Add missing terminator to ast_event_subscribe to fix a crash.
[asterisk-bristuff.git] / channels / chan_dahdi.c
blob640df5599f25d677d97a09bd06ac3231763679dd
1 /*
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.
19 /*! \file
21 * \brief DAHDI for Pseudo TDM
23 * \author Mark Spencer <markster@digium.com>
25 * Connects to the DAHDI telephony library as well as
26 * libpri. Libpri is optional and needed only if you are
27 * going to use ISDN connections.
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
32 * \par See also
33 * \arg \ref Config_dahdi
35 * \ingroup channel_drivers
37 * \todo Deprecate the "musiconhold" configuration option post 1.4
40 /*** MODULEINFO
41 <depend>res_smdi</depend>
42 <depend>dahdi</depend>
43 <depend>tonezone</depend>
44 <use>pri</use>
45 <use>ss7</use>
46 ***/
48 #include "asterisk.h"
50 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
52 #ifdef __NetBSD__
53 #include <pthread.h>
54 #include <signal.h>
55 #else
56 #include <sys/signal.h>
57 #endif
58 #include <sys/ioctl.h>
59 #include <math.h>
60 #include <ctype.h>
62 #include <dahdi/user.h>
63 #include <dahdi/tonezone.h>
65 #ifdef HAVE_PRI
66 #include <libpri.h>
67 #endif
69 #ifdef HAVE_SS7
70 #include <libss7.h>
71 #endif
73 #include "asterisk/lock.h"
74 #include "asterisk/channel.h"
75 #include "asterisk/config.h"
76 #include "asterisk/module.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/file.h"
79 #include "asterisk/ulaw.h"
80 #include "asterisk/alaw.h"
81 #include "asterisk/callerid.h"
82 #include "asterisk/adsi.h"
83 #include "asterisk/cli.h"
84 #include "asterisk/cdr.h"
85 #include "asterisk/features.h"
86 #include "asterisk/musiconhold.h"
87 #include "asterisk/say.h"
88 #include "asterisk/tdd.h"
89 #include "asterisk/app.h"
90 #include "asterisk/dsp.h"
91 #include "asterisk/astdb.h"
92 #include "asterisk/manager.h"
93 #include "asterisk/causes.h"
94 #include "asterisk/term.h"
95 #include "asterisk/utils.h"
96 #include "asterisk/transcap.h"
97 #include "asterisk/stringfields.h"
98 #include "asterisk/abstract_jb.h"
99 #include "asterisk/smdi.h"
100 #include "asterisk/astobj.h"
101 #include "asterisk/event.h"
102 #include "asterisk/devicestate.h"
104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
106 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
107 static const char *lbostr[] = {
108 "0 db (CSU)/0-133 feet (DSX-1)",
109 "133-266 feet (DSX-1)",
110 "266-399 feet (DSX-1)",
111 "399-533 feet (DSX-1)",
112 "533-655 feet (DSX-1)",
113 "-7.5db (CSU)",
114 "-15db (CSU)",
115 "-22.5db (CSU)"
117 #endif
119 /*! Global jitterbuffer configuration - by default, jb is disabled */
120 static struct ast_jb_conf default_jbconf =
122 .flags = 0,
123 .max_size = -1,
124 .resync_threshold = -1,
125 .impl = ""
127 static struct ast_jb_conf global_jbconf;
129 /* define this to send PRI user-user information elements */
130 #undef SUPPORT_USERUSER
132 /*!
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 */
143 /*! \note
144 * Define if you want to check the hook state for an FXO (FXS signalled) interface
145 * before dialing on it. Certain FXO interfaces always think they're out of
146 * service with this method however.
148 /* #define DAHDI_CHECK_HOOKSTATE */
150 /*! \brief Typically, how many rings before we should send Caller*ID */
151 #define DEFAULT_CIDRINGS 1
153 #define CHANNEL_PSEUDO -12
155 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
158 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
159 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
161 static const char tdesc[] = "DAHDI Telephony Driver"
162 #ifdef HAVE_PRI
163 " w/PRI"
164 #endif
165 #ifdef HAVE_SS7
166 " w/SS7"
167 #endif
170 static const char config[] = "chan_dahdi.conf";
172 #define SIG_EM DAHDI_SIG_EM
173 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
174 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
175 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
176 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
177 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
178 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
179 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
180 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
181 #define SIG_FXSLS DAHDI_SIG_FXSLS
182 #define SIG_FXSGS DAHDI_SIG_FXSGS
183 #define SIG_FXSKS DAHDI_SIG_FXSKS
184 #define SIG_FXOLS DAHDI_SIG_FXOLS
185 #define SIG_FXOGS DAHDI_SIG_FXOGS
186 #define SIG_FXOKS DAHDI_SIG_FXOKS
187 #define SIG_PRI DAHDI_SIG_CLEAR
188 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
189 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
190 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
191 #define SIG_SF DAHDI_SIG_SF
192 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
193 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
194 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
195 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
196 #define SIG_EM_E1 DAHDI_SIG_EM_E1
197 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
198 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
200 #ifdef LOTS_OF_SPANS
201 #define NUM_SPANS DAHDI_MAX_SPANS
202 #else
203 #define NUM_SPANS 32
204 #endif
205 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
206 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
208 #define CHAN_PSEUDO -2
210 #define DCHAN_PROVISIONED (1 << 0)
211 #define DCHAN_NOTINALARM (1 << 1)
212 #define DCHAN_UP (1 << 2)
214 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
216 /* Overlap dialing option types */
217 #define DAHDI_OVERLAPDIAL_NONE 0
218 #define DAHDI_OVERLAPDIAL_OUTGOING 1
219 #define DAHDI_OVERLAPDIAL_INCOMING 2
220 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
223 #define CALLPROGRESS_PROGRESS 1
224 #define CALLPROGRESS_FAX_OUTGOING 2
225 #define CALLPROGRESS_FAX_INCOMING 4
226 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
228 static char defaultcic[64] = "";
229 static char defaultozz[64] = "";
231 static char parkinglot[AST_MAX_EXTENSION] = ""; /*!< Default parking lot for this channel */
233 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
234 static char mwimonitornotify[PATH_MAX] = "";
235 static int mwisend_rpas = 0;
237 static char progzone[10] = "";
239 static int usedistinctiveringdetection = 0;
240 static int distinctiveringaftercid = 0;
242 static int numbufs = 4;
244 static int mwilevel = 512;
246 #ifdef HAVE_PRI
247 static struct ast_channel inuse;
248 #ifdef PRI_GETSET_TIMERS
249 static int pritimers[PRI_MAX_TIMERS];
250 #endif
251 static int pridebugfd = -1;
252 static char pridebugfilename[1024] = "";
253 #endif
255 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
256 static int firstdigittimeout = 16000;
258 /*! \brief How long to wait for following digits (FXO logic) */
259 static int gendigittimeout = 8000;
261 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
262 static int matchdigittimeout = 3000;
264 /*! \brief Protect the interface list (of dahdi_pvt's) */
265 AST_MUTEX_DEFINE_STATIC(iflock);
268 static int ifcount = 0;
270 #ifdef HAVE_PRI
271 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
272 #endif
274 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
275 when it's doing something critical. */
276 AST_MUTEX_DEFINE_STATIC(monlock);
278 /*! \brief This is the thread for the monitor which checks for input on the channels
279 which are not currently in use. */
280 static pthread_t monitor_thread = AST_PTHREADT_NULL;
282 static int restart_monitor(void);
284 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
286 static int dahdi_sendtext(struct ast_channel *c, const char *text);
288 static void mwi_event_cb(const struct ast_event *event, void *userdata)
290 /* This module does not handle MWI in an event-based manner. However, it
291 * subscribes to MWI for each mailbox that is configured so that the core
292 * knows that we care about it. Then, chan_dahdi will get the MWI from the
293 * event cache instead of checking the mailbox directly. */
296 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
297 static inline int dahdi_get_event(int fd)
299 int j;
300 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
301 return -1;
302 return j;
305 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
306 static inline int dahdi_wait_event(int fd)
308 int i, j = 0;
309 i = DAHDI_IOMUX_SIGEVENT;
310 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
311 return -1;
312 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
313 return -1;
314 return j;
317 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
318 #define READ_SIZE 160
320 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
321 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
323 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
324 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
325 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
326 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
327 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
329 struct dahdi_pvt;
331 static int ringt_base = DEFAULT_RINGT;
333 #ifdef HAVE_SS7
335 #define LINKSTATE_INALARM (1 << 0)
336 #define LINKSTATE_STARTING (1 << 1)
337 #define LINKSTATE_UP (1 << 2)
338 #define LINKSTATE_DOWN (1 << 3)
340 #define SS7_NAI_DYNAMIC -1
342 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
344 struct dahdi_ss7 {
345 pthread_t master; /*!< Thread of master */
346 ast_mutex_t lock;
347 int fds[NUM_DCHANS];
348 int numsigchans;
349 int linkstate[NUM_DCHANS];
350 int numchans;
351 int type;
352 enum {
353 LINKSET_STATE_DOWN = 0,
354 LINKSET_STATE_UP
355 } state;
356 char called_nai; /*!< Called Nature of Address Indicator */
357 char calling_nai; /*!< Calling Nature of Address Indicator */
358 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
359 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
360 char subscriberprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
361 char unknownprefix[20]; /*!< for unknown dialplans */
362 struct ss7 *ss7;
363 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
364 int flags; /*!< Linkset flags */
367 static struct dahdi_ss7 linksets[NUM_SPANS];
369 static int cur_ss7type = -1;
370 static int cur_linkset = -1;
371 static int cur_pointcode = -1;
372 static int cur_cicbeginswith = -1;
373 static int cur_adjpointcode = -1;
374 static int cur_networkindicator = -1;
375 static int cur_defaultdpc = -1;
376 #endif /* HAVE_SS7 */
378 #ifdef HAVE_PRI
380 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
381 #define PRI_CHANNEL(p) ((p) & 0xff)
382 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
383 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
385 struct dahdi_pri {
386 pthread_t master; /*!< Thread of master */
387 ast_mutex_t lock; /*!< Mutex */
388 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
389 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
390 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
391 int minunused; /*!< Min # of channels to keep empty */
392 int minidle; /*!< Min # of "idling" calls to keep active */
393 int nodetype; /*!< Node type */
394 int switchtype; /*!< Type of switch to emulate */
395 int nsf; /*!< Network-Specific Facilities */
396 int dialplan; /*!< Dialing plan */
397 int localdialplan; /*!< Local dialing plan */
398 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
399 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
400 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
401 char privateprefix[20]; /*!< for private dialplans */
402 char unknownprefix[20]; /*!< for unknown dialplans */
403 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
404 int trunkgroup; /*!< What our trunkgroup is */
405 int mastertrunkgroup; /*!< What trunk group is our master */
406 int prilogicalspan; /*!< Logical span number within trunk group */
407 int numchans; /*!< Num of channels we represent */
408 int overlapdial; /*!< In overlap dialing mode */
409 int facilityenable; /*!< Enable facility IEs */
410 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
411 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
412 struct pri *pri; /*!< Currently active D-channel */
413 int debug;
414 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
415 int offset;
416 int span;
417 int resetting;
418 int resetpos;
419 #ifdef HAVE_PRI_INBANDRELEASE
420 unsigned int inbandrelease:1; /*!< Should we support inband audio after receiving RELEASE? */
421 #endif
422 time_t lastreset; /*!< time when unused channels were last reset */
423 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
424 int sig;
425 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
426 struct dahdi_pvt *crvs; /*!< Member CRV structs */
427 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
431 static struct dahdi_pri pris[NUM_SPANS];
433 #if 0
434 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
435 #else
436 #define DEFAULT_PRI_DEBUG 0
437 #endif
439 static inline void pri_rel(struct dahdi_pri *pri)
441 ast_mutex_unlock(&pri->lock);
444 #else
445 /*! Shut up the compiler */
446 struct dahdi_pri;
447 #endif
449 #define SUB_REAL 0 /*!< Active call */
450 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
451 #define SUB_THREEWAY 2 /*!< Three-way call */
453 /* Polarity states */
454 #define POLARITY_IDLE 0
455 #define POLARITY_REV 1
458 struct distRingData {
459 int ring[3];
460 int range;
462 struct ringContextData {
463 char contextData[AST_MAX_CONTEXT];
465 struct dahdi_distRings {
466 struct distRingData ringnum[3];
467 struct ringContextData ringContext[3];
470 static char *subnames[] = {
471 "Real",
472 "Callwait",
473 "Threeway"
476 struct dahdi_subchannel {
477 int zfd;
478 struct ast_channel *owner;
479 int chan;
480 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
481 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
482 unsigned int needringing:1;
483 unsigned int needbusy:1;
484 unsigned int needcongestion:1;
485 unsigned int needcallerid:1;
486 unsigned int needanswer:1;
487 unsigned int needflash:1;
488 unsigned int needhold:1;
489 unsigned int needunhold:1;
490 unsigned int linear:1;
491 unsigned int inthreeway:1;
492 DAHDI_CONFINFO curconf;
495 #define CONF_USER_REAL (1 << 0)
496 #define CONF_USER_THIRDCALL (1 << 1)
498 #define MAX_SLAVES 4
500 static struct dahdi_pvt {
501 ast_mutex_t lock;
502 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
503 /*!< Up to three channels can be associated with this call */
505 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
506 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
507 struct dahdi_confinfo saveconf; /*!< Saved conference info */
509 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
510 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
511 int inconference; /*!< If our real should be in the conference */
513 int sig; /*!< Signalling style */
514 int radio; /*!< radio type */
515 int outsigmod; /*!< Outbound Signalling style (modifier) */
516 int oprmode; /*!< "Operator Services" mode */
517 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
518 float cid_rxgain; /*!< "Gain to apply during caller id */
519 float rxgain;
520 float txgain;
521 int tonezone; /*!< tone zone for this chan, or -1 for default */
522 struct dahdi_pvt *next; /*!< Next channel in list */
523 struct dahdi_pvt *prev; /*!< Prev channel in list */
525 /* flags */
526 unsigned int adsi:1;
527 unsigned int answeronpolarityswitch:1;
528 unsigned int busydetect:1;
529 unsigned int callreturn:1;
530 unsigned int callwaiting:1;
531 unsigned int callwaitingcallerid:1;
532 unsigned int cancallforward:1;
533 unsigned int canpark:1;
534 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
535 unsigned int destroy:1;
536 unsigned int didtdd:1; /*!< flag to say its done it once */
537 unsigned int dialednone:1;
538 unsigned int dialing:1;
539 unsigned int digital:1;
540 unsigned int dnd:1;
541 unsigned int echobreak:1;
542 unsigned int echocanbridged:1;
543 unsigned int echocanon:1;
544 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
545 unsigned int firstradio:1;
546 unsigned int hanguponpolarityswitch:1;
547 unsigned int hardwaredtmf:1;
548 unsigned int hidecallerid:1;
549 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
550 unsigned int ignoredtmf:1;
551 unsigned int immediate:1; /*!< Answer before getting digits? */
552 unsigned int inalarm:1;
553 unsigned int mate:1; /*!< flag to say its in MATE mode */
554 unsigned int outgoing:1;
555 /* unsigned int overlapdial:1; unused and potentially confusing */
556 unsigned int permcallwaiting:1;
557 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
558 unsigned int priindication_oob:1;
559 unsigned int priexclusive:1;
560 unsigned int pulse:1;
561 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
562 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
563 unsigned int threewaycalling:1;
564 unsigned int transfer:1;
565 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
566 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
567 unsigned int usedistinctiveringdetection:1;
568 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
569 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
570 unsigned int mwimonitor_neon:1; /*!< monitor this FXO port for neon type MWI indication from other end */
571 unsigned int mwimonitor_fsk:1; /*!< monitor this FXO port for fsk MWI indication from other end */
572 unsigned int mwimonitoractive:1; /*!< an MWI monitor thread is currently active */
573 unsigned int mwisendactive:1; /*!< a MWI message sending thread is active */
574 /* Channel state or unavilability flags */
575 unsigned int inservice:1;
576 unsigned int locallyblocked:1;
577 unsigned int remotelyblocked:1;
578 #if defined(HAVE_PRI) || defined(HAVE_SS7)
579 unsigned int rlt:1;
580 unsigned int alerting:1;
581 unsigned int alreadyhungup:1;
582 unsigned int isidlecall:1;
583 unsigned int proceeding:1;
584 unsigned int progress:1;
585 unsigned int resetting:1;
586 unsigned int setup_ack:1;
587 #endif
588 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
589 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
591 struct dahdi_distRings drings;
593 char context[AST_MAX_CONTEXT];
594 char defcontext[AST_MAX_CONTEXT];
595 char exten[AST_MAX_EXTENSION];
596 char language[MAX_LANGUAGE];
597 char mohinterpret[MAX_MUSICCLASS];
598 char mohsuggest[MAX_MUSICCLASS];
599 char parkinglot[AST_MAX_EXTENSION]; /*!< Parking lot for this channel */
600 #if defined(PRI_ANI) || defined(HAVE_SS7)
601 char cid_ani[AST_MAX_EXTENSION];
602 #endif
603 int cid_ani2;
604 char cid_num[AST_MAX_EXTENSION];
605 int cid_ton; /*!< Type Of Number (TON) */
606 char cid_name[AST_MAX_EXTENSION];
607 char lastcid_num[AST_MAX_EXTENSION];
608 char lastcid_name[AST_MAX_EXTENSION];
609 char *origcid_num; /*!< malloced original callerid */
610 char *origcid_name; /*!< malloced original callerid */
611 char callwait_num[AST_MAX_EXTENSION];
612 char callwait_name[AST_MAX_EXTENSION];
613 char rdnis[AST_MAX_EXTENSION];
614 char dnid[AST_MAX_EXTENSION];
615 ast_group_t group;
616 int law;
617 int confno; /*!< Our conference */
618 int confusers; /*!< Who is using our conference */
619 int propconfno; /*!< Propagated conference number */
620 ast_group_t callgroup;
621 ast_group_t pickupgroup;
622 struct ast_variable *vars;
623 int channel; /*!< Channel Number or CRV */
624 int span; /*!< Span number */
625 time_t guardtime; /*!< Must wait this much time before using for new call */
626 int cid_signalling; /*!< CID signalling type bell202 or v23 */
627 int cid_start; /*!< CID start indicator, polarity or ring */
628 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
629 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
630 int cidcwexpire; /*!< When to expire our muting for CID/CW */
631 unsigned char *cidspill;
632 int cidpos;
633 int cidlen;
634 int ringt;
635 int ringt_base;
636 int stripmsd;
637 int callwaitcas;
638 int callwaitrings;
639 struct {
640 struct dahdi_echocanparams head;
641 struct dahdi_echocanparam params[DAHDI_MAX_ECHOCANPARAMS];
642 } echocancel;
643 int echotraining;
644 char echorest[20];
645 int busycount;
646 int busy_tonelength;
647 int busy_quietlength;
648 int callprogress;
649 struct timeval flashtime; /*!< Last flash-hook time */
650 struct ast_dsp *dsp;
651 int cref; /*!< Call reference number */
652 DAHDI_DIAL_OPERATION dop;
653 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
654 char finaldial[64];
655 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
656 int amaflags; /*!< AMA Flags */
657 struct tdd_state *tdd; /*!< TDD flag */
658 char call_forward[AST_MAX_EXTENSION];
659 char mailbox[AST_MAX_EXTENSION];
660 struct ast_event_sub *mwi_event_sub;
661 char dialdest[256];
662 int onhooktime;
663 int msgstate;
664 int distinctivering; /*!< Which distinctivering to use */
665 int cidrings; /*!< Which ring to deliver CID on */
666 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
667 int fake_event;
668 int polarityonanswerdelay;
669 struct timeval polaritydelaytv;
670 int sendcalleridafter;
671 #ifdef HAVE_PRI
672 struct dahdi_pri *pri;
673 struct dahdi_pvt *bearer;
674 struct dahdi_pvt *realcall;
675 q931_call *call;
676 int prioffset;
677 int logicalspan;
678 #endif
679 int polarity;
680 int dsp_features;
681 #ifdef HAVE_SS7
682 struct dahdi_ss7 *ss7;
683 struct isup_call *ss7call;
684 char charge_number[50];
685 char gen_add_number[50];
686 char gen_dig_number[50];
687 char orig_called_num[50];
688 char redirecting_num[50];
689 char generic_name[50];
690 unsigned char gen_add_num_plan;
691 unsigned char gen_add_nai;
692 unsigned char gen_add_pres_ind;
693 unsigned char gen_add_type;
694 unsigned char gen_dig_type;
695 unsigned char gen_dig_scheme;
696 char jip_number[50];
697 unsigned char lspi_type;
698 unsigned char lspi_scheme;
699 unsigned char lspi_context;
700 char lspi_ident[50];
701 unsigned int call_ref_ident;
702 unsigned int call_ref_pc;
703 unsigned char calling_party_cat;
704 int transcap;
705 int cic; /*!< CIC associated with channel */
706 unsigned int dpc; /*!< CIC's DPC */
707 unsigned int loopedback:1;
708 #endif
709 char begindigit;
710 int muting;
711 } *iflist = NULL, *ifend = NULL;
713 /*! \brief Channel configuration from chan_dahdi.conf .
714 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
715 * Generally there is a field here for every possible configuration item.
717 * The state of fields is saved along the parsing and whenever a 'channel'
718 * statement is reached, the current dahdi_chan_conf is used to configure the
719 * channel (struct dahdi_pvt)
721 * \see dahdi_chan_init for the default values.
723 struct dahdi_chan_conf {
724 struct dahdi_pvt chan;
725 #ifdef HAVE_PRI
726 struct dahdi_pri pri;
727 #endif
729 #ifdef HAVE_SS7
730 struct dahdi_ss7 ss7;
731 #endif
732 DAHDI_PARAMS timing;
733 int is_sig_auto; /*!< Use channel signalling from DAHDI? */
735 char smdi_port[SMDI_MAX_FILENAME_LEN];
738 /*! returns a new dahdi_chan_conf with default values (by-value) */
739 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
740 /* recall that if a field is not included here it is initialized
741 * to 0 or equivalent
743 struct dahdi_chan_conf conf = {
744 #ifdef HAVE_PRI
745 .pri = {
746 .nsf = PRI_NSF_NONE,
747 .switchtype = PRI_SWITCH_NI2,
748 .dialplan = PRI_UNKNOWN + 1,
749 .localdialplan = PRI_NATIONAL_ISDN + 1,
750 .nodetype = PRI_CPE,
752 .minunused = 2,
753 .idleext = "",
754 .idledial = "",
755 .internationalprefix = "",
756 .nationalprefix = "",
757 .localprefix = "",
758 .privateprefix = "",
759 .unknownprefix = "",
760 .resetinterval = -1,
762 #endif
763 #ifdef HAVE_SS7
764 .ss7 = {
765 .called_nai = SS7_NAI_NATIONAL,
766 .calling_nai = SS7_NAI_NATIONAL,
767 .internationalprefix = "",
768 .nationalprefix = "",
769 .subscriberprefix = "",
770 .unknownprefix = ""
772 #endif
773 .chan = {
774 .context = "default",
775 .cid_num = "",
776 .cid_name = "",
777 .mohinterpret = "default",
778 .mohsuggest = "",
779 .parkinglot = "",
780 .transfertobusy = 1,
782 .cid_signalling = CID_SIG_BELL,
783 .cid_start = CID_START_RING,
784 .dahditrcallerid = 0,
785 .use_callerid = 1,
786 .sig = -1,
787 .outsigmod = -1,
789 .cid_rxgain = +5.0,
791 .tonezone = -1,
793 .echocancel.head.tap_length = 1,
795 .busycount = 3,
797 .accountcode = "",
799 .mailbox = "",
802 .polarityonanswerdelay = 600,
804 .sendcalleridafter = DEFAULT_CIDRINGS
806 .timing = {
807 .prewinktime = -1,
808 .preflashtime = -1,
809 .winktime = -1,
810 .flashtime = -1,
811 .starttime = -1,
812 .rxwinktime = -1,
813 .rxflashtime = -1,
814 .debouncetime = -1
816 .is_sig_auto = 1,
817 .smdi_port = "/dev/ttyS0",
820 return conf;
824 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
825 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
826 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
827 static int dahdi_sendtext(struct ast_channel *c, const char *text);
828 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
829 static int dahdi_hangup(struct ast_channel *ast);
830 static int dahdi_answer(struct ast_channel *ast);
831 static struct ast_frame *dahdi_read(struct ast_channel *ast);
832 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
833 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
834 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
835 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
836 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
837 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
838 static int handle_init_event(struct dahdi_pvt *i, int event);
840 static const struct ast_channel_tech dahdi_tech = {
841 .type = "DAHDI",
842 .description = tdesc,
843 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
844 .requester = dahdi_request,
845 .send_digit_begin = dahdi_digit_begin,
846 .send_digit_end = dahdi_digit_end,
847 .send_text = dahdi_sendtext,
848 .call = dahdi_call,
849 .hangup = dahdi_hangup,
850 .answer = dahdi_answer,
851 .read = dahdi_read,
852 .write = dahdi_write,
853 .bridge = dahdi_bridge,
854 .exception = dahdi_exception,
855 .indicate = dahdi_indicate,
856 .fixup = dahdi_fixup,
857 .setoption = dahdi_setoption,
858 .func_channel_read = dahdi_func_read,
861 #ifdef HAVE_PRI
862 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
863 #else
864 #define GET_CHANNEL(p) ((p)->channel)
865 #endif
867 struct dahdi_pvt *round_robin[32];
869 #ifdef HAVE_PRI
870 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
872 int res;
873 /* Grab the lock first */
874 do {
875 res = ast_mutex_trylock(&pri->lock);
876 if (res) {
877 DEADLOCK_AVOIDANCE(&pvt->lock);
879 } while (res);
880 /* Then break the poll */
881 pthread_kill(pri->master, SIGURG);
882 return 0;
884 #endif
886 #ifdef HAVE_SS7
887 static inline void ss7_rel(struct dahdi_ss7 *ss7)
889 ast_mutex_unlock(&ss7->lock);
892 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
894 int res;
895 /* Grab the lock first */
896 do {
897 res = ast_mutex_trylock(&pri->lock);
898 if (res) {
899 DEADLOCK_AVOIDANCE(&pvt->lock);
901 } while (res);
902 /* Then break the poll */
903 pthread_kill(pri->master, SIGURG);
904 return 0;
906 #endif
907 #define NUM_CADENCE_MAX 25
908 static int num_cadence = 4;
909 static int user_has_defined_cadences = 0;
911 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
912 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
913 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
914 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
915 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
918 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
919 * is 1, the second pause is 2 and so on.
922 static int cidrings[NUM_CADENCE_MAX] = {
923 2, /*!< Right after first long ring */
924 4, /*!< Right after long part */
925 3, /*!< After third chirp */
926 2, /*!< Second spell */
929 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
930 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
932 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
933 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
935 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
936 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
938 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
940 int res;
941 if (p->subs[0].owner == ast)
942 res = 0;
943 else if (p->subs[1].owner == ast)
944 res = 1;
945 else if (p->subs[2].owner == ast)
946 res = 2;
947 else {
948 res = -1;
949 if (!nullok)
950 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
952 return res;
955 #ifdef HAVE_PRI
956 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
957 #else
958 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
959 #endif
961 #ifdef HAVE_PRI
962 if (pri)
963 ast_mutex_unlock(&pri->lock);
964 #endif
965 for (;;) {
966 if (p->subs[a].owner) {
967 if (ast_channel_trylock(p->subs[a].owner)) {
968 DEADLOCK_AVOIDANCE(&p->lock);
969 } else {
970 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
971 ast_channel_unlock(p->subs[a].owner);
972 break;
974 } else
975 break;
977 #ifdef HAVE_PRI
978 if (pri)
979 ast_mutex_lock(&pri->lock);
980 #endif
983 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
985 #ifdef HAVE_PRI
986 struct dahdi_pri *pri = (struct dahdi_pri*) data;
987 #endif
988 #ifdef HAVE_SS7
989 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
990 #endif
991 /* We must unlock the PRI to avoid the possibility of a deadlock */
992 #if defined(HAVE_PRI) || defined(HAVE_SS7)
993 if (data) {
994 switch (p->sig) {
995 #ifdef HAVE_PRI
996 case SIG_BRI:
997 case SIG_BRI_PTMP:
998 case SIG_PRI:
999 ast_mutex_unlock(&pri->lock);
1000 break;
1001 #endif
1002 #ifdef HAVE_SS7
1003 case SIG_SS7:
1004 ast_mutex_unlock(&ss7->lock);
1005 break;
1006 #endif
1007 default:
1008 break;
1011 #endif
1012 for (;;) {
1013 if (p->owner) {
1014 if (ast_channel_trylock(p->owner)) {
1015 DEADLOCK_AVOIDANCE(&p->lock);
1016 } else {
1017 ast_queue_frame(p->owner, f);
1018 ast_channel_unlock(p->owner);
1019 break;
1021 } else
1022 break;
1024 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1025 if (data) {
1026 switch (p->sig) {
1027 #ifdef HAVE_PRI
1028 case SIG_BRI:
1029 case SIG_BRI_PTMP:
1030 case SIG_PRI:
1031 ast_mutex_lock(&pri->lock);
1032 break;
1033 #endif
1034 #ifdef HAVE_SS7
1035 case SIG_SS7:
1036 ast_mutex_lock(&ss7->lock);
1037 break;
1038 #endif
1039 default:
1040 break;
1044 #endif
1047 static int restore_gains(struct dahdi_pvt *p);
1049 static void swap_subs(struct dahdi_pvt *p, int a, int b)
1051 int tchan;
1052 int tinthreeway;
1053 struct ast_channel *towner;
1055 ast_debug(1, "Swapping %d and %d\n", a, b);
1057 tchan = p->subs[a].chan;
1058 towner = p->subs[a].owner;
1059 tinthreeway = p->subs[a].inthreeway;
1061 p->subs[a].chan = p->subs[b].chan;
1062 p->subs[a].owner = p->subs[b].owner;
1063 p->subs[a].inthreeway = p->subs[b].inthreeway;
1065 p->subs[b].chan = tchan;
1066 p->subs[b].owner = towner;
1067 p->subs[b].inthreeway = tinthreeway;
1069 if (p->subs[a].owner)
1070 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].zfd);
1071 if (p->subs[b].owner)
1072 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].zfd);
1073 wakeup_sub(p, a, NULL);
1074 wakeup_sub(p, b, NULL);
1077 static int dahdi_open(char *fn)
1079 int fd;
1080 int isnum;
1081 int chan = 0;
1082 int bs;
1083 int x;
1084 isnum = 1;
1085 for (x = 0; x < strlen(fn); x++) {
1086 if (!isdigit(fn[x])) {
1087 isnum = 0;
1088 break;
1091 if (isnum) {
1092 chan = atoi(fn);
1093 if (chan < 1) {
1094 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
1095 return -1;
1097 fn = "/dev/dahdi/channel";
1099 fd = open(fn, O_RDWR | O_NONBLOCK);
1100 if (fd < 0) {
1101 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
1102 return -1;
1104 if (chan) {
1105 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
1106 x = errno;
1107 close(fd);
1108 errno = x;
1109 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
1110 return -1;
1113 bs = READ_SIZE;
1114 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
1115 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
1116 x = errno;
1117 close(fd);
1118 errno = x;
1119 return -1;
1121 return fd;
1124 static void dahdi_close(int fd)
1126 if (fd > 0)
1127 close(fd);
1130 static int dahdi_setlinear(int zfd, int linear)
1132 int res;
1133 res = ioctl(zfd, DAHDI_SETLINEAR, &linear);
1134 if (res)
1135 return res;
1136 return 0;
1140 static int alloc_sub(struct dahdi_pvt *p, int x)
1142 DAHDI_BUFFERINFO bi;
1143 int res;
1144 if (p->subs[x].zfd >= 0) {
1145 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
1146 return -1;
1149 p->subs[x].zfd = dahdi_open("/dev/dahdi/pseudo");
1150 if (p->subs[x].zfd <= -1) {
1151 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
1152 return -1;
1155 res = ioctl(p->subs[x].zfd, DAHDI_GET_BUFINFO, &bi);
1156 if (!res) {
1157 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
1158 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
1159 bi.numbufs = numbufs;
1160 res = ioctl(p->subs[x].zfd, DAHDI_SET_BUFINFO, &bi);
1161 if (res < 0) {
1162 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
1164 } else
1165 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
1167 if (ioctl(p->subs[x].zfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
1168 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].zfd, strerror(errno));
1169 dahdi_close(p->subs[x].zfd);
1170 p->subs[x].zfd = -1;
1171 return -1;
1173 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
1174 return 0;
1177 static int unalloc_sub(struct dahdi_pvt *p, int x)
1179 if (!x) {
1180 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
1181 return -1;
1183 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
1184 if (p->subs[x].zfd > -1) {
1185 dahdi_close(p->subs[x].zfd);
1187 p->subs[x].zfd = -1;
1188 p->subs[x].linear = 0;
1189 p->subs[x].chan = 0;
1190 p->subs[x].owner = NULL;
1191 p->subs[x].inthreeway = 0;
1192 p->polarity = POLARITY_IDLE;
1193 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
1194 return 0;
1197 static int digit_to_dtmfindex(char digit)
1199 if (isdigit(digit))
1200 return DAHDI_TONE_DTMF_BASE + (digit - '0');
1201 else if (digit >= 'A' && digit <= 'D')
1202 return DAHDI_TONE_DTMF_A + (digit - 'A');
1203 else if (digit >= 'a' && digit <= 'd')
1204 return DAHDI_TONE_DTMF_A + (digit - 'a');
1205 else if (digit == '*')
1206 return DAHDI_TONE_DTMF_s;
1207 else if (digit == '#')
1208 return DAHDI_TONE_DTMF_p;
1209 else
1210 return -1;
1213 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1215 struct dahdi_pvt *pvt;
1216 int index;
1217 int dtmf = -1;
1219 pvt = chan->tech_pvt;
1221 ast_mutex_lock(&pvt->lock);
1223 index = dahdi_get_index(chan, pvt, 0);
1225 if ((index != SUB_REAL) || !pvt->owner)
1226 goto out;
1228 #ifdef HAVE_PRI
1229 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
1230 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1231 if (pvt->setup_ack) {
1232 if (!pri_grab(pvt, pvt->pri)) {
1233 pri_information(pvt->pri->pri, pvt->call, digit);
1234 pri_rel(pvt->pri);
1235 } else
1236 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1237 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1238 int res;
1239 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1240 res = strlen(pvt->dialdest);
1241 pvt->dialdest[res++] = digit;
1242 pvt->dialdest[res] = '\0';
1244 goto out;
1246 #endif
1247 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1248 goto out;
1250 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_SENDTONE, &dtmf)) {
1251 int res;
1252 DAHDI_DIAL_OPERATION zo = {
1253 .op = DAHDI_DIAL_OP_APPEND,
1256 zo.dialstr[0] = 'T';
1257 zo.dialstr[1] = digit;
1258 zo.dialstr[2] = '\0';
1259 if ((res = ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_DIAL, &zo)))
1260 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1261 else
1262 pvt->dialing = 1;
1263 } else {
1264 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
1265 pvt->dialing = 1;
1266 pvt->begindigit = digit;
1269 out:
1270 ast_mutex_unlock(&pvt->lock);
1272 return 0;
1275 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1277 struct dahdi_pvt *pvt;
1278 int res = 0;
1279 int index;
1280 int x;
1282 pvt = chan->tech_pvt;
1284 ast_mutex_lock(&pvt->lock);
1286 index = dahdi_get_index(chan, pvt, 0);
1288 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1289 goto out;
1291 #ifdef HAVE_PRI
1292 /* This means that the digit was already sent via PRI signalling */
1293 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
1294 && !pvt->begindigit)
1295 goto out;
1296 #endif
1298 if (pvt->begindigit) {
1299 x = -1;
1300 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
1301 res = ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_SENDTONE, &x);
1302 pvt->dialing = 0;
1303 pvt->begindigit = 0;
1306 out:
1307 ast_mutex_unlock(&pvt->lock);
1309 return res;
1312 static char *events[] = {
1313 "No event",
1314 "On hook",
1315 "Ring/Answered",
1316 "Wink/Flash",
1317 "Alarm",
1318 "No more alarm",
1319 "HDLC Abort",
1320 "HDLC Overrun",
1321 "HDLC Bad FCS",
1322 "Dial Complete",
1323 "Ringer On",
1324 "Ringer Off",
1325 "Hook Transition Complete",
1326 "Bits Changed",
1327 "Pulse Start",
1328 "Timer Expired",
1329 "Timer Ping",
1330 "Polarity Reversal",
1331 "Ring Begin",
1334 static struct {
1335 int alarm;
1336 char *name;
1337 } alarms[] = {
1338 { DAHDI_ALARM_RED, "Red Alarm" },
1339 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1340 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1341 { DAHDI_ALARM_RECOVER, "Recovering" },
1342 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1343 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1344 { DAHDI_ALARM_NONE, "None" },
1347 static char *alarm2str(int alarm)
1349 int x;
1350 for (x = 0; x < ARRAY_LEN(alarms); x++) {
1351 if (alarms[x].alarm & alarm)
1352 return alarms[x].name;
1354 return alarm ? "Unknown Alarm" : "No Alarm";
1357 static char *event2str(int event)
1359 static char buf[256];
1360 if ((event < (ARRAY_LEN(events))) && (event > -1))
1361 return events[event];
1362 sprintf(buf, "Event %d", event); /* safe */
1363 return buf;
1366 #ifdef HAVE_PRI
1367 static char *dialplan2str(int dialplan)
1369 if (dialplan == -1 || dialplan == -2) {
1370 return("Dynamically set dialplan in ISDN");
1372 return (pri_plan2str(dialplan));
1374 #endif
1376 static char *dahdi_sig2str(int sig)
1378 static char buf[256];
1379 switch (sig) {
1380 case SIG_EM:
1381 return "E & M Immediate";
1382 case SIG_EMWINK:
1383 return "E & M Wink";
1384 case SIG_EM_E1:
1385 return "E & M E1";
1386 case SIG_FEATD:
1387 return "Feature Group D (DTMF)";
1388 case SIG_FEATDMF:
1389 return "Feature Group D (MF)";
1390 case SIG_FEATDMF_TA:
1391 return "Feature Groud D (MF) Tandem Access";
1392 case SIG_FEATB:
1393 return "Feature Group B (MF)";
1394 case SIG_E911:
1395 return "E911 (MF)";
1396 case SIG_FGC_CAMA:
1397 return "FGC/CAMA (Dialpulse)";
1398 case SIG_FGC_CAMAMF:
1399 return "FGC/CAMA (MF)";
1400 case SIG_FXSLS:
1401 return "FXS Loopstart";
1402 case SIG_FXSGS:
1403 return "FXS Groundstart";
1404 case SIG_FXSKS:
1405 return "FXS Kewlstart";
1406 case SIG_FXOLS:
1407 return "FXO Loopstart";
1408 case SIG_FXOGS:
1409 return "FXO Groundstart";
1410 case SIG_FXOKS:
1411 return "FXO Kewlstart";
1412 case SIG_PRI:
1413 return "ISDN PRI";
1414 case SIG_BRI:
1415 return "ISDN BRI Point to Point";
1416 case SIG_BRI_PTMP:
1417 return "ISDN BRI Point to MultiPoint";
1418 case SIG_SS7:
1419 return "SS7";
1420 case SIG_SF:
1421 return "SF (Tone) Immediate";
1422 case SIG_SFWINK:
1423 return "SF (Tone) Wink";
1424 case SIG_SF_FEATD:
1425 return "SF (Tone) with Feature Group D (DTMF)";
1426 case SIG_SF_FEATDMF:
1427 return "SF (Tone) with Feature Group D (MF)";
1428 case SIG_SF_FEATB:
1429 return "SF (Tone) with Feature Group B (MF)";
1430 case SIG_GR303FXOKS:
1431 return "GR-303 with FXOKS";
1432 case SIG_GR303FXSKS:
1433 return "GR-303 with FXSKS";
1434 case 0:
1435 return "Pseudo";
1436 default:
1437 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1438 return buf;
1442 #define sig2str dahdi_sig2str
1444 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1446 /* If the conference already exists, and we're already in it
1447 don't bother doing anything */
1448 DAHDI_CONFINFO zi;
1450 memset(&zi, 0, sizeof(zi));
1451 zi.chan = 0;
1453 if (slavechannel > 0) {
1454 /* If we have only one slave, do a digital mon */
1455 zi.confmode = DAHDI_CONF_DIGITALMON;
1456 zi.confno = slavechannel;
1457 } else {
1458 if (!index) {
1459 /* Real-side and pseudo-side both participate in conference */
1460 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1461 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1462 } else
1463 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1464 zi.confno = p->confno;
1466 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1467 return 0;
1468 if (c->zfd < 0)
1469 return 0;
1470 if (ioctl(c->zfd, DAHDI_SETCONF, &zi)) {
1471 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->zfd, zi.confmode, zi.confno, strerror(errno));
1472 return -1;
1474 if (slavechannel < 1) {
1475 p->confno = zi.confno;
1477 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1478 ast_debug(1, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
1479 return 0;
1482 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1484 /* If they're listening to our channel, they're ours */
1485 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1486 return 1;
1487 /* If they're a talker on our (allocated) conference, they're ours */
1488 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1489 return 1;
1490 return 0;
1493 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1495 DAHDI_CONFINFO zi;
1496 if (/* Can't delete if there's no zfd */
1497 (c->zfd < 0) ||
1498 /* Don't delete from the conference if it's not our conference */
1499 !isourconf(p, c)
1500 /* Don't delete if we don't think it's conferenced at all (implied) */
1501 ) return 0;
1502 memset(&zi, 0, sizeof(zi));
1503 zi.chan = 0;
1504 zi.confno = 0;
1505 zi.confmode = 0;
1506 if (ioctl(c->zfd, DAHDI_SETCONF, &zi)) {
1507 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->zfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1508 return -1;
1510 ast_debug(1, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
1511 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1512 return 0;
1515 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1517 int x;
1518 int useslavenative;
1519 struct dahdi_pvt *slave = NULL;
1520 /* Start out optimistic */
1521 useslavenative = 1;
1522 /* Update conference state in a stateless fashion */
1523 for (x = 0; x < 3; x++) {
1524 /* Any three-way calling makes slave native mode *definitely* out
1525 of the question */
1526 if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway)
1527 useslavenative = 0;
1529 /* If we don't have any 3-way calls, check to see if we have
1530 precisely one slave */
1531 if (useslavenative) {
1532 for (x = 0; x < MAX_SLAVES; x++) {
1533 if (p->slaves[x]) {
1534 if (slave) {
1535 /* Whoops already have a slave! No
1536 slave native and stop right away */
1537 slave = NULL;
1538 useslavenative = 0;
1539 break;
1540 } else {
1541 /* We have one slave so far */
1542 slave = p->slaves[x];
1547 /* If no slave, slave native definitely out */
1548 if (!slave)
1549 useslavenative = 0;
1550 else if (slave->law != p->law) {
1551 useslavenative = 0;
1552 slave = NULL;
1554 if (out)
1555 *out = slave;
1556 return useslavenative;
1559 static int reset_conf(struct dahdi_pvt *p)
1561 DAHDI_CONFINFO zi;
1562 memset(&zi, 0, sizeof(zi));
1563 p->confno = -1;
1564 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1565 if (p->subs[SUB_REAL].zfd > -1) {
1566 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCONF, &zi))
1567 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1569 return 0;
1572 static int update_conf(struct dahdi_pvt *p)
1574 int needconf = 0;
1575 int x;
1576 int useslavenative;
1577 struct dahdi_pvt *slave = NULL;
1579 useslavenative = isslavenative(p, &slave);
1580 /* Start with the obvious, general stuff */
1581 for (x = 0; x < 3; x++) {
1582 /* Look for three way calls */
1583 if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway) {
1584 conf_add(p, &p->subs[x], x, 0);
1585 needconf++;
1586 } else {
1587 conf_del(p, &p->subs[x], x);
1590 /* If we have a slave, add him to our conference now. or DAX
1591 if this is slave native */
1592 for (x = 0; x < MAX_SLAVES; x++) {
1593 if (p->slaves[x]) {
1594 if (useslavenative)
1595 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1596 else {
1597 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1598 needconf++;
1602 /* If we're supposed to be in there, do so now */
1603 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1604 if (useslavenative)
1605 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1606 else {
1607 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1608 needconf++;
1611 /* If we have a master, add ourselves to his conference */
1612 if (p->master) {
1613 if (isslavenative(p->master, NULL)) {
1614 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1615 } else {
1616 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1619 if (!needconf) {
1620 /* Nobody is left (or should be left) in our conference.
1621 Kill it. */
1622 p->confno = -1;
1624 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1625 return 0;
1628 static void dahdi_enable_ec(struct dahdi_pvt *p)
1630 int x;
1631 int res;
1632 if (!p)
1633 return;
1634 if (p->echocanon) {
1635 ast_debug(1, "Echo cancellation already on\n");
1636 return;
1638 if (p->digital) {
1639 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
1640 return;
1642 if (p->echocancel.head.tap_length) {
1643 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
1644 x = 1;
1645 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &x);
1646 if (res)
1647 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1649 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
1650 if (res) {
1651 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1652 } else {
1653 p->echocanon = 1;
1654 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
1656 } else
1657 ast_debug(1, "No echo cancellation requested\n");
1660 static void dahdi_train_ec(struct dahdi_pvt *p)
1662 int x;
1663 int res;
1665 if (p && p->echocanon && p->echotraining) {
1666 x = p->echotraining;
1667 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOTRAIN, &x);
1668 if (res)
1669 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1670 else
1671 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
1672 } else {
1673 ast_debug(1, "No echo training requested\n");
1677 static void dahdi_disable_ec(struct dahdi_pvt *p)
1679 int res;
1681 if (p->echocanon) {
1682 struct dahdi_echocanparams ecp = { .tap_length = 0 };
1684 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
1686 if (res)
1687 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1688 else
1689 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
1692 p->echocanon = 0;
1695 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
1697 int j;
1698 int k;
1699 float linear_gain = pow(10.0, gain / 20.0);
1701 switch (law) {
1702 case DAHDI_LAW_ALAW:
1703 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
1704 if (gain) {
1705 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1706 if (k > 32767) k = 32767;
1707 if (k < -32767) k = -32767;
1708 g->txgain[j] = AST_LIN2A(k);
1709 } else {
1710 g->txgain[j] = j;
1713 break;
1714 case DAHDI_LAW_MULAW:
1715 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
1716 if (gain) {
1717 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1718 if (k > 32767) k = 32767;
1719 if (k < -32767) k = -32767;
1720 g->txgain[j] = AST_LIN2MU(k);
1721 } else {
1722 g->txgain[j] = j;
1725 break;
1729 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
1731 int j;
1732 int k;
1733 float linear_gain = pow(10.0, gain / 20.0);
1735 switch (law) {
1736 case DAHDI_LAW_ALAW:
1737 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
1738 if (gain) {
1739 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1740 if (k > 32767) k = 32767;
1741 if (k < -32767) k = -32767;
1742 g->rxgain[j] = AST_LIN2A(k);
1743 } else {
1744 g->rxgain[j] = j;
1747 break;
1748 case DAHDI_LAW_MULAW:
1749 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
1750 if (gain) {
1751 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1752 if (k > 32767) k = 32767;
1753 if (k < -32767) k = -32767;
1754 g->rxgain[j] = AST_LIN2MU(k);
1755 } else {
1756 g->rxgain[j] = j;
1759 break;
1763 static int set_actual_txgain(int fd, int chan, float gain, int law)
1765 struct dahdi_gains g;
1766 int res;
1768 memset(&g, 0, sizeof(g));
1769 g.chan = chan;
1770 res = ioctl(fd, DAHDI_GETGAINS, &g);
1771 if (res) {
1772 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
1773 return res;
1776 fill_txgain(&g, gain, law);
1778 return ioctl(fd, DAHDI_SETGAINS, &g);
1781 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1783 struct dahdi_gains g;
1784 int res;
1786 memset(&g, 0, sizeof(g));
1787 g.chan = chan;
1788 res = ioctl(fd, DAHDI_GETGAINS, &g);
1789 if (res) {
1790 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
1791 return res;
1794 fill_rxgain(&g, gain, law);
1796 return ioctl(fd, DAHDI_SETGAINS, &g);
1799 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1801 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1804 static int bump_gains(struct dahdi_pvt *p)
1806 int res;
1808 /* Bump receive gain by value stored in cid_rxgain */
1809 res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
1810 if (res) {
1811 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1812 return -1;
1815 return 0;
1818 static int restore_gains(struct dahdi_pvt *p)
1820 int res;
1822 res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
1823 if (res) {
1824 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1825 return -1;
1828 return 0;
1831 static inline int dahdi_set_hook(int fd, int hs)
1833 int x, res;
1835 x = hs;
1836 res = ioctl(fd, DAHDI_HOOK, &x);
1838 if (res < 0) {
1839 if (errno == EINPROGRESS)
1840 return 0;
1841 ast_log(LOG_WARNING, "DAHDI hook failed: %s\n", strerror(errno));
1844 return res;
1847 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1849 int x, y, res;
1850 x = muted;
1851 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
1852 y = 1;
1853 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &y);
1854 if (res)
1855 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1857 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_CONFMUTE, &x);
1858 if (res < 0)
1859 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1860 return res;
1863 static int save_conference(struct dahdi_pvt *p)
1865 struct dahdi_confinfo c;
1866 int res;
1867 if (p->saveconf.confmode) {
1868 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1869 return -1;
1871 p->saveconf.chan = 0;
1872 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GETCONF, &p->saveconf);
1873 if (res) {
1874 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1875 p->saveconf.confmode = 0;
1876 return -1;
1878 c.chan = 0;
1879 c.confno = 0;
1880 c.confmode = DAHDI_CONF_NORMAL;
1881 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCONF, &c);
1882 if (res) {
1883 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1884 return -1;
1886 ast_debug(1, "Disabled conferencing\n");
1887 return 0;
1891 * \brief Send MWI state change
1893 * \arg mailbox_full This is the mailbox associated with the FXO line that the
1894 * MWI state has changed on.
1895 * \arg thereornot This argument should simply be set to 1 or 0, to indicate
1896 * whether there are messages waiting or not.
1898 * \return nothing
1900 * This function does two things:
1902 * 1) It generates an internal Asterisk event notifying any other module that
1903 * cares about MWI that the state of a mailbox has changed.
1905 * 2) It runs the script specified by the mwimonitornotify option to allow
1906 * some custom handling of the state change.
1908 static void notify_message(char *mailbox_full, int thereornot)
1910 char s[sizeof(mwimonitornotify) + 80];
1911 struct ast_event *event;
1912 char *mailbox, *context;
1914 /* Strip off @default */
1915 context = mailbox = ast_strdupa(mailbox_full);
1916 strsep(&context, "@");
1917 if (ast_strlen_zero(context))
1918 context = "default";
1920 if (!(event = ast_event_new(AST_EVENT_MWI,
1921 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
1922 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
1923 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
1924 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
1925 AST_EVENT_IE_END))) {
1926 return;
1929 ast_event_queue_and_cache(event,
1930 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
1931 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
1932 AST_EVENT_IE_END);
1934 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
1935 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
1936 ast_safe_system(s);
1940 static int restore_conference(struct dahdi_pvt *p)
1942 int res;
1943 if (p->saveconf.confmode) {
1944 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCONF, &p->saveconf);
1945 p->saveconf.confmode = 0;
1946 if (res) {
1947 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1948 return -1;
1951 ast_debug(1, "Restored conferencing\n");
1952 return 0;
1955 static int send_callerid(struct dahdi_pvt *p);
1957 static int send_cwcidspill(struct dahdi_pvt *p)
1959 p->callwaitcas = 0;
1960 p->cidcwexpire = 0;
1961 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1962 return -1;
1963 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1964 /* Make sure we account for the end */
1965 p->cidlen += READ_SIZE * 4;
1966 p->cidpos = 0;
1967 send_callerid(p);
1968 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1969 return 0;
1972 static int has_voicemail(struct dahdi_pvt *p)
1974 int new_msgs;
1975 struct ast_event *event;
1976 char *mailbox, *context;
1978 mailbox = context = ast_strdupa(p->mailbox);
1979 strsep(&context, "@");
1980 if (ast_strlen_zero(context))
1981 context = "default";
1983 event = ast_event_get_cached(AST_EVENT_MWI,
1984 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
1985 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
1986 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
1987 AST_EVENT_IE_END);
1989 if (event) {
1990 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
1991 ast_event_destroy(event);
1992 } else
1993 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
1995 return new_msgs;
1998 static int send_callerid(struct dahdi_pvt *p)
2000 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
2001 int res;
2002 /* Take out of linear mode if necessary */
2003 if (p->subs[SUB_REAL].linear) {
2004 p->subs[SUB_REAL].linear = 0;
2005 dahdi_setlinear(p->subs[SUB_REAL].zfd, 0);
2007 while (p->cidpos < p->cidlen) {
2008 res = write(p->subs[SUB_REAL].zfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
2009 if (res < 0) {
2010 if (errno == EAGAIN)
2011 return 0;
2012 else {
2013 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
2014 return -1;
2017 if (!res)
2018 return 0;
2019 p->cidpos += res;
2021 ast_free(p->cidspill);
2022 p->cidspill = NULL;
2023 if (p->callwaitcas) {
2024 /* Wait for CID/CW to expire */
2025 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
2026 } else
2027 restore_conference(p);
2028 return 0;
2031 static int dahdi_callwait(struct ast_channel *ast)
2033 struct dahdi_pvt *p = ast->tech_pvt;
2034 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
2035 if (p->cidspill) {
2036 ast_log(LOG_WARNING, "Spill already exists?!?\n");
2037 ast_free(p->cidspill);
2039 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
2040 return -1;
2041 save_conference(p);
2042 /* Silence */
2043 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
2044 if (!p->callwaitrings && p->callwaitingcallerid) {
2045 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
2046 p->callwaitcas = 1;
2047 p->cidlen = 2400 + 680 + READ_SIZE * 4;
2048 } else {
2049 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
2050 p->callwaitcas = 0;
2051 p->cidlen = 2400 + READ_SIZE * 4;
2053 p->cidpos = 0;
2054 send_callerid(p);
2056 return 0;
2059 #ifdef HAVE_SS7
2060 static unsigned char cid_pres2ss7pres(int cid_pres)
2062 return (cid_pres >> 5) & 0x03;
2065 static unsigned char cid_pres2ss7screen(int cid_pres)
2067 return cid_pres & 0x03;
2069 #endif
2071 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
2073 struct dahdi_pvt *p = ast->tech_pvt;
2074 int x, res, index,mysig;
2075 char *c, *n, *l;
2076 #ifdef HAVE_PRI
2077 char *s = NULL;
2078 #endif
2079 char dest[256]; /* must be same length as p->dialdest */
2080 ast_mutex_lock(&p->lock);
2081 ast_copy_string(dest, rdest, sizeof(dest));
2082 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
2083 if ((ast->_state == AST_STATE_BUSY)) {
2084 p->subs[SUB_REAL].needbusy = 1;
2085 ast_mutex_unlock(&p->lock);
2086 return 0;
2088 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
2089 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
2090 ast_mutex_unlock(&p->lock);
2091 return -1;
2093 p->dialednone = 0;
2094 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
2096 /* Special pseudo -- automatically up */
2097 ast_setstate(ast, AST_STATE_UP);
2098 ast_mutex_unlock(&p->lock);
2099 return 0;
2101 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
2102 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_FLUSH, &x);
2103 if (res)
2104 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
2105 p->outgoing = 1;
2107 set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
2109 mysig = p->sig;
2110 if (p->outsigmod > -1)
2111 mysig = p->outsigmod;
2113 switch (mysig) {
2114 case SIG_FXOLS:
2115 case SIG_FXOGS:
2116 case SIG_FXOKS:
2117 if (p->owner == ast) {
2118 /* Normal ring, on hook */
2120 /* Don't send audio while on hook, until the call is answered */
2121 p->dialing = 1;
2122 if (p->use_callerid) {
2123 /* Generate the Caller-ID spill if desired */
2124 if (p->cidspill) {
2125 ast_log(LOG_WARNING, "cidspill already exists??\n");
2126 ast_free(p->cidspill);
2128 p->callwaitcas = 0;
2129 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
2130 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
2131 p->cidpos = 0;
2132 send_callerid(p);
2135 /* Choose proper cadence */
2136 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2137 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2138 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
2139 p->cidrings = cidrings[p->distinctivering - 1];
2140 } else {
2141 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, NULL))
2142 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
2143 p->cidrings = p->sendcalleridafter;
2146 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
2147 c = strchr(dest, '/');
2148 if (c)
2149 c++;
2150 if (c && (strlen(c) < p->stripmsd)) {
2151 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2152 c = NULL;
2154 if (c) {
2155 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2156 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
2157 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
2158 } else {
2159 p->dop.dialstr[0] = '\0';
2161 x = DAHDI_RING;
2162 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
2163 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
2164 ast_mutex_unlock(&p->lock);
2165 return -1;
2167 p->dialing = 1;
2168 } else {
2169 /* Call waiting call */
2170 p->callwaitrings = 0;
2171 if (ast->cid.cid_num)
2172 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
2173 else
2174 p->callwait_num[0] = '\0';
2175 if (ast->cid.cid_name)
2176 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
2177 else
2178 p->callwait_name[0] = '\0';
2179 /* Call waiting tone instead */
2180 if (dahdi_callwait(ast)) {
2181 ast_mutex_unlock(&p->lock);
2182 return -1;
2184 /* Make ring-back */
2185 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].zfd, DAHDI_TONE_RINGTONE))
2186 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
2189 n = ast->cid.cid_name;
2190 l = ast->cid.cid_num;
2191 if (l)
2192 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
2193 else
2194 p->lastcid_num[0] = '\0';
2195 if (n)
2196 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
2197 else
2198 p->lastcid_name[0] = '\0';
2199 ast_setstate(ast, AST_STATE_RINGING);
2200 index = dahdi_get_index(ast, p, 0);
2201 if (index > -1) {
2202 p->subs[index].needringing = 1;
2204 break;
2205 case SIG_FXSLS:
2206 case SIG_FXSGS:
2207 case SIG_FXSKS:
2208 case SIG_EMWINK:
2209 case SIG_EM:
2210 case SIG_EM_E1:
2211 case SIG_FEATD:
2212 case SIG_FEATDMF:
2213 case SIG_E911:
2214 case SIG_FGC_CAMA:
2215 case SIG_FGC_CAMAMF:
2216 case SIG_FEATB:
2217 case SIG_SFWINK:
2218 case SIG_SF:
2219 case SIG_SF_FEATD:
2220 case SIG_SF_FEATDMF:
2221 case SIG_FEATDMF_TA:
2222 case SIG_SF_FEATB:
2223 c = strchr(dest, '/');
2224 if (c)
2225 c++;
2226 else
2227 c = "";
2228 if (strlen(c) < p->stripmsd) {
2229 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2230 ast_mutex_unlock(&p->lock);
2231 return -1;
2233 #ifdef HAVE_PRI
2234 /* Start the trunk, if not GR-303 */
2235 if (!p->pri) {
2236 #endif
2237 x = DAHDI_START;
2238 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
2239 if (res < 0) {
2240 if (errno != EINPROGRESS) {
2241 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
2242 ast_mutex_unlock(&p->lock);
2243 return -1;
2246 #ifdef HAVE_PRI
2248 #endif
2249 ast_debug(1, "Dialing '%s'\n", c);
2250 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2252 c += p->stripmsd;
2254 switch (mysig) {
2255 case SIG_FEATD:
2256 l = ast->cid.cid_num;
2257 if (l)
2258 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
2259 else
2260 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
2261 break;
2262 case SIG_FEATDMF:
2263 l = ast->cid.cid_num;
2264 if (l)
2265 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
2266 else
2267 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
2268 break;
2269 case SIG_FEATDMF_TA:
2271 const char *cic, *ozz;
2273 /* If you have to go through a Tandem Access point you need to use this */
2274 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
2275 if (!ozz)
2276 ozz = defaultozz;
2277 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
2278 if (!cic)
2279 cic = defaultcic;
2280 if (!ozz || !cic) {
2281 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2282 ast_mutex_unlock(&p->lock);
2283 return -1;
2285 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
2286 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
2287 p->whichwink = 0;
2289 break;
2290 case SIG_E911:
2291 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2292 break;
2293 case SIG_FGC_CAMA:
2294 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2295 break;
2296 case SIG_FGC_CAMAMF:
2297 case SIG_FEATB:
2298 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2299 break;
2300 default:
2301 if (p->pulse)
2302 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2303 else
2304 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2305 break;
2308 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2309 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2310 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2311 p->echorest[sizeof(p->echorest) - 1] = '\0';
2312 p->echobreak = 1;
2313 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2314 } else
2315 p->echobreak = 0;
2316 if (!res) {
2317 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop)) {
2318 int saveerr = errno;
2320 x = DAHDI_ONHOOK;
2321 ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
2322 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2323 ast_mutex_unlock(&p->lock);
2324 return -1;
2326 } else
2327 ast_debug(1, "Deferring dialing...\n");
2329 p->dialing = 1;
2330 if (ast_strlen_zero(c))
2331 p->dialednone = 1;
2332 ast_setstate(ast, AST_STATE_DIALING);
2333 break;
2334 case 0:
2335 /* Special pseudo -- automatically up*/
2336 ast_setstate(ast, AST_STATE_UP);
2337 break;
2338 case SIG_PRI:
2339 case SIG_BRI:
2340 case SIG_BRI_PTMP:
2341 case SIG_SS7:
2342 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2343 p->dialdest[0] = '\0';
2344 break;
2345 default:
2346 ast_debug(1, "not yet implemented\n");
2347 ast_mutex_unlock(&p->lock);
2348 return -1;
2350 #ifdef HAVE_SS7
2351 if (p->ss7) {
2352 char ss7_called_nai;
2353 int called_nai_strip;
2354 char ss7_calling_nai;
2355 int calling_nai_strip;
2356 const char *charge_str = NULL;
2357 const char *gen_address = NULL;
2358 const char *gen_digits = NULL;
2359 const char *gen_dig_type = NULL;
2360 const char *gen_dig_scheme = NULL;
2361 const char *gen_name = NULL;
2362 const char *jip_digits = NULL;
2363 const char *lspi_ident = NULL;
2364 const char *rlt_flag = NULL;
2365 const char *call_ref_id = NULL;
2366 const char *call_ref_pc = NULL;
2367 const char *send_far = NULL;
2369 c = strchr(dest, '/');
2370 if (c)
2371 c++;
2372 else
2373 c = dest;
2375 if (!p->hidecallerid) {
2376 l = ast->cid.cid_num;
2377 } else {
2378 l = NULL;
2381 if (ss7_grab(p, p->ss7)) {
2382 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
2383 ast_mutex_unlock(&p->lock);
2384 return -1;
2386 p->digital = IS_DIGITAL(ast->transfercapability);
2387 p->ss7call = isup_new_call(p->ss7->ss7);
2389 if (!p->ss7call) {
2390 ss7_rel(p->ss7);
2391 ast_mutex_unlock(&p->lock);
2392 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
2393 return -1;
2396 called_nai_strip = 0;
2397 ss7_called_nai = p->ss7->called_nai;
2398 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
2399 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
2400 called_nai_strip = strlen(p->ss7->internationalprefix);
2401 ss7_called_nai = SS7_NAI_INTERNATIONAL;
2402 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
2403 called_nai_strip = strlen(p->ss7->nationalprefix);
2404 ss7_called_nai = SS7_NAI_NATIONAL;
2405 } else {
2406 ss7_called_nai = SS7_NAI_SUBSCRIBER;
2409 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
2411 calling_nai_strip = 0;
2412 ss7_calling_nai = p->ss7->calling_nai;
2413 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
2414 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
2415 calling_nai_strip = strlen(p->ss7->internationalprefix);
2416 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
2417 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
2418 calling_nai_strip = strlen(p->ss7->nationalprefix);
2419 ss7_calling_nai = SS7_NAI_NATIONAL;
2420 } else {
2421 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
2424 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
2425 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
2426 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
2428 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
2429 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
2431 ast_channel_lock(ast);
2432 /* Set the charge number if it is set */
2433 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
2434 if (charge_str)
2435 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
2437 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
2438 if (gen_address)
2439 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
2441 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
2442 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
2443 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
2444 if (gen_digits)
2445 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
2447 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
2448 if (gen_name)
2449 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
2451 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
2452 if (jip_digits)
2453 isup_set_jip_digits(p->ss7call, jip_digits);
2455 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
2456 if (lspi_ident)
2457 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
2459 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
2460 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
2461 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
2464 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
2465 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
2466 if (call_ref_id && call_ref_pc) {
2467 isup_set_callref(p->ss7call, atoi(call_ref_id),
2468 call_ref_pc ? atoi(call_ref_pc) : 0);
2471 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
2472 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
2473 (isup_far(p->ss7->ss7, p->ss7call));
2475 ast_channel_unlock(ast);
2477 isup_iam(p->ss7->ss7, p->ss7call);
2478 ast_setstate(ast, AST_STATE_DIALING);
2479 ss7_rel(p->ss7);
2481 #endif /* HAVE_SS7 */
2482 #ifdef HAVE_PRI
2483 if (p->pri) {
2484 struct pri_sr *sr;
2485 #ifdef SUPPORT_USERUSER
2486 const char *useruser;
2487 #endif
2488 int pridialplan;
2489 int dp_strip;
2490 int prilocaldialplan;
2491 int ldp_strip;
2492 int exclusive;
2493 const char *rr_str;
2494 int redirect_reason;
2496 c = strchr(dest, '/');
2497 if (c)
2498 c++;
2499 else
2500 c = dest;
2502 l = NULL;
2503 n = NULL;
2505 if (!p->hidecallerid) {
2506 l = ast->cid.cid_num;
2507 if (!p->hidecalleridname) {
2508 n = ast->cid.cid_name;
2512 if (strlen(c) < p->stripmsd) {
2513 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2514 ast_mutex_unlock(&p->lock);
2515 return -1;
2517 if (mysig != SIG_FXSKS) {
2518 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2519 s = strchr(c + p->stripmsd, 'w');
2520 if (s) {
2521 if (strlen(s) > 1)
2522 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2523 else
2524 p->dop.dialstr[0] = '\0';
2525 *s = '\0';
2526 } else {
2527 p->dop.dialstr[0] = '\0';
2530 if (pri_grab(p, p->pri)) {
2531 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2532 ast_mutex_unlock(&p->lock);
2533 return -1;
2535 if (!(p->call = pri_new_call(p->pri->pri))) {
2536 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2537 pri_rel(p->pri);
2538 ast_mutex_unlock(&p->lock);
2539 return -1;
2541 if (!(sr = pri_sr_new())) {
2542 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2543 pri_rel(p->pri);
2544 ast_mutex_unlock(&p->lock);
2546 if (p->bearer || (mysig == SIG_FXSKS)) {
2547 if (p->bearer) {
2548 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
2549 p->bearer->call = p->call;
2550 } else
2551 ast_debug(1, "I'm being setup with no bearer right now...\n");
2553 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2555 p->digital = IS_DIGITAL(ast->transfercapability);
2556 /* Add support for exclusive override */
2557 if (p->priexclusive)
2558 exclusive = 1;
2559 else {
2560 /* otherwise, traditional behavior */
2561 if (p->pri->nodetype == PRI_NETWORK)
2562 exclusive = 0;
2563 else
2564 exclusive = 1;
2567 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2568 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2569 (p->digital ? -1 :
2570 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2571 if (p->pri->facilityenable)
2572 pri_facility_enable(p->pri->pri);
2574 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2575 dp_strip = 0;
2576 pridialplan = p->pri->dialplan - 1;
2577 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
2578 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2579 if (pridialplan == -2) {
2580 dp_strip = strlen(p->pri->internationalprefix);
2582 pridialplan = PRI_INTERNATIONAL_ISDN;
2583 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2584 if (pridialplan == -2) {
2585 dp_strip = strlen(p->pri->nationalprefix);
2587 pridialplan = PRI_NATIONAL_ISDN;
2588 } else {
2589 pridialplan = PRI_LOCAL_ISDN;
2592 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
2593 switch (c[p->stripmsd]) {
2594 case 'U':
2595 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
2596 break;
2597 case 'I':
2598 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
2599 break;
2600 case 'N':
2601 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
2602 break;
2603 case 'L':
2604 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
2605 break;
2606 case 'S':
2607 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
2608 break;
2609 case 'V':
2610 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
2611 break;
2612 case 'R':
2613 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
2614 break;
2615 case 'u':
2616 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
2617 break;
2618 case 'e':
2619 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
2620 break;
2621 case 'x':
2622 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
2623 break;
2624 case 'f':
2625 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
2626 break;
2627 case 'n':
2628 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
2629 break;
2630 case 'p':
2631 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
2632 break;
2633 case 'r':
2634 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
2635 break;
2636 default:
2637 if (isalpha(*c))
2638 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
2640 c++;
2642 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2644 ldp_strip = 0;
2645 prilocaldialplan = p->pri->localdialplan - 1;
2646 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
2647 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2648 if (prilocaldialplan == -2) {
2649 ldp_strip = strlen(p->pri->internationalprefix);
2651 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2652 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2653 if (prilocaldialplan == -2) {
2654 ldp_strip = strlen(p->pri->nationalprefix);
2656 prilocaldialplan = PRI_NATIONAL_ISDN;
2657 } else {
2658 prilocaldialplan = PRI_LOCAL_ISDN;
2661 if (l != NULL) {
2662 while (*l > '9' && *l != '*' && *l != '#') {
2663 switch (*l) {
2664 case 'U':
2665 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
2666 break;
2667 case 'I':
2668 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
2669 break;
2670 case 'N':
2671 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
2672 break;
2673 case 'L':
2674 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
2675 break;
2676 case 'S':
2677 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
2678 break;
2679 case 'V':
2680 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
2681 break;
2682 case 'R':
2683 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
2684 break;
2685 case 'u':
2686 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
2687 break;
2688 case 'e':
2689 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
2690 break;
2691 case 'x':
2692 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
2693 break;
2694 case 'f':
2695 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
2696 break;
2697 case 'n':
2698 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
2699 break;
2700 case 'p':
2701 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
2702 break;
2703 case 'r':
2704 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
2705 break;
2706 default:
2707 if (isalpha(*l))
2708 ast_log(LOG_WARNING, "Unrecognized prilocaldialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
2710 l++;
2713 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2714 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2715 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2716 if (!strcasecmp(rr_str, "UNKNOWN"))
2717 redirect_reason = 0;
2718 else if (!strcasecmp(rr_str, "BUSY"))
2719 redirect_reason = 1;
2720 else if (!strcasecmp(rr_str, "NO_REPLY"))
2721 redirect_reason = 2;
2722 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2723 redirect_reason = 15;
2724 else
2725 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2726 } else
2727 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2728 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2730 #ifdef SUPPORT_USERUSER
2731 /* User-user info */
2732 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2734 if (useruser)
2735 pri_sr_set_useruser(sr, useruser);
2736 #endif
2738 if (pri_setup(p->pri->pri, p->call, sr)) {
2739 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2740 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2741 pri_rel(p->pri);
2742 ast_mutex_unlock(&p->lock);
2743 pri_sr_free(sr);
2744 return -1;
2746 pri_sr_free(sr);
2747 ast_setstate(ast, AST_STATE_DIALING);
2748 pri_rel(p->pri);
2750 #endif
2751 ast_mutex_unlock(&p->lock);
2752 return 0;
2755 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2757 struct dahdi_pvt *p = *pvt;
2758 /* Remove channel from the list */
2759 if (p->prev)
2760 p->prev->next = p->next;
2761 if (p->next)
2762 p->next->prev = p->prev;
2763 if (p->use_smdi)
2764 ast_smdi_interface_unref(p->smdi_iface);
2765 if (p->mwi_event_sub)
2766 ast_event_unsubscribe(p->mwi_event_sub);
2767 if (p->vars)
2768 ast_variables_destroy(p->vars);
2769 ast_mutex_destroy(&p->lock);
2770 ast_free(p);
2771 *pvt = NULL;
2774 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2776 int owned = 0;
2777 int i = 0;
2779 if (!now) {
2780 if (cur->owner) {
2781 owned = 1;
2784 for (i = 0; i < 3; i++) {
2785 if (cur->subs[i].owner) {
2786 owned = 1;
2789 if (!owned) {
2790 if (prev) {
2791 prev->next = cur->next;
2792 if (prev->next)
2793 prev->next->prev = prev;
2794 else
2795 ifend = prev;
2796 } else {
2797 iflist = cur->next;
2798 if (iflist)
2799 iflist->prev = NULL;
2800 else
2801 ifend = NULL;
2803 if (cur->subs[SUB_REAL].zfd > -1) {
2804 dahdi_close(cur->subs[SUB_REAL].zfd);
2806 destroy_dahdi_pvt(&cur);
2808 } else {
2809 if (prev) {
2810 prev->next = cur->next;
2811 if (prev->next)
2812 prev->next->prev = prev;
2813 else
2814 ifend = prev;
2815 } else {
2816 iflist = cur->next;
2817 if (iflist)
2818 iflist->prev = NULL;
2819 else
2820 ifend = NULL;
2822 if (cur->subs[SUB_REAL].zfd > -1) {
2823 dahdi_close(cur->subs[SUB_REAL].zfd);
2825 destroy_dahdi_pvt(&cur);
2827 return 0;
2830 #ifdef HAVE_PRI
2831 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2833 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2835 static char *dahdi_send_keypad_facility_descrip =
2836 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2837 " IE over the current channel.\n";
2839 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2841 /* Data will be our digit string */
2842 struct dahdi_pvt *p;
2843 char *digits = (char *) data;
2845 if (ast_strlen_zero(digits)) {
2846 ast_debug(1, "No digit string sent to application!\n");
2847 return -1;
2850 p = (struct dahdi_pvt *)chan->tech_pvt;
2852 if (!p) {
2853 ast_debug(1, "Unable to find technology private\n");
2854 return -1;
2857 ast_mutex_lock(&p->lock);
2859 if (!p->pri || !p->call) {
2860 ast_debug(1, "Unable to find pri or call on channel!\n");
2861 ast_mutex_unlock(&p->lock);
2862 return -1;
2865 if (!pri_grab(p, p->pri)) {
2866 pri_keypad_facility(p->pri->pri, p->call, digits);
2867 pri_rel(p->pri);
2868 } else {
2869 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
2870 ast_mutex_unlock(&p->lock);
2871 return -1;
2874 ast_mutex_unlock(&p->lock);
2876 return 0;
2879 static int pri_is_up(struct dahdi_pri *pri)
2881 int x;
2882 for (x = 0; x < NUM_DCHANS; x++) {
2883 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2884 return 1;
2886 return 0;
2889 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2891 bearer->owner = &inuse;
2892 bearer->realcall = crv;
2893 crv->subs[SUB_REAL].zfd = bearer->subs[SUB_REAL].zfd;
2894 if (crv->subs[SUB_REAL].owner)
2895 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].zfd);
2896 crv->bearer = bearer;
2897 crv->call = bearer->call;
2898 crv->pri = pri;
2899 return 0;
2902 static char *pri_order(int level)
2904 switch (level) {
2905 case 0:
2906 return "Primary";
2907 case 1:
2908 return "Secondary";
2909 case 2:
2910 return "Tertiary";
2911 case 3:
2912 return "Quaternary";
2913 default:
2914 return "<Unknown>";
2918 /* Returns fd of the active dchan */
2919 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2921 int x = -1;
2923 for (x = 0; x < NUM_DCHANS; x++) {
2924 if ((pri->dchans[x] == pri->pri))
2925 break;
2928 return pri->fds[x];
2931 static int pri_find_dchan(struct dahdi_pri *pri)
2933 int oldslot = -1;
2934 struct pri *old;
2935 int newslot = -1;
2936 int x;
2937 old = pri->pri;
2938 for (x = 0; x < NUM_DCHANS; x++) {
2939 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2940 newslot = x;
2941 if (pri->dchans[x] == old) {
2942 oldslot = x;
2945 if (newslot < 0) {
2946 newslot = 0;
2947 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2948 pri->dchannels[newslot]);
2950 if (old && (oldslot != newslot))
2951 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2952 pri->dchannels[oldslot], pri->dchannels[newslot]);
2953 pri->pri = pri->dchans[newslot];
2954 return 0;
2956 #endif
2958 static int dahdi_hangup(struct ast_channel *ast)
2960 int res;
2961 int index,x, law;
2962 /*static int restore_gains(struct dahdi_pvt *p);*/
2963 struct dahdi_pvt *p = ast->tech_pvt;
2964 struct dahdi_pvt *tmp = NULL;
2965 struct dahdi_pvt *prev = NULL;
2966 DAHDI_PARAMS par;
2968 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
2969 if (!ast->tech_pvt) {
2970 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2971 return 0;
2974 ast_mutex_lock(&p->lock);
2976 index = dahdi_get_index(ast, p, 1);
2978 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
2979 x = 1;
2980 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2983 x = 0;
2984 dahdi_confmute(p, 0);
2985 p->muting = 0;
2986 restore_gains(p);
2987 if (p->origcid_num) {
2988 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2989 ast_free(p->origcid_num);
2990 p->origcid_num = NULL;
2992 if (p->origcid_name) {
2993 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2994 ast_free(p->origcid_name);
2995 p->origcid_name = NULL;
2997 if (p->dsp)
2998 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
2999 if (p->exten)
3000 p->exten[0] = '\0';
3002 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
3003 p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
3004 p->ignoredtmf = 0;
3006 if (index > -1) {
3007 /* Real channel, do some fixup */
3008 p->subs[index].owner = NULL;
3009 p->subs[index].needanswer = 0;
3010 p->subs[index].needflash = 0;
3011 p->subs[index].needringing = 0;
3012 p->subs[index].needbusy = 0;
3013 p->subs[index].needcongestion = 0;
3014 p->subs[index].linear = 0;
3015 p->subs[index].needcallerid = 0;
3016 p->polarity = POLARITY_IDLE;
3017 dahdi_setlinear(p->subs[index].zfd, 0);
3018 if (index == SUB_REAL) {
3019 if ((p->subs[SUB_CALLWAIT].zfd > -1) && (p->subs[SUB_THREEWAY].zfd > -1)) {
3020 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
3021 if (p->subs[SUB_CALLWAIT].inthreeway) {
3022 /* We had flipped over to answer a callwait and now it's gone */
3023 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
3024 /* Move to the call-wait, but un-own us until they flip back. */
3025 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3026 unalloc_sub(p, SUB_CALLWAIT);
3027 p->owner = NULL;
3028 } else {
3029 /* The three way hung up, but we still have a call wait */
3030 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
3031 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3032 unalloc_sub(p, SUB_THREEWAY);
3033 if (p->subs[SUB_REAL].inthreeway) {
3034 /* This was part of a three way call. Immediately make way for
3035 another call */
3036 ast_debug(1, "Call was complete, setting owner to former third call\n");
3037 p->owner = p->subs[SUB_REAL].owner;
3038 } else {
3039 /* This call hasn't been completed yet... Set owner to NULL */
3040 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3041 p->owner = NULL;
3043 p->subs[SUB_REAL].inthreeway = 0;
3045 } else if (p->subs[SUB_CALLWAIT].zfd > -1) {
3046 /* Move to the call-wait and switch back to them. */
3047 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3048 unalloc_sub(p, SUB_CALLWAIT);
3049 p->owner = p->subs[SUB_REAL].owner;
3050 if (p->owner->_state != AST_STATE_UP)
3051 p->subs[SUB_REAL].needanswer = 1;
3052 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
3053 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3054 } else if (p->subs[SUB_THREEWAY].zfd > -1) {
3055 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3056 unalloc_sub(p, SUB_THREEWAY);
3057 if (p->subs[SUB_REAL].inthreeway) {
3058 /* This was part of a three way call. Immediately make way for
3059 another call */
3060 ast_debug(1, "Call was complete, setting owner to former third call\n");
3061 p->owner = p->subs[SUB_REAL].owner;
3062 } else {
3063 /* This call hasn't been completed yet... Set owner to NULL */
3064 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3065 p->owner = NULL;
3067 p->subs[SUB_REAL].inthreeway = 0;
3069 } else if (index == SUB_CALLWAIT) {
3070 /* Ditch the holding callwait call, and immediately make it availabe */
3071 if (p->subs[SUB_CALLWAIT].inthreeway) {
3072 /* This is actually part of a three way, placed on hold. Place the third part
3073 on music on hold now */
3074 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3075 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
3076 S_OR(p->mohsuggest, NULL),
3077 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
3079 p->subs[SUB_THREEWAY].inthreeway = 0;
3080 /* Make it the call wait now */
3081 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
3082 unalloc_sub(p, SUB_THREEWAY);
3083 } else
3084 unalloc_sub(p, SUB_CALLWAIT);
3085 } else if (index == SUB_THREEWAY) {
3086 if (p->subs[SUB_CALLWAIT].inthreeway) {
3087 /* The other party of the three way call is currently in a call-wait state.
3088 Start music on hold for them, and take the main guy out of the third call */
3089 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
3090 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
3091 S_OR(p->mohsuggest, NULL),
3092 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
3094 p->subs[SUB_CALLWAIT].inthreeway = 0;
3096 p->subs[SUB_REAL].inthreeway = 0;
3097 /* If this was part of a three way call index, let us make
3098 another three way call */
3099 unalloc_sub(p, SUB_THREEWAY);
3100 } else {
3101 /* This wasn't any sort of call, but how are we an index? */
3102 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
3106 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
3107 p->owner = NULL;
3108 p->ringt = 0;
3109 p->distinctivering = 0;
3110 p->confirmanswer = 0;
3111 p->cidrings = 1;
3112 p->outgoing = 0;
3113 p->digital = 0;
3114 p->faxhandled = 0;
3115 p->pulsedial = 0;
3116 p->onhooktime = time(NULL);
3117 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3118 p->proceeding = 0;
3119 p->progress = 0;
3120 p->alerting = 0;
3121 p->setup_ack = 0;
3122 p->rlt = 0;
3123 #endif
3124 if (p->dsp) {
3125 ast_dsp_free(p->dsp);
3126 p->dsp = NULL;
3129 law = DAHDI_LAW_DEFAULT;
3130 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETLAW, &law);
3131 if (res < 0)
3132 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
3133 /* Perform low level hangup if no owner left */
3134 #ifdef HAVE_SS7
3135 if (p->ss7) {
3136 if (p->ss7call) {
3137 if (!ss7_grab(p, p->ss7)) {
3138 if (!p->alreadyhungup) {
3139 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
3140 int icause = ast->hangupcause ? ast->hangupcause : -1;
3142 if (cause) {
3143 if (atoi(cause))
3144 icause = atoi(cause);
3146 isup_rel(p->ss7->ss7, p->ss7call, icause);
3147 ss7_rel(p->ss7);
3148 p->alreadyhungup = 1;
3149 } else
3150 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
3151 } else {
3152 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
3153 res = -1;
3157 #endif
3158 #ifdef HAVE_PRI
3159 if (p->pri) {
3160 #ifdef SUPPORT_USERUSER
3161 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
3162 #endif
3164 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
3165 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
3166 if (!pri_grab(p, p->pri)) {
3167 if (p->alreadyhungup) {
3168 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
3170 #ifdef SUPPORT_USERUSER
3171 pri_call_set_useruser(p->call, useruser);
3172 #endif
3174 pri_hangup(p->pri->pri, p->call, -1);
3175 p->call = NULL;
3176 if (p->bearer)
3177 p->bearer->call = NULL;
3178 } else {
3179 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
3180 int icause = ast->hangupcause ? ast->hangupcause : -1;
3181 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
3183 #ifdef SUPPORT_USERUSER
3184 pri_call_set_useruser(p->call, useruser);
3185 #endif
3187 p->alreadyhungup = 1;
3188 if (p->bearer)
3189 p->bearer->alreadyhungup = 1;
3190 if (cause) {
3191 if (atoi(cause))
3192 icause = atoi(cause);
3194 pri_hangup(p->pri->pri, p->call, icause);
3196 if (res < 0)
3197 ast_log(LOG_WARNING, "pri_disconnect failed\n");
3198 pri_rel(p->pri);
3199 } else {
3200 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
3201 res = -1;
3203 } else {
3204 if (p->bearer)
3205 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
3206 p->call = NULL;
3207 res = 0;
3210 #endif
3211 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
3212 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
3213 if (res < 0) {
3214 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
3216 switch (p->sig) {
3217 case SIG_FXOGS:
3218 case SIG_FXOLS:
3219 case SIG_FXOKS:
3220 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &par);
3221 if (!res) {
3222 #if 0
3223 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
3224 #endif
3225 /* If they're off hook, try playing congestion */
3226 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
3227 tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
3228 else
3229 tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
3231 break;
3232 case SIG_FXSGS:
3233 case SIG_FXSLS:
3234 case SIG_FXSKS:
3235 /* Make sure we're not made available for at least two seconds assuming
3236 we were actually used for an inbound or outbound call. */
3237 if (ast->_state != AST_STATE_RESERVED) {
3238 time(&p->guardtime);
3239 p->guardtime += 2;
3241 break;
3242 default:
3243 tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
3245 if (p->cidspill)
3246 ast_free(p->cidspill);
3247 if (p->sig)
3248 dahdi_disable_ec(p);
3249 x = 0;
3250 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
3251 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
3252 p->didtdd = 0;
3253 p->cidspill = NULL;
3254 p->callwaitcas = 0;
3255 p->callwaiting = p->permcallwaiting;
3256 p->hidecallerid = p->permhidecallerid;
3257 p->dialing = 0;
3258 p->rdnis[0] = '\0';
3259 update_conf(p);
3260 reset_conf(p);
3261 /* Restore data mode */
3262 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
3263 x = 0;
3264 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
3266 #ifdef HAVE_PRI
3267 if (p->bearer) {
3268 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
3269 /* Free up the bearer channel as well, and
3270 don't use its file descriptor anymore */
3271 update_conf(p->bearer);
3272 reset_conf(p->bearer);
3273 p->bearer->owner = NULL;
3274 p->bearer->realcall = NULL;
3275 p->bearer = NULL;
3276 p->subs[SUB_REAL].zfd = -1;
3277 p->pri = NULL;
3279 #endif
3280 restart_monitor();
3283 p->callwaitingrepeat = 0;
3284 p->cidcwexpire = 0;
3285 p->oprmode = 0;
3286 ast->tech_pvt = NULL;
3287 ast_mutex_unlock(&p->lock);
3288 ast_module_unref(ast_module_info->self);
3289 ast_verb(3, "Hungup '%s'\n", ast->name);
3291 ast_mutex_lock(&iflock);
3292 tmp = iflist;
3293 prev = NULL;
3294 if (p->destroy) {
3295 while (tmp) {
3296 if (tmp == p) {
3297 destroy_channel(prev, tmp, 0);
3298 break;
3299 } else {
3300 prev = tmp;
3301 tmp = tmp->next;
3305 ast_mutex_unlock(&iflock);
3306 return 0;
3309 static int dahdi_answer(struct ast_channel *ast)
3311 struct dahdi_pvt *p = ast->tech_pvt;
3312 int res = 0;
3313 int index;
3314 int oldstate = ast->_state;
3315 ast_setstate(ast, AST_STATE_UP);
3316 ast_mutex_lock(&p->lock);
3317 index = dahdi_get_index(ast, p, 0);
3318 if (index < 0)
3319 index = SUB_REAL;
3320 /* nothing to do if a radio channel */
3321 if ((p->radio || (p->oprmode < 0))) {
3322 ast_mutex_unlock(&p->lock);
3323 return 0;
3325 switch (p->sig) {
3326 case SIG_FXSLS:
3327 case SIG_FXSGS:
3328 case SIG_FXSKS:
3329 p->ringt = 0;
3330 /* Fall through */
3331 case SIG_EM:
3332 case SIG_EM_E1:
3333 case SIG_EMWINK:
3334 case SIG_FEATD:
3335 case SIG_FEATDMF:
3336 case SIG_FEATDMF_TA:
3337 case SIG_E911:
3338 case SIG_FGC_CAMA:
3339 case SIG_FGC_CAMAMF:
3340 case SIG_FEATB:
3341 case SIG_SF:
3342 case SIG_SFWINK:
3343 case SIG_SF_FEATD:
3344 case SIG_SF_FEATDMF:
3345 case SIG_SF_FEATB:
3346 case SIG_FXOLS:
3347 case SIG_FXOGS:
3348 case SIG_FXOKS:
3349 /* Pick up the line */
3350 ast_debug(1, "Took %s off hook\n", ast->name);
3351 if (p->hanguponpolarityswitch) {
3352 p->polaritydelaytv = ast_tvnow();
3354 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
3355 tone_zone_play_tone(p->subs[index].zfd, -1);
3356 p->dialing = 0;
3357 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
3358 if (oldstate == AST_STATE_RINGING) {
3359 ast_debug(1, "Finally swapping real and threeway\n");
3360 tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, -1);
3361 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3362 p->owner = p->subs[SUB_REAL].owner;
3365 if (p->sig & __DAHDI_SIG_FXS) {
3366 dahdi_enable_ec(p);
3367 dahdi_train_ec(p);
3369 break;
3370 #ifdef HAVE_PRI
3371 case SIG_BRI:
3372 case SIG_BRI_PTMP:
3373 case SIG_PRI:
3374 /* Send a pri acknowledge */
3375 if (!pri_grab(p, p->pri)) {
3376 p->proceeding = 1;
3377 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
3378 pri_rel(p->pri);
3379 } else {
3380 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
3381 res = -1;
3383 break;
3384 #endif
3385 #ifdef HAVE_SS7
3386 case SIG_SS7:
3387 if (!ss7_grab(p, p->ss7)) {
3388 p->proceeding = 1;
3389 res = isup_anm(p->ss7->ss7, p->ss7call);
3390 ss7_rel(p->ss7);
3391 } else {
3392 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
3393 res = -1;
3395 break;
3396 #endif
3397 case 0:
3398 ast_mutex_unlock(&p->lock);
3399 return 0;
3400 default:
3401 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
3402 res = -1;
3404 ast_mutex_unlock(&p->lock);
3405 return res;
3408 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
3410 char *cp;
3411 signed char *scp;
3412 int x;
3413 int index;
3414 struct dahdi_pvt *p = chan->tech_pvt, *pp;
3415 struct oprmode *oprmode;
3418 /* all supported options require data */
3419 if (!data || (datalen < 1)) {
3420 errno = EINVAL;
3421 return -1;
3424 switch (option) {
3425 case AST_OPTION_TXGAIN:
3426 scp = (signed char *) data;
3427 index = dahdi_get_index(chan, p, 0);
3428 if (index < 0) {
3429 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
3430 return -1;
3432 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
3433 return set_actual_txgain(p->subs[index].zfd, 0, p->txgain + (float) *scp, p->law);
3434 case AST_OPTION_RXGAIN:
3435 scp = (signed char *) data;
3436 index = dahdi_get_index(chan, p, 0);
3437 if (index < 0) {
3438 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
3439 return -1;
3441 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
3442 return set_actual_rxgain(p->subs[index].zfd, 0, p->rxgain + (float) *scp, p->law);
3443 case AST_OPTION_TONE_VERIFY:
3444 if (!p->dsp)
3445 break;
3446 cp = (char *) data;
3447 switch (*cp) {
3448 case 1:
3449 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
3450 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
3451 break;
3452 case 2:
3453 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
3454 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
3455 break;
3456 default:
3457 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
3458 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
3459 break;
3461 break;
3462 case AST_OPTION_TDD:
3463 /* turn on or off TDD */
3464 cp = (char *) data;
3465 p->mate = 0;
3466 if (!*cp) { /* turn it off */
3467 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
3468 if (p->tdd)
3469 tdd_free(p->tdd);
3470 p->tdd = 0;
3471 break;
3473 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
3474 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
3475 dahdi_disable_ec(p);
3476 /* otherwise, turn it on */
3477 if (!p->didtdd) { /* if havent done it yet */
3478 unsigned char mybuf[41000], *buf;
3479 int size, res, fd, len;
3480 struct pollfd fds[1];
3482 buf = mybuf;
3483 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
3484 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
3485 len = 40000;
3486 index = dahdi_get_index(chan, p, 0);
3487 if (index < 0) {
3488 ast_log(LOG_WARNING, "No index in TDD?\n");
3489 return -1;
3491 fd = p->subs[index].zfd;
3492 while (len) {
3493 if (ast_check_hangup(chan))
3494 return -1;
3495 size = len;
3496 if (size > READ_SIZE)
3497 size = READ_SIZE;
3498 fds[0].fd = fd;
3499 fds[0].events = POLLPRI | POLLOUT;
3500 fds[0].revents = 0;
3501 res = poll(fds, 1, -1);
3502 if (!res) {
3503 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
3504 continue;
3506 /* if got exception */
3507 if (fds[0].revents & POLLPRI)
3508 return -1;
3509 if (!(fds[0].revents & POLLOUT)) {
3510 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
3511 continue;
3513 res = write(fd, buf, size);
3514 if (res != size) {
3515 if (res == -1) return -1;
3516 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
3517 break;
3519 len -= size;
3520 buf += size;
3522 p->didtdd = 1; /* set to have done it now */
3524 if (*cp == 2) { /* Mate mode */
3525 if (p->tdd)
3526 tdd_free(p->tdd);
3527 p->tdd = 0;
3528 p->mate = 1;
3529 break;
3531 if (!p->tdd) { /* if we dont have one yet */
3532 p->tdd = tdd_new(); /* allocate one */
3534 break;
3535 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
3536 if (!p->dsp)
3537 break;
3538 cp = (char *) data;
3539 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3540 *cp ? "ON" : "OFF", (int) *cp, chan->name);
3541 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
3542 break;
3543 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
3544 cp = (char *) data;
3545 if (!*cp) {
3546 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
3547 x = 0;
3548 dahdi_disable_ec(p);
3549 } else {
3550 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
3551 x = 1;
3553 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &x) == -1)
3554 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
3555 break;
3556 case AST_OPTION_OPRMODE: /* Operator services mode */
3557 oprmode = (struct oprmode *) data;
3558 pp = oprmode->peer->tech_pvt;
3559 p->oprmode = pp->oprmode = 0;
3560 /* setup peers */
3561 p->oprpeer = pp;
3562 pp->oprpeer = p;
3563 /* setup modes, if any */
3564 if (oprmode->mode)
3566 pp->oprmode = oprmode->mode;
3567 p->oprmode = -oprmode->mode;
3569 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
3570 oprmode->mode, chan->name,oprmode->peer->name);
3571 break;
3572 case AST_OPTION_ECHOCAN:
3573 cp = (char *) data;
3574 if (*cp) {
3575 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
3576 dahdi_enable_ec(p);
3577 } else {
3578 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
3579 dahdi_disable_ec(p);
3581 break;
3583 errno = 0;
3585 return 0;
3588 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
3590 struct dahdi_pvt *p = chan->tech_pvt;
3592 if (!strcasecmp(data, "rxgain")) {
3593 ast_mutex_lock(&p->lock);
3594 snprintf(buf, len, "%f", p->rxgain);
3595 ast_mutex_unlock(&p->lock);
3596 } else if (!strcasecmp(data, "txgain")) {
3597 ast_mutex_lock(&p->lock);
3598 snprintf(buf, len, "%f", p->txgain);
3599 ast_mutex_unlock(&p->lock);
3600 } else {
3601 ast_copy_string(buf, "", len);
3603 return 0;
3607 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3609 /* Unlink a specific slave or all slaves/masters from a given master */
3610 int x;
3611 int hasslaves;
3612 if (!master)
3613 return;
3614 if (needlock) {
3615 ast_mutex_lock(&master->lock);
3616 if (slave) {
3617 while (ast_mutex_trylock(&slave->lock)) {
3618 DEADLOCK_AVOIDANCE(&master->lock);
3622 hasslaves = 0;
3623 for (x = 0; x < MAX_SLAVES; x++) {
3624 if (master->slaves[x]) {
3625 if (!slave || (master->slaves[x] == slave)) {
3626 /* Take slave out of the conference */
3627 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3628 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3629 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3630 master->slaves[x]->master = NULL;
3631 master->slaves[x] = NULL;
3632 } else
3633 hasslaves = 1;
3635 if (!hasslaves)
3636 master->inconference = 0;
3638 if (!slave) {
3639 if (master->master) {
3640 /* Take master out of the conference */
3641 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3642 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3643 hasslaves = 0;
3644 for (x = 0; x < MAX_SLAVES; x++) {
3645 if (master->master->slaves[x] == master)
3646 master->master->slaves[x] = NULL;
3647 else if (master->master->slaves[x])
3648 hasslaves = 1;
3650 if (!hasslaves)
3651 master->master->inconference = 0;
3653 master->master = NULL;
3655 update_conf(master);
3656 if (needlock) {
3657 if (slave)
3658 ast_mutex_unlock(&slave->lock);
3659 ast_mutex_unlock(&master->lock);
3663 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3664 int x;
3665 if (!slave || !master) {
3666 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3667 return;
3669 for (x = 0; x < MAX_SLAVES; x++) {
3670 if (!master->slaves[x]) {
3671 master->slaves[x] = slave;
3672 break;
3675 if (x >= MAX_SLAVES) {
3676 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3677 master->slaves[MAX_SLAVES - 1] = slave;
3679 if (slave->master)
3680 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3681 slave->master = master;
3683 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3686 static void disable_dtmf_detect(struct dahdi_pvt *p)
3688 #ifdef DAHDI_TONEDETECT
3689 int val;
3690 #endif
3692 p->ignoredtmf = 1;
3694 #ifdef DAHDI_TONEDETECT
3695 val = 0;
3696 ioctl(p->subs[SUB_REAL].zfd, DAHDI_TONEDETECT, &val);
3697 #endif
3698 if (!p->hardwaredtmf && p->dsp) {
3699 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
3700 ast_dsp_set_features(p->dsp, p->dsp_features);
3704 static void enable_dtmf_detect(struct dahdi_pvt *p)
3706 #ifdef DAHDI_TONEDETECT
3707 int val;
3708 #endif
3710 if (p->channel == CHAN_PSEUDO)
3711 return;
3713 p->ignoredtmf = 0;
3715 #ifdef DAHDI_TONEDETECT
3716 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3717 ioctl(p->subs[SUB_REAL].zfd, DAHDI_TONEDETECT, &val);
3718 #endif
3719 if (!p->hardwaredtmf && p->dsp) {
3720 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
3721 ast_dsp_set_features(p->dsp, p->dsp_features);
3725 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
3727 struct ast_channel *who;
3728 struct dahdi_pvt *p0, *p1, *op0, *op1;
3729 struct dahdi_pvt *master = NULL, *slave = NULL;
3730 struct ast_frame *f;
3731 int inconf = 0;
3732 int nothingok = 1;
3733 int ofd0, ofd1;
3734 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3735 int os0 = -1, os1 = -1;
3736 int priority = 0;
3737 struct ast_channel *oc0, *oc1;
3738 enum ast_bridge_result res;
3740 #ifdef PRI_2BCT
3741 int triedtopribridge = 0;
3742 q931_call *q931c0 = NULL, *q931c1 = NULL;
3743 #endif
3745 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3746 There is code below to handle it properly until DTMF is actually seen,
3747 but due to currently unresolved issues it's ignored...
3750 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3751 return AST_BRIDGE_FAILED_NOWARN;
3753 ast_channel_lock(c0);
3754 while (ast_channel_trylock(c1)) {
3755 CHANNEL_DEADLOCK_AVOIDANCE(c0);
3758 p0 = c0->tech_pvt;
3759 p1 = c1->tech_pvt;
3760 /* cant do pseudo-channels here */
3761 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3762 ast_channel_unlock(c0);
3763 ast_channel_unlock(c1);
3764 return AST_BRIDGE_FAILED_NOWARN;
3767 oi0 = dahdi_get_index(c0, p0, 0);
3768 oi1 = dahdi_get_index(c1, p1, 0);
3769 if ((oi0 < 0) || (oi1 < 0)) {
3770 ast_channel_unlock(c0);
3771 ast_channel_unlock(c1);
3772 return AST_BRIDGE_FAILED;
3775 op0 = p0 = c0->tech_pvt;
3776 op1 = p1 = c1->tech_pvt;
3777 ofd0 = c0->fds[0];
3778 ofd1 = c1->fds[0];
3779 oc0 = p0->owner;
3780 oc1 = p1->owner;
3782 if (ast_mutex_trylock(&p0->lock)) {
3783 /* Don't block, due to potential for deadlock */
3784 ast_channel_unlock(c0);
3785 ast_channel_unlock(c1);
3786 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3787 return AST_BRIDGE_RETRY;
3789 if (ast_mutex_trylock(&p1->lock)) {
3790 /* Don't block, due to potential for deadlock */
3791 ast_mutex_unlock(&p0->lock);
3792 ast_channel_unlock(c0);
3793 ast_channel_unlock(c1);
3794 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3795 return AST_BRIDGE_RETRY;
3798 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3799 if (p0->owner && p1->owner) {
3800 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3801 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3802 master = p0;
3803 slave = p1;
3804 inconf = 1;
3805 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3806 master = p1;
3807 slave = p0;
3808 inconf = 1;
3809 } else {
3810 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3811 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3812 p0->channel,
3813 oi0, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
3814 p0->subs[SUB_REAL].inthreeway, p0->channel,
3815 oi0, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
3816 p1->subs[SUB_REAL].inthreeway);
3818 nothingok = 0;
3820 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3821 if (p1->subs[SUB_THREEWAY].inthreeway) {
3822 master = p1;
3823 slave = p0;
3824 nothingok = 0;
3826 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3827 if (p0->subs[SUB_THREEWAY].inthreeway) {
3828 master = p0;
3829 slave = p1;
3830 nothingok = 0;
3832 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3833 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3834 don't put us in anything */
3835 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3836 master = p1;
3837 slave = p0;
3838 nothingok = 0;
3840 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3841 /* Same as previous */
3842 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3843 master = p0;
3844 slave = p1;
3845 nothingok = 0;
3848 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
3849 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3850 if (master && slave) {
3851 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3852 in an active threeway call with a channel that is ringing, we should
3853 indicate ringing. */
3854 if ((oi1 == SUB_THREEWAY) &&
3855 p1->subs[SUB_THREEWAY].inthreeway &&
3856 p1->subs[SUB_REAL].owner &&
3857 p1->subs[SUB_REAL].inthreeway &&
3858 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3859 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3860 tone_zone_play_tone(p0->subs[oi0].zfd, DAHDI_TONE_RINGTONE);
3861 os1 = p1->subs[SUB_REAL].owner->_state;
3862 } else {
3863 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3864 tone_zone_play_tone(p0->subs[oi0].zfd, -1);
3866 if ((oi0 == SUB_THREEWAY) &&
3867 p0->subs[SUB_THREEWAY].inthreeway &&
3868 p0->subs[SUB_REAL].owner &&
3869 p0->subs[SUB_REAL].inthreeway &&
3870 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3871 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3872 tone_zone_play_tone(p1->subs[oi1].zfd, DAHDI_TONE_RINGTONE);
3873 os0 = p0->subs[SUB_REAL].owner->_state;
3874 } else {
3875 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3876 tone_zone_play_tone(p1->subs[oi0].zfd, -1);
3878 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3879 if (!p0->echocanbridged || !p1->echocanbridged) {
3880 /* Disable echo cancellation if appropriate */
3881 dahdi_disable_ec(p0);
3882 dahdi_disable_ec(p1);
3885 dahdi_link(slave, master);
3886 master->inconference = inconf;
3887 } else if (!nothingok)
3888 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3890 update_conf(p0);
3891 update_conf(p1);
3892 t0 = p0->subs[SUB_REAL].inthreeway;
3893 t1 = p1->subs[SUB_REAL].inthreeway;
3895 ast_mutex_unlock(&p0->lock);
3896 ast_mutex_unlock(&p1->lock);
3898 ast_channel_unlock(c0);
3899 ast_channel_unlock(c1);
3901 /* Native bridge failed */
3902 if ((!master || !slave) && !nothingok) {
3903 dahdi_enable_ec(p0);
3904 dahdi_enable_ec(p1);
3905 return AST_BRIDGE_FAILED;
3908 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
3910 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3911 disable_dtmf_detect(op0);
3913 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3914 disable_dtmf_detect(op1);
3916 for (;;) {
3917 struct ast_channel *c0_priority[2] = {c0, c1};
3918 struct ast_channel *c1_priority[2] = {c1, c0};
3920 /* Here's our main loop... Start by locking things, looking for private parts,
3921 and then balking if anything is wrong */
3923 ast_channel_lock(c0);
3924 while (ast_channel_trylock(c1)) {
3925 CHANNEL_DEADLOCK_AVOIDANCE(c0);
3928 p0 = c0->tech_pvt;
3929 p1 = c1->tech_pvt;
3931 if (op0 == p0)
3932 i0 = dahdi_get_index(c0, p0, 1);
3933 if (op1 == p1)
3934 i1 = dahdi_get_index(c1, p1, 1);
3936 ast_channel_unlock(c0);
3937 ast_channel_unlock(c1);
3939 if (!timeoutms ||
3940 (op0 != p0) ||
3941 (op1 != p1) ||
3942 (ofd0 != c0->fds[0]) ||
3943 (ofd1 != c1->fds[0]) ||
3944 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3945 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3946 (oc0 != p0->owner) ||
3947 (oc1 != p1->owner) ||
3948 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3949 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3950 (oi0 != i0) ||
3951 (oi1 != i1)) {
3952 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3953 op0->channel, oi0, op1->channel, oi1);
3954 res = AST_BRIDGE_RETRY;
3955 goto return_from_bridge;
3958 #ifdef PRI_2BCT
3959 q931c0 = p0->call;
3960 q931c1 = p1->call;
3961 if (p0->transfer && p1->transfer
3962 && q931c0 && q931c1
3963 && !triedtopribridge) {
3964 pri_channel_bridge(q931c0, q931c1);
3965 triedtopribridge = 1;
3967 #endif
3969 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3970 if (!who) {
3971 ast_debug(1, "Ooh, empty read...\n");
3972 continue;
3974 f = ast_read(who);
3975 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3976 *fo = f;
3977 *rc = who;
3978 res = AST_BRIDGE_COMPLETE;
3979 goto return_from_bridge;
3981 if (f->frametype == AST_FRAME_DTMF) {
3982 if ((who == c0) && p0->pulsedial) {
3983 ast_write(c1, f);
3984 } else if ((who == c1) && p1->pulsedial) {
3985 ast_write(c0, f);
3986 } else {
3987 *fo = f;
3988 *rc = who;
3989 res = AST_BRIDGE_COMPLETE;
3990 goto return_from_bridge;
3993 ast_frfree(f);
3995 /* Swap who gets priority */
3996 priority = !priority;
3999 return_from_bridge:
4000 if (op0 == p0)
4001 dahdi_enable_ec(p0);
4003 if (op1 == p1)
4004 dahdi_enable_ec(p1);
4006 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
4007 enable_dtmf_detect(op0);
4009 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
4010 enable_dtmf_detect(op1);
4012 dahdi_unlink(slave, master, 1);
4014 return res;
4017 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
4019 struct dahdi_pvt *p = newchan->tech_pvt;
4020 int x;
4021 ast_mutex_lock(&p->lock);
4022 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
4023 if (p->owner == oldchan) {
4024 p->owner = newchan;
4026 for (x = 0; x < 3; x++)
4027 if (p->subs[x].owner == oldchan) {
4028 if (!x)
4029 dahdi_unlink(NULL, p, 0);
4030 p->subs[x].owner = newchan;
4032 if (newchan->_state == AST_STATE_RINGING)
4033 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
4034 update_conf(p);
4035 ast_mutex_unlock(&p->lock);
4036 return 0;
4039 static int dahdi_ring_phone(struct dahdi_pvt *p)
4041 int x;
4042 int res;
4043 /* Make sure our transmit state is on hook */
4044 x = 0;
4045 x = DAHDI_ONHOOK;
4046 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
4047 do {
4048 x = DAHDI_RING;
4049 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
4050 if (res) {
4051 switch (errno) {
4052 case EBUSY:
4053 case EINTR:
4054 /* Wait just in case */
4055 usleep(10000);
4056 continue;
4057 case EINPROGRESS:
4058 res = 0;
4059 break;
4060 default:
4061 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
4062 res = 0;
4065 } while (res);
4066 return res;
4069 static void *ss_thread(void *data);
4071 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
4073 static int attempt_transfer(struct dahdi_pvt *p)
4075 /* In order to transfer, we need at least one of the channels to
4076 actually be in a call bridge. We can't conference two applications
4077 together (but then, why would we want to?) */
4078 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4079 /* The three-way person we're about to transfer to could still be in MOH, so
4080 stop if now if appropriate */
4081 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
4082 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
4083 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
4084 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
4086 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
4087 tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, DAHDI_TONE_RINGTONE);
4089 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
4090 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
4091 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
4092 return -1;
4094 /* Orphan the channel after releasing the lock */
4095 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4096 unalloc_sub(p, SUB_THREEWAY);
4097 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4098 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4099 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
4100 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
4102 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
4103 tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
4105 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
4106 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
4107 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
4108 return -1;
4110 /* Three-way is now the REAL */
4111 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4112 ast_channel_unlock(p->subs[SUB_REAL].owner);
4113 unalloc_sub(p, SUB_THREEWAY);
4114 /* Tell the caller not to hangup */
4115 return 1;
4116 } else {
4117 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
4118 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
4119 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4120 return -1;
4122 return 0;
4125 static int check_for_conference(struct dahdi_pvt *p)
4127 DAHDI_CONFINFO ci;
4128 /* Fine if we already have a master, etc */
4129 if (p->master || (p->confno > -1))
4130 return 0;
4131 memset(&ci, 0, sizeof(ci));
4132 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_GETCONF, &ci)) {
4133 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
4134 return 0;
4136 /* If we have no master and don't have a confno, then
4137 if we're in a conference, it's probably a MeetMe room or
4138 some such, so don't let us 3-way out! */
4139 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
4140 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
4141 return 1;
4143 return 0;
4146 /*! Checks channel for alarms
4147 * \param p a channel to check for alarms.
4148 * \returns the alarms on the span to which the channel belongs, or alarms on
4149 * the channel if no span alarms.
4151 static int get_alarms(struct dahdi_pvt *p)
4153 int res;
4154 DAHDI_SPANINFO zi;
4155 struct dahdi_params params;
4157 memset(&zi, 0, sizeof(zi));
4158 zi.spanno = p->span;
4160 if ((res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SPANSTAT, &zi)) >= 0) {
4161 if (zi.alarms != DAHDI_ALARM_NONE)
4162 return zi.alarms;
4163 } else {
4164 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
4165 return 0;
4168 /* No alarms on the span. Check for channel alarms. */
4169 if ((res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &params)) >= 0)
4170 return params.chan_alarms;
4172 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
4174 return DAHDI_ALARM_NONE;
4177 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
4179 struct dahdi_pvt *p = ast->tech_pvt;
4180 struct ast_frame *f = *dest;
4182 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
4184 if (p->confirmanswer) {
4185 ast_debug(1, "Confirm answer on %s!\n", ast->name);
4186 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
4187 of a DTMF digit */
4188 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4189 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4190 *dest = &p->subs[index].f;
4191 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
4192 p->confirmanswer = 0;
4193 } else if (p->callwaitcas) {
4194 if ((f->subclass == 'A') || (f->subclass == 'D')) {
4195 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
4196 if (p->cidspill)
4197 ast_free(p->cidspill);
4198 send_cwcidspill(p);
4200 p->callwaitcas = 0;
4201 p->subs[index].f.frametype = AST_FRAME_NULL;
4202 p->subs[index].f.subclass = 0;
4203 *dest = &p->subs[index].f;
4204 } else if (f->subclass == 'f') {
4205 /* Fax tone -- Handle and return NULL */
4206 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
4207 p->faxhandled++;
4208 if (strcmp(ast->exten, "fax")) {
4209 const char *target_context = S_OR(ast->macrocontext, ast->context);
4211 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
4212 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
4213 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
4214 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
4215 if (ast_async_goto(ast, target_context, "fax", 1))
4216 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
4217 } else
4218 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
4219 } else
4220 ast_debug(1, "Already in a fax extension, not redirecting\n");
4221 } else
4222 ast_debug(1, "Fax already handled\n");
4223 dahdi_confmute(p, 0);
4224 p->subs[index].f.frametype = AST_FRAME_NULL;
4225 p->subs[index].f.subclass = 0;
4226 *dest = &p->subs[index].f;
4230 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
4232 int res, x;
4233 int index, mysig;
4234 char *c;
4235 struct dahdi_pvt *p = ast->tech_pvt;
4236 pthread_t threadid;
4237 struct ast_channel *chan;
4238 struct ast_frame *f;
4240 index = dahdi_get_index(ast, p, 0);
4241 mysig = p->sig;
4242 if (p->outsigmod > -1)
4243 mysig = p->outsigmod;
4244 p->subs[index].f.frametype = AST_FRAME_NULL;
4245 p->subs[index].f.subclass = 0;
4246 p->subs[index].f.datalen = 0;
4247 p->subs[index].f.samples = 0;
4248 p->subs[index].f.mallocd = 0;
4249 p->subs[index].f.offset = 0;
4250 p->subs[index].f.src = "dahdi_handle_event";
4251 p->subs[index].f.data.ptr = NULL;
4252 f = &p->subs[index].f;
4254 if (index < 0)
4255 return &p->subs[index].f;
4256 if (p->fake_event) {
4257 res = p->fake_event;
4258 p->fake_event = 0;
4259 } else
4260 res = dahdi_get_event(p->subs[index].zfd);
4262 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
4264 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
4265 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
4266 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
4267 #ifdef HAVE_PRI
4268 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
4269 /* absorb event */
4270 } else {
4271 #endif
4272 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
4273 p->subs[index].f.subclass = res & 0xff;
4274 #ifdef HAVE_PRI
4276 #endif
4277 dahdi_handle_dtmfup(ast, index, &f);
4278 return f;
4281 if (res & DAHDI_EVENT_DTMFDOWN) {
4282 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
4283 /* Mute conference */
4284 dahdi_confmute(p, 1);
4285 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
4286 p->subs[index].f.subclass = res & 0xff;
4287 return &p->subs[index].f;
4290 switch (res) {
4291 #ifdef DAHDI_EVENT_EC_DISABLED
4292 case DAHDI_EVENT_EC_DISABLED:
4293 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
4294 p->echocanon = 0;
4295 break;
4296 #endif
4297 case DAHDI_EVENT_BITSCHANGED:
4298 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
4299 case DAHDI_EVENT_PULSE_START:
4300 /* Stop tone if there's a pulse start and the PBX isn't started */
4301 if (!ast->pbx)
4302 tone_zone_play_tone(p->subs[index].zfd, -1);
4303 break;
4304 case DAHDI_EVENT_DIALCOMPLETE:
4305 if (p->inalarm) break;
4306 if ((p->radio || (p->oprmode < 0))) break;
4307 if (ioctl(p->subs[index].zfd,DAHDI_DIALING,&x) == -1) {
4308 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
4309 return NULL;
4311 if (!x) { /* if not still dialing in driver */
4312 dahdi_enable_ec(p);
4313 if (p->echobreak) {
4314 dahdi_train_ec(p);
4315 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
4316 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4317 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
4318 p->echobreak = 0;
4319 } else {
4320 p->dialing = 0;
4321 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
4322 /* if thru with dialing after offhook */
4323 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
4324 ast_setstate(ast, AST_STATE_UP);
4325 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4326 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4327 break;
4328 } else { /* if to state wait for offhook to dial rest */
4329 /* we now wait for off hook */
4330 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
4333 if (ast->_state == AST_STATE_DIALING) {
4334 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
4335 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
4336 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
4337 ast_setstate(ast, AST_STATE_RINGING);
4338 } else if (!p->answeronpolarityswitch) {
4339 ast_setstate(ast, AST_STATE_UP);
4340 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4341 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4342 /* If aops=0 and hops=1, this is necessary */
4343 p->polarity = POLARITY_REV;
4344 } else {
4345 /* Start clean, so we can catch the change to REV polarity when party answers */
4346 p->polarity = POLARITY_IDLE;
4351 break;
4352 case DAHDI_EVENT_ALARM:
4353 #ifdef HAVE_PRI
4354 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
4355 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
4356 /* T309 is not enabled : hangup calls when alarm occurs */
4357 if (p->call) {
4358 if (p->pri && p->pri->pri) {
4359 if (!pri_grab(p, p->pri)) {
4360 pri_hangup(p->pri->pri, p->call, -1);
4361 pri_destroycall(p->pri->pri, p->call);
4362 p->call = NULL;
4363 pri_rel(p->pri);
4364 } else
4365 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
4366 } else
4367 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
4369 if (p->owner)
4370 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
4373 if (p->bearer)
4374 p->bearer->inalarm = 1;
4375 else
4376 #endif
4377 p->inalarm = 1;
4378 res = get_alarms(p);
4379 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm2str(res));
4380 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
4381 "Alarm: %s\r\n"
4382 "Channel: %d\r\n",
4383 alarm2str(res), p->channel);
4384 #ifdef HAVE_PRI
4385 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
4386 /* fall through intentionally */
4387 } else {
4388 break;
4390 #endif
4391 #ifdef HAVE_SS7
4392 if (p->sig == SIG_SS7)
4393 break;
4394 #endif
4395 case DAHDI_EVENT_ONHOOK:
4396 if (p->radio) {
4397 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4398 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4399 break;
4401 if (p->oprmode < 0)
4403 if (p->oprmode != -1) break;
4404 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4406 /* Make sure it starts ringing */
4407 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_RINGOFF);
4408 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_RING);
4409 save_conference(p->oprpeer);
4410 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
4412 break;
4414 switch (p->sig) {
4415 case SIG_FXOLS:
4416 case SIG_FXOGS:
4417 case SIG_FXOKS:
4418 p->onhooktime = time(NULL);
4419 p->msgstate = -1;
4420 /* Check for some special conditions regarding call waiting */
4421 if (index == SUB_REAL) {
4422 /* The normal line was hung up */
4423 if (p->subs[SUB_CALLWAIT].owner) {
4424 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
4425 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
4426 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
4427 unalloc_sub(p, SUB_CALLWAIT);
4428 #if 0
4429 p->subs[index].needanswer = 0;
4430 p->subs[index].needringing = 0;
4431 #endif
4432 p->callwaitingrepeat = 0;
4433 p->cidcwexpire = 0;
4434 p->owner = NULL;
4435 /* Don't start streaming audio yet if the incoming call isn't up yet */
4436 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
4437 p->dialing = 1;
4438 dahdi_ring_phone(p);
4439 } else if (p->subs[SUB_THREEWAY].owner) {
4440 unsigned int mssinceflash;
4441 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4442 the private structure -- not especially easy or clean */
4443 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
4444 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4445 DLA_UNLOCK(&p->lock);
4446 CHANNEL_DEADLOCK_AVOIDANCE(ast);
4447 /* We can grab ast and p in that order, without worry. We should make sure
4448 nothing seriously bad has happened though like some sort of bizarre double
4449 masquerade! */
4450 DLA_LOCK(&p->lock);
4451 if (p->owner != ast) {
4452 ast_log(LOG_WARNING, "This isn't good...\n");
4453 return NULL;
4456 if (!p->subs[SUB_THREEWAY].owner) {
4457 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
4458 return NULL;
4460 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
4461 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
4462 if (mssinceflash < MIN_MS_SINCE_FLASH) {
4463 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4464 hanging up. Hangup both channels now */
4465 if (p->subs[SUB_THREEWAY].owner)
4466 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
4467 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4468 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
4469 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4470 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
4471 if (p->transfer) {
4472 /* In any case this isn't a threeway call anymore */
4473 p->subs[SUB_REAL].inthreeway = 0;
4474 p->subs[SUB_THREEWAY].inthreeway = 0;
4475 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4476 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
4477 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4478 /* Swap subs and dis-own channel */
4479 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4480 p->owner = NULL;
4481 /* Ring the phone */
4482 dahdi_ring_phone(p);
4483 } else {
4484 if ((res = attempt_transfer(p)) < 0) {
4485 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4486 if (p->subs[SUB_THREEWAY].owner)
4487 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4488 } else if (res) {
4489 /* Don't actually hang up at this point */
4490 if (p->subs[SUB_THREEWAY].owner)
4491 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4492 break;
4495 } else {
4496 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4497 if (p->subs[SUB_THREEWAY].owner)
4498 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4500 } else {
4501 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4502 /* Swap subs and dis-own channel */
4503 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4504 p->owner = NULL;
4505 /* Ring the phone */
4506 dahdi_ring_phone(p);
4509 } else {
4510 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
4512 /* Fall through */
4513 default:
4514 dahdi_disable_ec(p);
4515 return NULL;
4517 break;
4518 case DAHDI_EVENT_RINGOFFHOOK:
4519 if (p->inalarm) break;
4520 if (p->oprmode < 0)
4522 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4524 /* Make sure it stops ringing */
4525 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_RINGOFF);
4526 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, -1);
4527 restore_conference(p->oprpeer);
4529 break;
4531 if (p->radio)
4533 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4534 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4535 break;
4537 /* for E911, its supposed to wait for offhook then dial
4538 the second half of the dial string */
4539 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
4540 c = strchr(p->dialdest, '/');
4541 if (c)
4542 c++;
4543 else
4544 c = p->dialdest;
4545 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
4546 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
4547 if (strlen(p->dop.dialstr) > 4) {
4548 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
4549 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
4550 p->echorest[sizeof(p->echorest) - 1] = '\0';
4551 p->echobreak = 1;
4552 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
4553 } else
4554 p->echobreak = 0;
4555 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop)) {
4556 int saveerr = errno;
4558 x = DAHDI_ONHOOK;
4559 ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
4560 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4561 return NULL;
4563 p->dialing = 1;
4564 return &p->subs[index].f;
4566 switch (p->sig) {
4567 case SIG_FXOLS:
4568 case SIG_FXOGS:
4569 case SIG_FXOKS:
4570 switch (ast->_state) {
4571 case AST_STATE_RINGING:
4572 dahdi_enable_ec(p);
4573 dahdi_train_ec(p);
4574 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4575 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4576 /* Make sure it stops ringing */
4577 dahdi_set_hook(p->subs[index].zfd, DAHDI_OFFHOOK);
4578 ast_debug(1, "channel %d answered\n", p->channel);
4579 if (p->cidspill) {
4580 /* Cancel any running CallerID spill */
4581 ast_free(p->cidspill);
4582 p->cidspill = NULL;
4584 p->dialing = 0;
4585 p->callwaitcas = 0;
4586 if (p->confirmanswer) {
4587 /* Ignore answer if "confirm answer" is enabled */
4588 p->subs[index].f.frametype = AST_FRAME_NULL;
4589 p->subs[index].f.subclass = 0;
4590 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4591 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4592 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
4593 if (res < 0) {
4594 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4595 p->dop.dialstr[0] = '\0';
4596 return NULL;
4597 } else {
4598 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4599 p->subs[index].f.frametype = AST_FRAME_NULL;
4600 p->subs[index].f.subclass = 0;
4601 p->dialing = 1;
4603 p->dop.dialstr[0] = '\0';
4604 ast_setstate(ast, AST_STATE_DIALING);
4605 } else
4606 ast_setstate(ast, AST_STATE_UP);
4607 return &p->subs[index].f;
4608 case AST_STATE_DOWN:
4609 ast_setstate(ast, AST_STATE_RING);
4610 ast->rings = 1;
4611 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4612 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4613 ast_debug(1, "channel %d picked up\n", p->channel);
4614 return &p->subs[index].f;
4615 case AST_STATE_UP:
4616 /* Make sure it stops ringing */
4617 dahdi_set_hook(p->subs[index].zfd, DAHDI_OFFHOOK);
4618 /* Okay -- probably call waiting*/
4619 if (ast_bridged_channel(p->owner))
4620 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4621 p->subs[index].needunhold = 1;
4622 break;
4623 case AST_STATE_RESERVED:
4624 /* Start up dialtone */
4625 if (has_voicemail(p))
4626 res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_STUTTER);
4627 else
4628 res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_DIALTONE);
4629 break;
4630 default:
4631 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4633 break;
4634 case SIG_FXSLS:
4635 case SIG_FXSGS:
4636 case SIG_FXSKS:
4637 if (ast->_state == AST_STATE_RING) {
4638 p->ringt = p->ringt_base;
4641 /* If we get a ring then we cannot be in
4642 * reversed polarity. So we reset to idle */
4643 ast_debug(1, "Setting IDLE polarity due "
4644 "to ring. Old polarity was %d\n",
4645 p->polarity);
4646 p->polarity = POLARITY_IDLE;
4648 /* Fall through */
4649 case SIG_EM:
4650 case SIG_EM_E1:
4651 case SIG_EMWINK:
4652 case SIG_FEATD:
4653 case SIG_FEATDMF:
4654 case SIG_FEATDMF_TA:
4655 case SIG_E911:
4656 case SIG_FGC_CAMA:
4657 case SIG_FGC_CAMAMF:
4658 case SIG_FEATB:
4659 case SIG_SF:
4660 case SIG_SFWINK:
4661 case SIG_SF_FEATD:
4662 case SIG_SF_FEATDMF:
4663 case SIG_SF_FEATB:
4664 if (ast->_state == AST_STATE_PRERING)
4665 ast_setstate(ast, AST_STATE_RING);
4666 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4667 ast_debug(1, "Ring detected\n");
4668 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4669 p->subs[index].f.subclass = AST_CONTROL_RING;
4670 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4671 ast_debug(1, "Line answered\n");
4672 if (p->confirmanswer) {
4673 p->subs[index].f.frametype = AST_FRAME_NULL;
4674 p->subs[index].f.subclass = 0;
4675 } else {
4676 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4677 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4678 ast_setstate(ast, AST_STATE_UP);
4680 } else if (ast->_state != AST_STATE_RING)
4681 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4682 break;
4683 default:
4684 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4686 break;
4687 #ifdef DAHDI_EVENT_RINGBEGIN
4688 case DAHDI_EVENT_RINGBEGIN:
4689 switch (p->sig) {
4690 case SIG_FXSLS:
4691 case SIG_FXSGS:
4692 case SIG_FXSKS:
4693 if (ast->_state == AST_STATE_RING) {
4694 p->ringt = p->ringt_base;
4696 break;
4698 break;
4699 #endif
4700 case DAHDI_EVENT_RINGEROFF:
4701 if (p->inalarm) break;
4702 if ((p->radio || (p->oprmode < 0))) break;
4703 ast->rings++;
4704 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4705 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4706 ast_free(p->cidspill);
4707 p->cidspill = NULL;
4708 p->callwaitcas = 0;
4710 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4711 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4712 break;
4713 case DAHDI_EVENT_RINGERON:
4714 break;
4715 case DAHDI_EVENT_NOALARM:
4716 p->inalarm = 0;
4717 #ifdef HAVE_PRI
4718 /* Extremely unlikely but just in case */
4719 if (p->bearer)
4720 p->bearer->inalarm = 0;
4721 #endif
4722 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4723 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4724 "Channel: %d\r\n", p->channel);
4725 break;
4726 case DAHDI_EVENT_WINKFLASH:
4727 if (p->inalarm) break;
4728 if (p->radio) break;
4729 if (p->oprmode < 0) break;
4730 if (p->oprmode > 1)
4732 struct dahdi_params par;
4734 if (ioctl(p->oprpeer->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &par) != -1)
4736 if (!par.rxisoffhook)
4738 /* Make sure it stops ringing */
4739 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].zfd, DAHDI_RINGOFF);
4740 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].zfd, DAHDI_RING);
4741 save_conference(p);
4742 tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
4745 break;
4747 /* Remember last time we got a flash-hook */
4748 p->flashtime = ast_tvnow();
4749 switch (mysig) {
4750 case SIG_FXOLS:
4751 case SIG_FXOGS:
4752 case SIG_FXOKS:
4753 ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4754 index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
4755 p->callwaitcas = 0;
4757 if (index != SUB_REAL) {
4758 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4759 goto winkflashdone;
4762 if (p->subs[SUB_CALLWAIT].owner) {
4763 /* Swap to call-wait */
4764 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4765 tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
4766 p->owner = p->subs[SUB_REAL].owner;
4767 ast_debug(1, "Making %s the new owner\n", p->owner->name);
4768 if (p->owner->_state == AST_STATE_RINGING) {
4769 ast_setstate(p->owner, AST_STATE_UP);
4770 p->subs[SUB_REAL].needanswer = 1;
4772 p->callwaitingrepeat = 0;
4773 p->cidcwexpire = 0;
4774 /* Start music on hold if appropriate */
4775 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4776 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4777 S_OR(p->mohsuggest, NULL),
4778 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4780 p->subs[SUB_CALLWAIT].needhold = 1;
4781 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4782 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4783 S_OR(p->mohsuggest, NULL),
4784 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4786 p->subs[SUB_REAL].needunhold = 1;
4787 } else if (!p->subs[SUB_THREEWAY].owner) {
4788 char cid_num[256];
4789 char cid_name[256];
4791 if (!p->threewaycalling) {
4792 /* Just send a flash if no 3-way calling */
4793 p->subs[SUB_REAL].needflash = 1;
4794 goto winkflashdone;
4795 } else if (!check_for_conference(p)) {
4796 if (p->dahditrcallerid && p->owner) {
4797 if (p->owner->cid.cid_num)
4798 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4799 if (p->owner->cid.cid_name)
4800 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4802 /* XXX This section needs much more error checking!!! XXX */
4803 /* Start a 3-way call if feasible */
4804 if (!((ast->pbx) ||
4805 (ast->_state == AST_STATE_UP) ||
4806 (ast->_state == AST_STATE_RING))) {
4807 ast_debug(1, "Flash when call not up or ringing\n");
4808 goto winkflashdone;
4810 if (alloc_sub(p, SUB_THREEWAY)) {
4811 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4812 goto winkflashdone;
4814 /* Make new channel */
4815 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4816 if (p->dahditrcallerid) {
4817 if (!p->origcid_num)
4818 p->origcid_num = ast_strdup(p->cid_num);
4819 if (!p->origcid_name)
4820 p->origcid_name = ast_strdup(p->cid_name);
4821 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4822 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4824 /* Swap things around between the three-way and real call */
4825 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4826 /* Disable echo canceller for better dialing */
4827 dahdi_disable_ec(p);
4828 res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_DIALRECALL);
4829 if (res)
4830 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4831 p->owner = chan;
4832 if (!chan) {
4833 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4834 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
4835 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4836 res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
4837 dahdi_enable_ec(p);
4838 ast_hangup(chan);
4839 } else {
4840 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4841 int way3bridge = 0, cdr3way = 0;
4843 if (!other) {
4844 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4845 } else
4846 way3bridge = 1;
4848 if (p->subs[SUB_THREEWAY].owner->cdr)
4849 cdr3way = 1;
4851 ast_verb(3, "Started three way call on channel %d\n", p->channel);
4853 /* Start music on hold if appropriate */
4854 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4855 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4856 S_OR(p->mohsuggest, NULL),
4857 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4859 p->subs[SUB_THREEWAY].needhold = 1;
4862 } else {
4863 /* Already have a 3 way call */
4864 if (p->subs[SUB_THREEWAY].inthreeway) {
4865 /* Call is already up, drop the last person */
4866 ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4867 /* If the primary call isn't answered yet, use it */
4868 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4869 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4870 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4871 p->owner = p->subs[SUB_REAL].owner;
4873 /* Drop the last call and stop the conference */
4874 ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4875 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4876 p->subs[SUB_REAL].inthreeway = 0;
4877 p->subs[SUB_THREEWAY].inthreeway = 0;
4878 } else {
4879 /* Lets see what we're up to */
4880 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4881 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4882 int otherindex = SUB_THREEWAY;
4883 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4884 int way3bridge = 0, cdr3way = 0;
4886 if (!other) {
4887 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4888 } else
4889 way3bridge = 1;
4891 if (p->subs[SUB_THREEWAY].owner->cdr)
4892 cdr3way = 1;
4894 ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
4895 /* Put them in the threeway, and flip */
4896 p->subs[SUB_THREEWAY].inthreeway = 1;
4897 p->subs[SUB_REAL].inthreeway = 1;
4898 if (ast->_state == AST_STATE_UP) {
4899 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4900 otherindex = SUB_REAL;
4902 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4903 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4904 p->subs[otherindex].needunhold = 1;
4905 p->owner = p->subs[SUB_REAL].owner;
4906 if (ast->_state == AST_STATE_RINGING) {
4907 ast_debug(1, "Enabling ringtone on real and threeway\n");
4908 res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
4909 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, DAHDI_TONE_RINGTONE);
4911 } else {
4912 ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4913 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4914 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4915 p->owner = p->subs[SUB_REAL].owner;
4916 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4917 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4918 p->subs[SUB_REAL].needunhold = 1;
4919 dahdi_enable_ec(p);
4924 winkflashdone:
4925 update_conf(p);
4926 break;
4927 case SIG_EM:
4928 case SIG_EM_E1:
4929 case SIG_EMWINK:
4930 case SIG_FEATD:
4931 case SIG_SF:
4932 case SIG_SFWINK:
4933 case SIG_SF_FEATD:
4934 case SIG_FXSLS:
4935 case SIG_FXSGS:
4936 if (option_debug) {
4937 if (p->dialing)
4938 ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
4939 else
4940 ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4942 break;
4943 case SIG_FEATDMF_TA:
4944 switch (p->whichwink) {
4945 case 0:
4946 ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4947 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4948 break;
4949 case 1:
4950 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4951 break;
4952 case 2:
4953 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4954 return NULL;
4956 p->whichwink++;
4957 /* Fall through */
4958 case SIG_FEATDMF:
4959 case SIG_E911:
4960 case SIG_FGC_CAMAMF:
4961 case SIG_FGC_CAMA:
4962 case SIG_FEATB:
4963 case SIG_SF_FEATDMF:
4964 case SIG_SF_FEATB:
4965 /* FGD MF *Must* wait for wink */
4966 if (!ast_strlen_zero(p->dop.dialstr)) {
4967 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
4968 if (res < 0) {
4969 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4970 p->dop.dialstr[0] = '\0';
4971 return NULL;
4972 } else
4973 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
4975 p->dop.dialstr[0] = '\0';
4976 break;
4977 default:
4978 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4980 break;
4981 case DAHDI_EVENT_HOOKCOMPLETE:
4982 if (p->inalarm) break;
4983 if ((p->radio || (p->oprmode < 0))) break;
4984 switch (mysig) {
4985 case SIG_FXSLS: /* only interesting for FXS */
4986 case SIG_FXSGS:
4987 case SIG_FXSKS:
4988 case SIG_EM:
4989 case SIG_EM_E1:
4990 case SIG_EMWINK:
4991 case SIG_FEATD:
4992 case SIG_SF:
4993 case SIG_SFWINK:
4994 case SIG_SF_FEATD:
4995 if (!ast_strlen_zero(p->dop.dialstr)) {
4996 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
4997 if (res < 0) {
4998 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4999 p->dop.dialstr[0] = '\0';
5000 return NULL;
5001 } else
5002 ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
5004 p->dop.dialstr[0] = '\0';
5005 p->dop.op = DAHDI_DIAL_OP_REPLACE;
5006 break;
5007 case SIG_FEATDMF:
5008 case SIG_FEATDMF_TA:
5009 case SIG_E911:
5010 case SIG_FGC_CAMA:
5011 case SIG_FGC_CAMAMF:
5012 case SIG_FEATB:
5013 case SIG_SF_FEATDMF:
5014 case SIG_SF_FEATB:
5015 ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
5016 break;
5017 default:
5018 break;
5020 break;
5021 case DAHDI_EVENT_POLARITY:
5023 * If we get a Polarity Switch event, check to see
5024 * if we should change the polarity state and
5025 * mark the channel as UP or if this is an indication
5026 * of remote end disconnect.
5028 if (p->polarity == POLARITY_IDLE) {
5029 p->polarity = POLARITY_REV;
5030 if (p->answeronpolarityswitch &&
5031 ((ast->_state == AST_STATE_DIALING) ||
5032 (ast->_state == AST_STATE_RINGING))) {
5033 ast_debug(1, "Answering on polarity switch!\n");
5034 ast_setstate(p->owner, AST_STATE_UP);
5035 if (p->hanguponpolarityswitch) {
5036 p->polaritydelaytv = ast_tvnow();
5038 } else
5039 ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
5042 /* Removed else statement from here as it was preventing hangups from ever happening*/
5043 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
5044 if (p->hanguponpolarityswitch &&
5045 (p->polarityonanswerdelay > 0) &&
5046 (p->polarity == POLARITY_REV) &&
5047 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
5048 /* Added log_debug information below to provide a better indication of what is going on */
5049 ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
5051 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
5052 ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
5053 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
5054 p->polarity = POLARITY_IDLE;
5055 } else
5056 ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
5058 } else {
5059 p->polarity = POLARITY_IDLE;
5060 ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
5062 /* Added more log_debug information below to provide a better indication of what is going on */
5063 ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
5064 break;
5065 default:
5066 ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
5068 return &p->subs[index].f;
5071 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
5073 struct dahdi_pvt *p = ast->tech_pvt;
5074 int res;
5075 int usedindex=-1;
5076 int index;
5077 struct ast_frame *f;
5080 index = dahdi_get_index(ast, p, 1);
5082 p->subs[index].f.frametype = AST_FRAME_NULL;
5083 p->subs[index].f.datalen = 0;
5084 p->subs[index].f.samples = 0;
5085 p->subs[index].f.mallocd = 0;
5086 p->subs[index].f.offset = 0;
5087 p->subs[index].f.subclass = 0;
5088 p->subs[index].f.delivery = ast_tv(0,0);
5089 p->subs[index].f.src = "dahdi_exception";
5090 p->subs[index].f.data.ptr = NULL;
5093 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
5094 /* If nobody owns us, absorb the event appropriately, otherwise
5095 we loop indefinitely. This occurs when, during call waiting, the
5096 other end hangs up our channel so that it no longer exists, but we
5097 have neither FLASH'd nor ONHOOK'd to signify our desire to
5098 change to the other channel. */
5099 if (p->fake_event) {
5100 res = p->fake_event;
5101 p->fake_event = 0;
5102 } else
5103 res = dahdi_get_event(p->subs[SUB_REAL].zfd);
5104 /* Switch to real if there is one and this isn't something really silly... */
5105 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
5106 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
5107 ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
5108 p->owner = p->subs[SUB_REAL].owner;
5109 if (p->owner && ast_bridged_channel(p->owner))
5110 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
5111 p->subs[SUB_REAL].needunhold = 1;
5113 switch (res) {
5114 case DAHDI_EVENT_ONHOOK:
5115 dahdi_disable_ec(p);
5116 if (p->owner) {
5117 ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
5118 dahdi_ring_phone(p);
5119 p->callwaitingrepeat = 0;
5120 p->cidcwexpire = 0;
5121 } else
5122 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
5123 update_conf(p);
5124 break;
5125 case DAHDI_EVENT_RINGOFFHOOK:
5126 dahdi_enable_ec(p);
5127 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
5128 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
5129 p->subs[SUB_REAL].needanswer = 1;
5130 p->dialing = 0;
5132 break;
5133 case DAHDI_EVENT_HOOKCOMPLETE:
5134 case DAHDI_EVENT_RINGERON:
5135 case DAHDI_EVENT_RINGEROFF:
5136 /* Do nothing */
5137 break;
5138 case DAHDI_EVENT_WINKFLASH:
5139 p->flashtime = ast_tvnow();
5140 if (p->owner) {
5141 ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
5142 if (p->owner->_state != AST_STATE_UP) {
5143 /* Answer if necessary */
5144 usedindex = dahdi_get_index(p->owner, p, 0);
5145 if (usedindex > -1) {
5146 p->subs[usedindex].needanswer = 1;
5148 ast_setstate(p->owner, AST_STATE_UP);
5150 p->callwaitingrepeat = 0;
5151 p->cidcwexpire = 0;
5152 if (ast_bridged_channel(p->owner))
5153 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
5154 p->subs[SUB_REAL].needunhold = 1;
5155 } else
5156 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
5157 update_conf(p);
5158 break;
5159 default:
5160 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
5162 f = &p->subs[index].f;
5163 return f;
5165 if (!(p->radio || (p->oprmode < 0)))
5166 ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
5167 /* If it's not us, return NULL immediately */
5168 if (ast != p->owner) {
5169 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
5170 f = &p->subs[index].f;
5171 return f;
5173 f = dahdi_handle_event(ast);
5174 return f;
5177 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
5179 struct dahdi_pvt *p = ast->tech_pvt;
5180 struct ast_frame *f;
5181 ast_mutex_lock(&p->lock);
5182 f = __dahdi_exception(ast);
5183 ast_mutex_unlock(&p->lock);
5184 return f;
5187 static struct ast_frame *dahdi_read(struct ast_channel *ast)
5189 struct dahdi_pvt *p = ast->tech_pvt;
5190 int res;
5191 int index;
5192 void *readbuf;
5193 struct ast_frame *f;
5195 while (ast_mutex_trylock(&p->lock)) {
5196 CHANNEL_DEADLOCK_AVOIDANCE(ast);
5199 index = dahdi_get_index(ast, p, 0);
5201 /* Hang up if we don't really exist */
5202 if (index < 0) {
5203 ast_log(LOG_WARNING, "We dont exist?\n");
5204 ast_mutex_unlock(&p->lock);
5205 return NULL;
5208 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
5210 p->subs[index].f.frametype = AST_FRAME_NULL;
5211 p->subs[index].f.datalen = 0;
5212 p->subs[index].f.samples = 0;
5213 p->subs[index].f.mallocd = 0;
5214 p->subs[index].f.offset = 0;
5215 p->subs[index].f.subclass = 0;
5216 p->subs[index].f.delivery = ast_tv(0,0);
5217 p->subs[index].f.src = "dahdi_read";
5218 p->subs[index].f.data.ptr = NULL;
5220 /* make sure it sends initial key state as first frame */
5221 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
5223 DAHDI_PARAMS ps;
5225 ps.channo = p->channel;
5226 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps) < 0) {
5227 ast_mutex_unlock(&p->lock);
5228 return NULL;
5230 p->firstradio = 1;
5231 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5232 if (ps.rxisoffhook)
5234 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
5236 else
5238 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
5240 ast_mutex_unlock(&p->lock);
5241 return &p->subs[index].f;
5243 if (p->ringt == 1) {
5244 ast_mutex_unlock(&p->lock);
5245 return NULL;
5247 else if (p->ringt > 0)
5248 p->ringt--;
5250 if (p->subs[index].needringing) {
5251 /* Send ringing frame if requested */
5252 p->subs[index].needringing = 0;
5253 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5254 p->subs[index].f.subclass = AST_CONTROL_RINGING;
5255 ast_setstate(ast, AST_STATE_RINGING);
5256 ast_mutex_unlock(&p->lock);
5257 return &p->subs[index].f;
5260 if (p->subs[index].needbusy) {
5261 /* Send busy frame if requested */
5262 p->subs[index].needbusy = 0;
5263 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5264 p->subs[index].f.subclass = AST_CONTROL_BUSY;
5265 ast_mutex_unlock(&p->lock);
5266 return &p->subs[index].f;
5269 if (p->subs[index].needcongestion) {
5270 /* Send congestion frame if requested */
5271 p->subs[index].needcongestion = 0;
5272 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5273 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
5274 ast_mutex_unlock(&p->lock);
5275 return &p->subs[index].f;
5278 if (p->subs[index].needcallerid) {
5279 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
5280 S_OR(p->lastcid_name, NULL),
5281 S_OR(p->lastcid_num, NULL)
5283 p->subs[index].needcallerid = 0;
5286 if (p->subs[index].needanswer) {
5287 /* Send answer frame if requested */
5288 p->subs[index].needanswer = 0;
5289 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5290 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
5291 ast_mutex_unlock(&p->lock);
5292 return &p->subs[index].f;
5295 if (p->subs[index].needflash) {
5296 /* Send answer frame if requested */
5297 p->subs[index].needflash = 0;
5298 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5299 p->subs[index].f.subclass = AST_CONTROL_FLASH;
5300 ast_mutex_unlock(&p->lock);
5301 return &p->subs[index].f;
5304 if (p->subs[index].needhold) {
5305 /* Send answer frame if requested */
5306 p->subs[index].needhold = 0;
5307 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5308 p->subs[index].f.subclass = AST_CONTROL_HOLD;
5309 ast_mutex_unlock(&p->lock);
5310 ast_debug(1, "Sending hold on '%s'\n", ast->name);
5311 return &p->subs[index].f;
5314 if (p->subs[index].needunhold) {
5315 /* Send answer frame if requested */
5316 p->subs[index].needunhold = 0;
5317 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5318 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
5319 ast_mutex_unlock(&p->lock);
5320 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
5321 return &p->subs[index].f;
5324 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
5325 if (!p->subs[index].linear) {
5326 p->subs[index].linear = 1;
5327 res = dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
5328 if (res)
5329 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
5331 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
5332 (ast->rawreadformat == AST_FORMAT_ALAW)) {
5333 if (p->subs[index].linear) {
5334 p->subs[index].linear = 0;
5335 res = dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
5336 if (res)
5337 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
5339 } else {
5340 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
5341 ast_mutex_unlock(&p->lock);
5342 return NULL;
5344 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
5345 CHECK_BLOCKING(ast);
5346 res = read(p->subs[index].zfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
5347 ast_clear_flag(ast, AST_FLAG_BLOCKING);
5348 /* Check for hangup */
5349 if (res < 0) {
5350 f = NULL;
5351 if (res == -1) {
5352 if (errno == EAGAIN) {
5353 /* Return "NULL" frame if there is nobody there */
5354 ast_mutex_unlock(&p->lock);
5355 return &p->subs[index].f;
5356 } else if (errno == ELAST) {
5357 f = __dahdi_exception(ast);
5358 } else
5359 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
5361 ast_mutex_unlock(&p->lock);
5362 return f;
5364 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
5365 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
5366 f = __dahdi_exception(ast);
5367 ast_mutex_unlock(&p->lock);
5368 return f;
5370 if (p->tdd) { /* if in TDD mode, see if we receive that */
5371 int c;
5373 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
5374 if (c < 0) {
5375 ast_debug(1,"tdd_feed failed\n");
5376 ast_mutex_unlock(&p->lock);
5377 return NULL;
5379 if (c) { /* if a char to return */
5380 p->subs[index].f.subclass = 0;
5381 p->subs[index].f.frametype = AST_FRAME_TEXT;
5382 p->subs[index].f.mallocd = 0;
5383 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
5384 p->subs[index].f.data.ptr = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
5385 p->subs[index].f.datalen = 1;
5386 *((char *) p->subs[index].f.data.ptr) = c;
5387 ast_mutex_unlock(&p->lock);
5388 return &p->subs[index].f;
5391 /* Ensure the CW timer decrements only on a single subchannel */
5392 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
5393 p->callwaitingrepeat--;
5395 if (p->cidcwexpire)
5396 p->cidcwexpire--;
5397 /* Repeat callwaiting */
5398 if (p->callwaitingrepeat == 1) {
5399 p->callwaitrings++;
5400 dahdi_callwait(ast);
5402 /* Expire CID/CW */
5403 if (p->cidcwexpire == 1) {
5404 ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
5405 restore_conference(p);
5407 if (p->subs[index].linear) {
5408 p->subs[index].f.datalen = READ_SIZE * 2;
5409 } else
5410 p->subs[index].f.datalen = READ_SIZE;
5412 /* Handle CallerID Transmission */
5413 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
5414 send_callerid(p);
5417 p->subs[index].f.frametype = AST_FRAME_VOICE;
5418 p->subs[index].f.subclass = ast->rawreadformat;
5419 p->subs[index].f.samples = READ_SIZE;
5420 p->subs[index].f.mallocd = 0;
5421 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
5422 p->subs[index].f.data.ptr = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
5423 #if 0
5424 ast_debug(1, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
5425 #endif
5426 if (p->dialing || /* Transmitting something */
5427 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
5428 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
5430 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
5431 don't send anything */
5432 p->subs[index].f.frametype = AST_FRAME_NULL;
5433 p->subs[index].f.subclass = 0;
5434 p->subs[index].f.samples = 0;
5435 p->subs[index].f.mallocd = 0;
5436 p->subs[index].f.offset = 0;
5437 p->subs[index].f.data.ptr = NULL;
5438 p->subs[index].f.datalen= 0;
5440 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
5441 /* Perform busy detection. etc on the dahdi line */
5442 int mute;
5444 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
5446 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
5447 mute = ast_dsp_was_muted(p->dsp);
5448 if (p->muting != mute) {
5449 p->muting = mute;
5450 dahdi_confmute(p, mute);
5453 if (f) {
5454 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
5455 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
5456 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5457 a busy */
5458 f = NULL;
5460 } else if (f->frametype == AST_FRAME_DTMF) {
5461 #ifdef HAVE_PRI
5462 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
5463 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
5464 (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
5465 /* Don't accept in-band DTMF when in overlap dial mode */
5466 f->frametype = AST_FRAME_NULL;
5467 f->subclass = 0;
5469 #endif
5470 /* DSP clears us of being pulse */
5471 p->pulsedial = 0;
5474 } else
5475 f = &p->subs[index].f;
5477 if (f && (f->frametype == AST_FRAME_DTMF))
5478 dahdi_handle_dtmfup(ast, index, &f);
5480 /* If we have a fake_event, trigger exception to handle it */
5481 if (p->fake_event)
5482 ast_set_flag(ast, AST_FLAG_EXCEPTION);
5484 ast_mutex_unlock(&p->lock);
5485 return f;
5488 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
5490 int sent=0;
5491 int size;
5492 int res;
5493 int fd;
5494 fd = p->subs[index].zfd;
5495 while (len) {
5496 size = len;
5497 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
5498 size = (linear ? READ_SIZE * 2 : READ_SIZE);
5499 res = write(fd, buf, size);
5500 if (res != size) {
5501 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
5502 return sent;
5504 len -= size;
5505 buf += size;
5507 return sent;
5510 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
5512 struct dahdi_pvt *p = ast->tech_pvt;
5513 int res;
5514 int index;
5515 index = dahdi_get_index(ast, p, 0);
5516 if (index < 0) {
5517 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
5518 return -1;
5521 #if 0
5522 #ifdef HAVE_PRI
5523 ast_mutex_lock(&p->lock);
5524 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5525 if (p->pri->pri) {
5526 if (!pri_grab(p, p->pri)) {
5527 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5528 pri_rel(p->pri);
5529 } else
5530 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5532 p->proceeding=1;
5534 ast_mutex_unlock(&p->lock);
5535 #endif
5536 #endif
5537 /* Write a frame of (presumably voice) data */
5538 if (frame->frametype != AST_FRAME_VOICE) {
5539 if (frame->frametype != AST_FRAME_IMAGE)
5540 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
5541 return 0;
5543 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
5544 (frame->subclass != AST_FORMAT_ULAW) &&
5545 (frame->subclass != AST_FORMAT_ALAW)) {
5546 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
5547 return -1;
5549 if (p->dialing) {
5550 ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
5551 return 0;
5553 if (!p->owner) {
5554 ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
5555 return 0;
5557 if (p->cidspill) {
5558 ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
5559 return 0;
5561 /* Return if it's not valid data */
5562 if (!frame->data.ptr || !frame->datalen)
5563 return 0;
5565 if (frame->subclass == AST_FORMAT_SLINEAR) {
5566 if (!p->subs[index].linear) {
5567 p->subs[index].linear = 1;
5568 res = dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
5569 if (res)
5570 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5572 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, index, 1);
5573 } else {
5574 /* x-law already */
5575 if (p->subs[index].linear) {
5576 p->subs[index].linear = 0;
5577 res = dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
5578 if (res)
5579 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5581 res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, index, 0);
5583 if (res < 0) {
5584 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5585 return -1;
5587 return 0;
5590 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5592 struct dahdi_pvt *p = chan->tech_pvt;
5593 int res=-1;
5594 int index;
5595 int func = DAHDI_FLASH;
5596 ast_mutex_lock(&p->lock);
5597 index = dahdi_get_index(chan, p, 0);
5598 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
5599 if (index == SUB_REAL) {
5600 switch (condition) {
5601 case AST_CONTROL_BUSY:
5602 #ifdef HAVE_PRI
5603 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
5604 chan->hangupcause = AST_CAUSE_USER_BUSY;
5605 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5606 res = 0;
5607 } else if (!p->progress &&
5608 ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
5609 && p->pri && !p->outgoing) {
5610 if (p->pri->pri) {
5611 if (!pri_grab(p, p->pri)) {
5612 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5613 pri_rel(p->pri);
5615 else
5616 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5618 p->progress = 1;
5619 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_BUSY);
5620 } else
5621 #endif
5622 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_BUSY);
5623 break;
5624 case AST_CONTROL_RINGING:
5625 #ifdef HAVE_PRI
5626 if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
5627 && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5628 if (p->pri->pri) {
5629 if (!pri_grab(p, p->pri)) {
5630 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5631 pri_rel(p->pri);
5633 else
5634 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5636 p->alerting = 1;
5639 #endif
5640 #ifdef HAVE_SS7
5641 if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5642 if (p->ss7->ss7) {
5643 ss7_grab(p, p->ss7);
5645 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
5646 p->rlt = 1;
5647 if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
5648 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
5649 p->alerting = 1;
5650 ss7_rel(p->ss7);
5653 #endif
5655 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_RINGTONE);
5657 if (chan->_state != AST_STATE_UP) {
5658 if ((chan->_state != AST_STATE_RING) ||
5659 ((p->sig != SIG_FXSKS) &&
5660 (p->sig != SIG_FXSLS) &&
5661 (p->sig != SIG_FXSGS)))
5662 ast_setstate(chan, AST_STATE_RINGING);
5664 break;
5665 case AST_CONTROL_PROCEEDING:
5666 ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5667 #ifdef HAVE_PRI
5668 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
5669 && p->pri && !p->outgoing) {
5670 if (p->pri->pri) {
5671 if (!pri_grab(p, p->pri)) {
5672 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5673 pri_rel(p->pri);
5675 else
5676 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5678 p->proceeding = 1;
5680 #endif
5681 #ifdef HAVE_SS7
5682 /* This IF sends the FAR for an answered ALEG call */
5683 if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
5684 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
5685 p->rlt = 1;
5688 if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
5689 if (p->ss7->ss7) {
5690 ss7_grab(p, p->ss7);
5691 isup_acm(p->ss7->ss7, p->ss7call);
5692 p->proceeding = 1;
5693 ss7_rel(p->ss7);
5697 #endif
5698 /* don't continue in ast_indicate */
5699 res = 0;
5700 break;
5701 case AST_CONTROL_PROGRESS:
5702 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5703 #ifdef HAVE_PRI
5704 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5705 if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
5706 && p->pri && !p->outgoing) {
5707 if (p->pri->pri) {
5708 if (!pri_grab(p, p->pri)) {
5709 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5710 pri_rel(p->pri);
5712 else
5713 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5715 p->progress = 1;
5717 #endif
5718 #ifdef HAVE_SS7
5719 if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
5720 if (p->ss7->ss7) {
5721 ss7_grab(p, p->ss7);
5722 isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
5723 p->progress = 1;
5724 ss7_rel(p->ss7);
5725 /* enable echo canceler here on SS7 calls */
5726 dahdi_enable_ec(p);
5730 #endif
5731 /* don't continue in ast_indicate */
5732 res = 0;
5733 break;
5734 case AST_CONTROL_CONGESTION:
5735 chan->hangupcause = AST_CAUSE_CONGESTION;
5736 #ifdef HAVE_PRI
5737 if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
5738 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5739 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5740 res = 0;
5741 } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
5742 && p->pri && !p->outgoing) {
5743 if (p->pri) {
5744 if (!pri_grab(p, p->pri)) {
5745 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5746 pri_rel(p->pri);
5747 } else
5748 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5750 p->progress = 1;
5751 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
5752 } else
5753 #endif
5754 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
5755 break;
5756 case AST_CONTROL_HOLD:
5757 #ifdef HAVE_PRI
5758 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5759 if (!pri_grab(p, p->pri)) {
5760 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5761 pri_rel(p->pri);
5762 } else
5763 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5764 } else
5765 #endif
5766 ast_moh_start(chan, data, p->mohinterpret);
5767 break;
5768 case AST_CONTROL_UNHOLD:
5769 #ifdef HAVE_PRI
5770 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5771 if (!pri_grab(p, p->pri)) {
5772 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5773 pri_rel(p->pri);
5774 } else
5775 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5776 } else
5777 #endif
5778 ast_moh_stop(chan);
5779 break;
5780 case AST_CONTROL_RADIO_KEY:
5781 if (p->radio)
5782 res = dahdi_set_hook(p->subs[index].zfd, DAHDI_OFFHOOK);
5783 res = 0;
5784 break;
5785 case AST_CONTROL_RADIO_UNKEY:
5786 if (p->radio)
5787 res = dahdi_set_hook(p->subs[index].zfd, DAHDI_RINGOFF);
5788 res = 0;
5789 break;
5790 case AST_CONTROL_FLASH:
5791 /* flash hookswitch */
5792 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5793 /* Clear out the dial buffer */
5794 p->dop.dialstr[0] = '\0';
5795 if ((ioctl(p->subs[SUB_REAL].zfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5796 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5797 chan->name, strerror(errno));
5798 } else
5799 res = 0;
5800 } else
5801 res = 0;
5802 break;
5803 case AST_CONTROL_SRCUPDATE:
5804 res = 0;
5805 break;
5806 case -1:
5807 res = tone_zone_play_tone(p->subs[index].zfd, -1);
5808 break;
5810 } else
5811 res = 0;
5812 ast_mutex_unlock(&p->lock);
5813 return res;
5816 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5818 struct ast_channel *tmp;
5819 int deflaw;
5820 int res;
5821 int x,y;
5822 int features;
5823 struct ast_str *chan_name;
5824 struct ast_variable *v;
5825 DAHDI_PARAMS ps;
5826 if (i->subs[index].owner) {
5827 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5828 return NULL;
5830 y = 1;
5831 chan_name = ast_str_alloca(32);
5832 do {
5833 #ifdef HAVE_PRI
5834 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5835 ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5836 else
5837 #endif
5838 if (i->channel == CHAN_PSEUDO)
5839 ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
5840 else
5841 ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
5842 for (x = 0; x < 3; x++) {
5843 if ((index != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name))
5844 break;
5846 y++;
5847 } while (x < 3);
5848 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str);
5849 if (!tmp)
5850 return NULL;
5851 tmp->tech = &dahdi_tech;
5852 ps.channo = i->channel;
5853 res = ioctl(i->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps);
5854 if (res) {
5855 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5856 ps.curlaw = DAHDI_LAW_MULAW;
5858 if (ps.curlaw == DAHDI_LAW_ALAW)
5859 deflaw = AST_FORMAT_ALAW;
5860 else
5861 deflaw = AST_FORMAT_ULAW;
5862 if (law) {
5863 if (law == DAHDI_LAW_ALAW)
5864 deflaw = AST_FORMAT_ALAW;
5865 else
5866 deflaw = AST_FORMAT_ULAW;
5868 ast_channel_set_fd(tmp, 0, i->subs[index].zfd);
5869 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5870 /* Start out assuming ulaw since it's smaller :) */
5871 tmp->rawreadformat = deflaw;
5872 tmp->readformat = deflaw;
5873 tmp->rawwriteformat = deflaw;
5874 tmp->writeformat = deflaw;
5875 i->subs[index].linear = 0;
5876 dahdi_setlinear(i->subs[index].zfd, i->subs[index].linear);
5877 features = 0;
5878 if (index == SUB_REAL) {
5879 if (i->busydetect && CANBUSYDETECT(i))
5880 features |= DSP_FEATURE_BUSY_DETECT;
5881 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
5882 features |= DSP_FEATURE_CALL_PROGRESS;
5883 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
5884 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
5885 features |= DSP_FEATURE_FAX_DETECT;
5887 #ifdef DAHDI_TONEDETECT
5888 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5889 if (ioctl(i->subs[index].zfd, DAHDI_TONEDETECT, &x)) {
5890 #endif
5891 i->hardwaredtmf = 0;
5892 features |= DSP_FEATURE_DIGIT_DETECT;
5893 #ifdef DAHDI_TONEDETECT
5894 } else if (NEED_MFDETECT(i)) {
5895 i->hardwaredtmf = 1;
5896 features |= DSP_FEATURE_DIGIT_DETECT;
5898 #endif
5900 if (features) {
5901 if (i->dsp) {
5902 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
5903 } else {
5904 if (i->channel != CHAN_PSEUDO)
5905 i->dsp = ast_dsp_new();
5906 else
5907 i->dsp = NULL;
5908 if (i->dsp) {
5909 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5910 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5911 /* We cannot do progress detection until receives PROGRESS message */
5912 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
5913 /* Remember requested DSP features, don't treat
5914 talking as ANSWER */
5915 features = 0;
5917 #endif
5918 ast_dsp_set_features(i->dsp, features);
5919 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5920 if (!ast_strlen_zero(progzone))
5921 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5922 if (i->busydetect && CANBUSYDETECT(i)) {
5923 ast_dsp_set_busy_count(i->dsp, i->busycount);
5924 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5930 if (state == AST_STATE_RING)
5931 tmp->rings = 1;
5932 tmp->tech_pvt = i;
5933 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5934 /* Only FXO signalled stuff can be picked up */
5935 tmp->callgroup = i->callgroup;
5936 tmp->pickupgroup = i->pickupgroup;
5938 if (!ast_strlen_zero(i->parkinglot))
5939 ast_string_field_set(tmp, parkinglot, i->parkinglot);
5940 if (!ast_strlen_zero(i->language))
5941 ast_string_field_set(tmp, language, i->language);
5942 if (!i->owner)
5943 i->owner = tmp;
5944 if (!ast_strlen_zero(i->accountcode))
5945 ast_string_field_set(tmp, accountcode, i->accountcode);
5946 if (i->amaflags)
5947 tmp->amaflags = i->amaflags;
5948 i->subs[index].owner = tmp;
5949 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5950 ast_string_field_set(tmp, call_forward, i->call_forward);
5951 /* If we've been told "no ADSI" then enforce it */
5952 if (!i->adsi)
5953 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5954 if (!ast_strlen_zero(i->exten))
5955 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5956 if (!ast_strlen_zero(i->rdnis))
5957 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5958 if (!ast_strlen_zero(i->dnid))
5959 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5961 /* Don't use ast_set_callerid() here because it will
5962 * generate a needless NewCallerID event */
5963 #ifdef PRI_ANI
5964 if (!ast_strlen_zero(i->cid_ani))
5965 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5966 else
5967 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5968 #else
5969 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5970 #endif
5971 tmp->cid.cid_pres = i->callingpres;
5972 tmp->cid.cid_ton = i->cid_ton;
5973 tmp->cid.cid_ani2 = i->cid_ani2;
5974 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5975 tmp->transfercapability = transfercapability;
5976 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5977 if (transfercapability & AST_TRANS_CAP_DIGITAL)
5978 i->digital = 1;
5979 /* Assume calls are not idle calls unless we're told differently */
5980 i->isidlecall = 0;
5981 i->alreadyhungup = 0;
5982 #endif
5983 /* clear the fake event in case we posted one before we had ast_channel */
5984 i->fake_event = 0;
5985 /* Assure there is no confmute on this channel */
5986 dahdi_confmute(i, 0);
5987 i->muting = 0;
5988 /* Configure the new channel jb */
5989 ast_jb_configure(tmp, &global_jbconf);
5991 ast_device_state_changed_literal(tmp->name);
5993 for (v = i->vars ; v ; v = v->next)
5994 pbx_builtin_setvar_helper(tmp, v->name, v->value);
5996 if (startpbx) {
5997 if (ast_pbx_start(tmp)) {
5998 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5999 ast_hangup(tmp);
6000 i->owner = NULL;
6001 return NULL;
6005 ast_module_ref(ast_module_info->self);
6006 return tmp;
6010 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
6012 char c;
6014 *str = 0; /* start with empty output buffer */
6015 for (;;)
6017 /* Wait for the first digit (up to specified ms). */
6018 c = ast_waitfordigit(chan, ms);
6019 /* if timeout, hangup or error, return as such */
6020 if (c < 1)
6021 return c;
6022 *str++ = c;
6023 *str = 0;
6024 if (strchr(term, c))
6025 return 1;
6029 static int dahdi_wink(struct dahdi_pvt *p, int index)
6031 int j;
6032 dahdi_set_hook(p->subs[index].zfd, DAHDI_WINK);
6033 for (;;)
6035 /* set bits of interest */
6036 j = DAHDI_IOMUX_SIGEVENT;
6037 /* wait for some happening */
6038 if (ioctl(p->subs[index].zfd,DAHDI_IOMUX,&j) == -1) return(-1);
6039 /* exit loop if we have it */
6040 if (j & DAHDI_IOMUX_SIGEVENT) break;
6042 /* get the event info */
6043 if (ioctl(p->subs[index].zfd,DAHDI_GETEVENT,&j) == -1) return(-1);
6044 return 0;
6047 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
6048 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
6049 * \param on 1 to enable, 0 to disable
6051 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
6052 * DAHDI channel). Use this to enable or disable it.
6054 * \bug the use of the word "channel" for those dahdichans is really confusing.
6056 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
6058 /* Do not disturb */
6059 dahdichan->dnd = on;
6060 ast_verb(3, "%s DND on channel %d\n",
6061 on? "Enabled" : "Disabled",
6062 dahdichan->channel);
6063 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6064 "Channel: DAHDI/%d\r\n"
6065 "Status: %s\r\n", dahdichan->channel,
6066 on? "enabled" : "disabled");
6069 static void *ss_thread(void *data)
6071 struct ast_channel *chan = data;
6072 struct dahdi_pvt *p = chan->tech_pvt;
6073 char exten[AST_MAX_EXTENSION] = "";
6074 char exten2[AST_MAX_EXTENSION] = "";
6075 unsigned char buf[256];
6076 char dtmfcid[300];
6077 char dtmfbuf[300];
6078 struct callerid_state *cs = NULL;
6079 char *name = NULL, *number = NULL;
6080 int distMatches;
6081 int curRingData[3];
6082 int receivedRingT;
6083 int counter1;
6084 int counter;
6085 int samples = 0;
6086 struct ast_smdi_md_message *smdi_msg = NULL;
6087 int flags;
6088 int i;
6089 int timeout;
6090 int getforward = 0;
6091 char *s1, *s2;
6092 int len = 0;
6093 int res;
6094 int index;
6096 /* in the bizarre case where the channel has become a zombie before we
6097 even get started here, abort safely
6099 if (!p) {
6100 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
6101 ast_hangup(chan);
6102 return NULL;
6105 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
6106 index = dahdi_get_index(chan, p, 1);
6107 if (index < 0) {
6108 ast_log(LOG_WARNING, "Huh?\n");
6109 ast_hangup(chan);
6110 return NULL;
6112 if (p->dsp)
6113 ast_dsp_digitreset(p->dsp);
6114 switch (p->sig) {
6115 #ifdef HAVE_PRI
6116 case SIG_PRI:
6117 case SIG_BRI:
6118 case SIG_BRI_PTMP:
6119 /* Now loop looking for an extension */
6120 ast_copy_string(exten, p->exten, sizeof(exten));
6121 len = strlen(exten);
6122 res = 0;
6123 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
6124 if (len && !ast_ignore_pattern(chan->context, exten))
6125 tone_zone_play_tone(p->subs[index].zfd, -1);
6126 else
6127 tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);
6128 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
6129 timeout = matchdigittimeout;
6130 else
6131 timeout = gendigittimeout;
6132 res = ast_waitfordigit(chan, timeout);
6133 if (res < 0) {
6134 ast_debug(1, "waitfordigit returned < 0...\n");
6135 ast_hangup(chan);
6136 return NULL;
6137 } else if (res) {
6138 exten[len++] = res;
6139 exten[len] = '\0';
6140 } else
6141 break;
6143 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
6144 if (ast_strlen_zero(exten)) {
6145 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
6146 exten[0] = 's';
6147 exten[1] = '\0';
6149 tone_zone_play_tone(p->subs[index].zfd, -1);
6150 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
6151 /* Start the real PBX */
6152 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6153 if (p->dsp) ast_dsp_digitreset(p->dsp);
6154 dahdi_enable_ec(p);
6155 ast_setstate(chan, AST_STATE_RING);
6156 res = ast_pbx_run(chan);
6157 if (res) {
6158 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
6160 } else {
6161 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
6162 chan->hangupcause = AST_CAUSE_UNALLOCATED;
6163 ast_hangup(chan);
6164 p->exten[0] = '\0';
6165 /* Since we send release complete here, we won't get one */
6166 p->call = NULL;
6168 return NULL;
6169 break;
6170 #endif
6171 case SIG_FEATD:
6172 case SIG_FEATDMF:
6173 case SIG_FEATDMF_TA:
6174 case SIG_E911:
6175 case SIG_FGC_CAMAMF:
6176 case SIG_FEATB:
6177 case SIG_EMWINK:
6178 case SIG_SF_FEATD:
6179 case SIG_SF_FEATDMF:
6180 case SIG_SF_FEATB:
6181 case SIG_SFWINK:
6182 if (dahdi_wink(p, index))
6183 return NULL;
6184 /* Fall through */
6185 case SIG_EM:
6186 case SIG_EM_E1:
6187 case SIG_SF:
6188 case SIG_FGC_CAMA:
6189 res = tone_zone_play_tone(p->subs[index].zfd, -1);
6190 if (p->dsp)
6191 ast_dsp_digitreset(p->dsp);
6192 /* set digit mode appropriately */
6193 if (p->dsp) {
6194 if (NEED_MFDETECT(p))
6195 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
6196 else
6197 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6199 memset(dtmfbuf, 0, sizeof(dtmfbuf));
6200 /* Wait for the first digit only if immediate=no */
6201 if (!p->immediate)
6202 /* Wait for the first digit (up to 5 seconds). */
6203 res = ast_waitfordigit(chan, 5000);
6204 else
6205 res = 0;
6206 if (res > 0) {
6207 /* save first char */
6208 dtmfbuf[0] = res;
6209 switch (p->sig) {
6210 case SIG_FEATD:
6211 case SIG_SF_FEATD:
6212 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
6213 if (res > 0)
6214 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
6215 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6216 break;
6217 case SIG_FEATDMF_TA:
6218 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6219 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6220 if (dahdi_wink(p, index)) return NULL;
6221 dtmfbuf[0] = 0;
6222 /* Wait for the first digit (up to 5 seconds). */
6223 res = ast_waitfordigit(chan, 5000);
6224 if (res <= 0) break;
6225 dtmfbuf[0] = res;
6226 /* fall through intentionally */
6227 case SIG_FEATDMF:
6228 case SIG_E911:
6229 case SIG_FGC_CAMAMF:
6230 case SIG_SF_FEATDMF:
6231 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6232 /* if international caca, do it again to get real ANO */
6233 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
6235 if (dahdi_wink(p, index)) return NULL;
6236 dtmfbuf[0] = 0;
6237 /* Wait for the first digit (up to 5 seconds). */
6238 res = ast_waitfordigit(chan, 5000);
6239 if (res <= 0) break;
6240 dtmfbuf[0] = res;
6241 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6243 if (res > 0) {
6244 /* if E911, take off hook */
6245 if (p->sig == SIG_E911)
6246 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
6247 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
6249 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6250 break;
6251 case SIG_FEATB:
6252 case SIG_SF_FEATB:
6253 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6254 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6255 break;
6256 case SIG_EMWINK:
6257 /* if we received a '*', we are actually receiving Feature Group D
6258 dial syntax, so use that mode; otherwise, fall through to normal
6259 mode
6261 if (res == '*') {
6262 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
6263 if (res > 0)
6264 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
6265 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6266 break;
6268 default:
6269 /* If we got the first digit, get the rest */
6270 len = 1;
6271 dtmfbuf[len] = '\0';
6272 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
6273 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
6274 timeout = matchdigittimeout;
6275 } else {
6276 timeout = gendigittimeout;
6278 res = ast_waitfordigit(chan, timeout);
6279 if (res < 0) {
6280 ast_debug(1, "waitfordigit returned < 0...\n");
6281 ast_hangup(chan);
6282 return NULL;
6283 } else if (res) {
6284 dtmfbuf[len++] = res;
6285 dtmfbuf[len] = '\0';
6286 } else {
6287 break;
6290 break;
6293 if (res == -1) {
6294 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
6295 ast_hangup(chan);
6296 return NULL;
6297 } else if (res < 0) {
6298 ast_debug(1, "Got hung up before digits finished\n");
6299 ast_hangup(chan);
6300 return NULL;
6303 if (p->sig == SIG_FGC_CAMA) {
6304 char anibuf[100];
6306 if (ast_safe_sleep(chan,1000) == -1) {
6307 ast_hangup(chan);
6308 return NULL;
6310 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
6311 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
6312 res = my_getsigstr(chan, anibuf, "#", 10000);
6313 if ((res > 0) && (strlen(anibuf) > 2)) {
6314 if (anibuf[strlen(anibuf) - 1] == '#')
6315 anibuf[strlen(anibuf) - 1] = 0;
6316 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
6318 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6321 ast_copy_string(exten, dtmfbuf, sizeof(exten));
6322 if (ast_strlen_zero(exten))
6323 ast_copy_string(exten, "s", sizeof(exten));
6324 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
6325 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
6326 if (exten[0] == '*') {
6327 char *stringp=NULL;
6328 ast_copy_string(exten2, exten, sizeof(exten2));
6329 /* Parse out extension and callerid */
6330 stringp=exten2 +1;
6331 s1 = strsep(&stringp, "*");
6332 s2 = strsep(&stringp, "*");
6333 if (s2) {
6334 if (!ast_strlen_zero(p->cid_num))
6335 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6336 else
6337 ast_set_callerid(chan, s1, NULL, s1);
6338 ast_copy_string(exten, s2, sizeof(exten));
6339 } else
6340 ast_copy_string(exten, s1, sizeof(exten));
6341 } else if (p->sig == SIG_FEATD)
6342 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
6344 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
6345 if (exten[0] == '*') {
6346 char *stringp=NULL;
6347 ast_copy_string(exten2, exten, sizeof(exten2));
6348 /* Parse out extension and callerid */
6349 stringp=exten2 +1;
6350 s1 = strsep(&stringp, "#");
6351 s2 = strsep(&stringp, "#");
6352 if (s2) {
6353 if (!ast_strlen_zero(p->cid_num))
6354 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6355 else
6356 if (*(s1 + 2))
6357 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
6358 ast_copy_string(exten, s2 + 1, sizeof(exten));
6359 } else
6360 ast_copy_string(exten, s1 + 2, sizeof(exten));
6361 } else
6362 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
6364 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
6365 if (exten[0] == '*') {
6366 char *stringp=NULL;
6367 ast_copy_string(exten2, exten, sizeof(exten2));
6368 /* Parse out extension and callerid */
6369 stringp=exten2 +1;
6370 s1 = strsep(&stringp, "#");
6371 s2 = strsep(&stringp, "#");
6372 if (s2 && (*(s2 + 1) == '0')) {
6373 if (*(s2 + 2))
6374 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
6376 if (s1) ast_copy_string(exten, s1, sizeof(exten));
6377 else ast_copy_string(exten, "911", sizeof(exten));
6378 } else
6379 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
6381 if (p->sig == SIG_FEATB) {
6382 if (exten[0] == '*') {
6383 char *stringp=NULL;
6384 ast_copy_string(exten2, exten, sizeof(exten2));
6385 /* Parse out extension and callerid */
6386 stringp=exten2 +1;
6387 s1 = strsep(&stringp, "#");
6388 ast_copy_string(exten, exten2 + 1, sizeof(exten));
6389 } else
6390 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
6392 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
6393 dahdi_wink(p, index);
6394 /* some switches require a minimum guard time between
6395 the last FGD wink and something that answers
6396 immediately. This ensures it */
6397 if (ast_safe_sleep(chan,100)) return NULL;
6399 dahdi_enable_ec(p);
6400 if (NEED_MFDETECT(p)) {
6401 if (p->dsp) {
6402 if (!p->hardwaredtmf)
6403 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6404 else {
6405 ast_dsp_free(p->dsp);
6406 p->dsp = NULL;
6411 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
6412 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6413 if (p->dsp) ast_dsp_digitreset(p->dsp);
6414 res = ast_pbx_run(chan);
6415 if (res) {
6416 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6417 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
6419 return NULL;
6420 } else {
6421 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
6422 sleep(2);
6423 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_INFO);
6424 if (res < 0)
6425 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
6426 else
6427 sleep(1);
6428 res = ast_streamfile(chan, "ss-noservice", chan->language);
6429 if (res >= 0)
6430 ast_waitstream(chan, "");
6431 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
6432 ast_hangup(chan);
6433 return NULL;
6435 break;
6436 case SIG_FXOLS:
6437 case SIG_FXOGS:
6438 case SIG_FXOKS:
6439 /* Read the first digit */
6440 timeout = firstdigittimeout;
6441 /* If starting a threeway call, never timeout on the first digit so someone
6442 can use flash-hook as a "hold" feature */
6443 if (p->subs[SUB_THREEWAY].owner)
6444 timeout = 999999;
6445 while (len < AST_MAX_EXTENSION-1) {
6446 /* Read digit unless it's supposed to be immediate, in which case the
6447 only answer is 's' */
6448 if (p->immediate)
6449 res = 's';
6450 else
6451 res = ast_waitfordigit(chan, timeout);
6452 timeout = 0;
6453 if (res < 0) {
6454 ast_debug(1, "waitfordigit returned < 0...\n");
6455 res = tone_zone_play_tone(p->subs[index].zfd, -1);
6456 ast_hangup(chan);
6457 return NULL;
6458 } else if (res) {
6459 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
6460 exten[len++]=res;
6461 exten[len] = '\0';
6463 if (!ast_ignore_pattern(chan->context, exten))
6464 tone_zone_play_tone(p->subs[index].zfd, -1);
6465 else
6466 tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);
6467 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
6468 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
6469 if (getforward) {
6470 /* Record this as the forwarding extension */
6471 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
6472 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
6473 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6474 if (res)
6475 break;
6476 usleep(500000);
6477 res = tone_zone_play_tone(p->subs[index].zfd, -1);
6478 sleep(1);
6479 memset(exten, 0, sizeof(exten));
6480 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALTONE);
6481 len = 0;
6482 getforward = 0;
6483 } else {
6484 res = tone_zone_play_tone(p->subs[index].zfd, -1);
6485 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6486 if (!ast_strlen_zero(p->cid_num)) {
6487 if (!p->hidecallerid)
6488 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6489 else
6490 ast_set_callerid(chan, NULL, NULL, p->cid_num);
6492 if (!ast_strlen_zero(p->cid_name)) {
6493 if (!p->hidecallerid)
6494 ast_set_callerid(chan, NULL, p->cid_name, NULL);
6496 ast_setstate(chan, AST_STATE_RING);
6497 dahdi_enable_ec(p);
6498 res = ast_pbx_run(chan);
6499 if (res) {
6500 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6501 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
6503 return NULL;
6505 } else {
6506 /* It's a match, but they just typed a digit, and there is an ambiguous match,
6507 so just set the timeout to matchdigittimeout and wait some more */
6508 timeout = matchdigittimeout;
6510 } else if (res == 0) {
6511 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
6512 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
6513 dahdi_wait_event(p->subs[index].zfd);
6514 ast_hangup(chan);
6515 return NULL;
6516 } else if (p->callwaiting && !strcmp(exten, "*70")) {
6517 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
6518 /* Disable call waiting if enabled */
6519 p->callwaiting = 0;
6520 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6521 if (res) {
6522 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6523 chan->name, strerror(errno));
6525 len = 0;
6526 ioctl(p->subs[index].zfd,DAHDI_CONFDIAG,&len);
6527 memset(exten, 0, sizeof(exten));
6528 timeout = firstdigittimeout;
6530 } else if (!strcmp(exten,ast_pickup_ext())) {
6531 /* Scan all channels and see if there are any
6532 * ringing channels that have call groups
6533 * that equal this channels pickup group
6535 if (index == SUB_REAL) {
6536 /* Switch us from Third call to Call Wait */
6537 if (p->subs[SUB_THREEWAY].owner) {
6538 /* If you make a threeway call and the *8# a call, it should actually
6539 look like a callwait */
6540 alloc_sub(p, SUB_CALLWAIT);
6541 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6542 unalloc_sub(p, SUB_THREEWAY);
6544 dahdi_enable_ec(p);
6545 if (ast_pickup_call(chan)) {
6546 ast_debug(1, "No call pickup possible...\n");
6547 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
6548 dahdi_wait_event(p->subs[index].zfd);
6550 ast_hangup(chan);
6551 return NULL;
6552 } else {
6553 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
6554 ast_hangup(chan);
6555 return NULL;
6558 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
6559 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
6560 /* Disable Caller*ID if enabled */
6561 p->hidecallerid = 1;
6562 if (chan->cid.cid_num)
6563 ast_free(chan->cid.cid_num);
6564 chan->cid.cid_num = NULL;
6565 if (chan->cid.cid_name)
6566 ast_free(chan->cid.cid_name);
6567 chan->cid.cid_name = NULL;
6568 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6569 if (res) {
6570 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6571 chan->name, strerror(errno));
6573 len = 0;
6574 memset(exten, 0, sizeof(exten));
6575 timeout = firstdigittimeout;
6576 } else if (p->callreturn && !strcmp(exten, "*69")) {
6577 res = 0;
6578 if (!ast_strlen_zero(p->lastcid_num)) {
6579 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
6581 if (!res)
6582 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6583 break;
6584 } else if (!strcmp(exten, "*78")) {
6585 dahdi_dnd(p, 1);
6586 /* Do not disturb */
6587 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6588 getforward = 0;
6589 memset(exten, 0, sizeof(exten));
6590 len = 0;
6591 } else if (!strcmp(exten, "*79")) {
6592 dahdi_dnd(p, 0);
6593 /* Do not disturb */
6594 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6595 getforward = 0;
6596 memset(exten, 0, sizeof(exten));
6597 len = 0;
6598 } else if (p->cancallforward && !strcmp(exten, "*72")) {
6599 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6600 getforward = 1;
6601 memset(exten, 0, sizeof(exten));
6602 len = 0;
6603 } else if (p->cancallforward && !strcmp(exten, "*73")) {
6604 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
6605 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6606 memset(p->call_forward, 0, sizeof(p->call_forward));
6607 getforward = 0;
6608 memset(exten, 0, sizeof(exten));
6609 len = 0;
6610 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
6611 p->subs[SUB_THREEWAY].owner &&
6612 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6613 /* This is a three way call, the main call being a real channel,
6614 and we're parking the first call. */
6615 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
6616 ast_verb(3, "Parking call to '%s'\n", chan->name);
6617 break;
6618 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
6619 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
6620 res = ast_db_put("blacklist", p->lastcid_num, "1");
6621 if (!res) {
6622 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6623 memset(exten, 0, sizeof(exten));
6624 len = 0;
6626 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6627 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
6628 /* Enable Caller*ID if enabled */
6629 p->hidecallerid = 0;
6630 if (chan->cid.cid_num)
6631 ast_free(chan->cid.cid_num);
6632 chan->cid.cid_num = NULL;
6633 if (chan->cid.cid_name)
6634 ast_free(chan->cid.cid_name);
6635 chan->cid.cid_name = NULL;
6636 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6637 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_DIALRECALL);
6638 if (res) {
6639 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6640 chan->name, strerror(errno));
6642 len = 0;
6643 memset(exten, 0, sizeof(exten));
6644 timeout = firstdigittimeout;
6645 } else if (!strcmp(exten, "*0")) {
6646 struct ast_channel *nbridge =
6647 p->subs[SUB_THREEWAY].owner;
6648 struct dahdi_pvt *pbridge = NULL;
6649 /* set up the private struct of the bridged one, if any */
6650 if (nbridge && ast_bridged_channel(nbridge))
6651 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6652 if (nbridge && pbridge &&
6653 (nbridge->tech == &dahdi_tech) &&
6654 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
6655 ISTRUNK(pbridge)) {
6656 int func = DAHDI_FLASH;
6657 /* Clear out the dial buffer */
6658 p->dop.dialstr[0] = '\0';
6659 /* flash hookswitch */
6660 if ((ioctl(pbridge->subs[SUB_REAL].zfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6661 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6662 nbridge->name, strerror(errno));
6664 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6665 unalloc_sub(p, SUB_THREEWAY);
6666 p->owner = p->subs[SUB_REAL].owner;
6667 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6668 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6669 ast_hangup(chan);
6670 return NULL;
6671 } else {
6672 tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
6673 dahdi_wait_event(p->subs[index].zfd);
6674 tone_zone_play_tone(p->subs[index].zfd, -1);
6675 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6676 unalloc_sub(p, SUB_THREEWAY);
6677 p->owner = p->subs[SUB_REAL].owner;
6678 ast_hangup(chan);
6679 return NULL;
6681 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6682 ((exten[0] != '*') || (strlen(exten) > 2))) {
6683 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
6684 break;
6686 if (!timeout)
6687 timeout = gendigittimeout;
6688 if (len && !ast_ignore_pattern(chan->context, exten))
6689 tone_zone_play_tone(p->subs[index].zfd, -1);
6691 break;
6692 case SIG_FXSLS:
6693 case SIG_FXSGS:
6694 case SIG_FXSKS:
6695 #ifdef HAVE_PRI
6696 if (p->pri) {
6697 /* This is a GR-303 trunk actually. Wait for the first ring... */
6698 struct ast_frame *f;
6699 int res;
6700 time_t start;
6702 time(&start);
6703 ast_setstate(chan, AST_STATE_RING);
6704 while (time(NULL) < start + 3) {
6705 res = ast_waitfor(chan, 1000);
6706 if (res) {
6707 f = ast_read(chan);
6708 if (!f) {
6709 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6710 ast_hangup(chan);
6711 return NULL;
6712 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6713 res = 1;
6714 } else
6715 res = 0;
6716 ast_frfree(f);
6717 if (res) {
6718 ast_debug(1, "Got ring!\n");
6719 res = 0;
6720 break;
6725 #endif
6726 /* check for SMDI messages */
6727 if (p->use_smdi && p->smdi_iface) {
6728 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6730 if (smdi_msg != NULL) {
6731 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6733 if (smdi_msg->type == 'B')
6734 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6735 else if (smdi_msg->type == 'N')
6736 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6738 ast_debug(1, "Recieved SMDI message on %s\n", chan->name);
6739 } else {
6740 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6744 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6745 number = smdi_msg->calling_st;
6747 /* If we want caller id, we're in a prering state due to a polarity reversal
6748 * and we're set to use a polarity reversal to trigger the start of caller id,
6749 * grab the caller id and wait for ringing to start... */
6750 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
6751 /* If set to use DTMF CID signalling, listen for DTMF */
6752 if (p->cid_signalling == CID_SIG_DTMF) {
6753 int i = 0;
6754 cs = NULL;
6755 ast_debug(1, "Receiving DTMF cid on "
6756 "channel %s\n", chan->name);
6757 dahdi_setlinear(p->subs[index].zfd, 0);
6758 res = 2000;
6759 for (;;) {
6760 struct ast_frame *f;
6761 res = ast_waitfor(chan, res);
6762 if (res <= 0) {
6763 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6764 "Exiting simple switch\n");
6765 ast_hangup(chan);
6766 return NULL;
6768 f = ast_read(chan);
6769 if (!f)
6770 break;
6771 if (f->frametype == AST_FRAME_DTMF) {
6772 dtmfbuf[i++] = f->subclass;
6773 ast_debug(1, "CID got digit '%c'\n", f->subclass);
6774 res = 2000;
6776 ast_frfree(f);
6777 if (chan->_state == AST_STATE_RING ||
6778 chan->_state == AST_STATE_RINGING)
6779 break; /* Got ring */
6781 dtmfbuf[i] = '\0';
6782 dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
6783 /* Got cid and ring. */
6784 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
6785 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6786 ast_debug(1, "CID is '%s', flags %d\n",
6787 dtmfcid, flags);
6788 /* If first byte is NULL, we have no cid */
6789 if (!ast_strlen_zero(dtmfcid))
6790 number = dtmfcid;
6791 else
6792 number = NULL;
6793 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6794 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6795 cs = callerid_new(p->cid_signalling);
6796 if (cs) {
6797 samples = 0;
6798 #if 1
6799 bump_gains(p);
6800 #endif
6801 /* Take out of linear mode for Caller*ID processing */
6802 dahdi_setlinear(p->subs[index].zfd, 0);
6804 /* First we wait and listen for the Caller*ID */
6805 for (;;) {
6806 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6807 if ((res = ioctl(p->subs[index].zfd, DAHDI_IOMUX, &i))) {
6808 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6809 callerid_free(cs);
6810 ast_hangup(chan);
6811 return NULL;
6813 if (i & DAHDI_IOMUX_SIGEVENT) {
6814 res = dahdi_get_event(p->subs[index].zfd);
6815 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6817 if (p->cid_signalling == CID_SIG_V23_JP) {
6818 #ifdef DAHDI_EVENT_RINGBEGIN
6819 if (res == DAHDI_EVENT_RINGBEGIN) {
6820 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
6821 usleep(1);
6823 #endif
6824 } else {
6825 res = 0;
6826 break;
6828 } else if (i & DAHDI_IOMUX_READ) {
6829 res = read(p->subs[index].zfd, buf, sizeof(buf));
6830 if (res < 0) {
6831 if (errno != ELAST) {
6832 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6833 callerid_free(cs);
6834 ast_hangup(chan);
6835 return NULL;
6837 break;
6839 samples += res;
6841 if (p->cid_signalling == CID_SIG_V23_JP) {
6842 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6843 } else {
6844 res = callerid_feed(cs, buf, res, AST_LAW(p));
6847 if (res < 0) {
6848 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6849 break;
6850 } else if (res)
6851 break;
6852 else if (samples > (8000 * 10))
6853 break;
6856 if (res == 1) {
6857 callerid_get(cs, &name, &number, &flags);
6858 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6861 if (p->cid_signalling == CID_SIG_V23_JP) {
6862 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
6863 usleep(1);
6864 res = 4000;
6865 } else {
6867 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6868 res = 2000;
6871 for (;;) {
6872 struct ast_frame *f;
6873 res = ast_waitfor(chan, res);
6874 if (res <= 0) {
6875 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6876 "Exiting simple switch\n");
6877 ast_hangup(chan);
6878 return NULL;
6880 if (!(f = ast_read(chan))) {
6881 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6882 ast_hangup(chan);
6883 return NULL;
6885 ast_frfree(f);
6886 if (chan->_state == AST_STATE_RING ||
6887 chan->_state == AST_STATE_RINGING)
6888 break; /* Got ring */
6891 /* We must have a ring by now, so, if configured, lets try to listen for
6892 * distinctive ringing */
6893 if (p->usedistinctiveringdetection == 1) {
6894 len = 0;
6895 distMatches = 0;
6896 /* Clear the current ring data array so we dont have old data in it. */
6897 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
6898 curRingData[receivedRingT] = 0;
6899 receivedRingT = 0;
6900 counter = 0;
6901 counter1 = 0;
6902 /* Check to see if context is what it should be, if not set to be. */
6903 if (strcmp(p->context,p->defcontext) != 0) {
6904 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6905 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6908 for (;;) {
6909 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6910 if ((res = ioctl(p->subs[index].zfd, DAHDI_IOMUX, &i))) {
6911 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6912 callerid_free(cs);
6913 ast_hangup(chan);
6914 return NULL;
6916 if (i & DAHDI_IOMUX_SIGEVENT) {
6917 res = dahdi_get_event(p->subs[index].zfd);
6918 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6919 res = 0;
6920 /* Let us detect distinctive ring */
6922 curRingData[receivedRingT] = p->ringt;
6924 if (p->ringt < p->ringt_base/2)
6925 break;
6926 /* Increment the ringT counter so we can match it against
6927 values in chan_dahdi.conf for distinctive ring */
6928 if (++receivedRingT == ARRAY_LEN(curRingData))
6929 break;
6930 } else if (i & DAHDI_IOMUX_READ) {
6931 res = read(p->subs[index].zfd, buf, sizeof(buf));
6932 if (res < 0) {
6933 if (errno != ELAST) {
6934 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6935 callerid_free(cs);
6936 ast_hangup(chan);
6937 return NULL;
6939 break;
6941 if (p->ringt)
6942 p->ringt--;
6943 if (p->ringt == 1) {
6944 res = -1;
6945 break;
6949 /* this only shows up if you have n of the dring patterns filled in */
6950 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6951 for (counter = 0; counter < 3; counter++) {
6952 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6953 channel */
6954 distMatches = 0;
6955 for (counter1 = 0; counter1 < 3; counter1++) {
6956 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
6957 if (p->drings.ringnum[counter].ring[counter1] == -1) {
6958 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
6959 curRingData[counter1]);
6960 distMatches++;
6962 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
6963 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
6964 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
6965 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
6966 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
6967 distMatches++;
6971 if (distMatches == 3) {
6972 /* The ring matches, set the context to whatever is for distinctive ring.. */
6973 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6974 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6975 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
6976 break;
6980 /* Restore linear mode (if appropriate) for Caller*ID processing */
6981 dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
6982 #if 1
6983 restore_gains(p);
6984 #endif
6985 } else
6986 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6987 } else {
6988 ast_log(LOG_WARNING, "Channel %s in prering "
6989 "state, but I have nothing to do. "
6990 "Terminating simple switch, should be "
6991 "restarted by the actual ring.\n",
6992 chan->name);
6993 ast_hangup(chan);
6994 return NULL;
6996 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6997 if (p->cid_signalling == CID_SIG_DTMF) {
6998 int i = 0;
6999 cs = NULL;
7000 dahdi_setlinear(p->subs[index].zfd, 0);
7001 res = 2000;
7002 for (;;) {
7003 struct ast_frame *f;
7004 res = ast_waitfor(chan, res);
7005 if (res <= 0) {
7006 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
7007 "Exiting simple switch\n");
7008 ast_hangup(chan);
7009 return NULL;
7011 f = ast_read(chan);
7012 if (f->frametype == AST_FRAME_DTMF) {
7013 dtmfbuf[i++] = f->subclass;
7014 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
7015 res = 2000;
7017 ast_frfree(f);
7019 if (p->ringt_base == p->ringt)
7020 break;
7023 dtmfbuf[i] = '\0';
7024 dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
7025 /* Got cid and ring. */
7026 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
7027 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
7028 dtmfcid, flags);
7029 /* If first byte is NULL, we have no cid */
7030 if (!ast_strlen_zero(dtmfcid))
7031 number = dtmfcid;
7032 else
7033 number = NULL;
7034 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
7035 } else {
7036 /* FSK Bell202 callerID */
7037 cs = callerid_new(p->cid_signalling);
7038 if (cs) {
7039 #if 1
7040 bump_gains(p);
7041 #endif
7042 samples = 0;
7043 len = 0;
7044 distMatches = 0;
7045 /* Clear the current ring data array so we dont have old data in it. */
7046 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
7047 curRingData[receivedRingT] = 0;
7048 receivedRingT = 0;
7049 counter = 0;
7050 counter1 = 0;
7051 /* Check to see if context is what it should be, if not set to be. */
7052 if (strcmp(p->context,p->defcontext) != 0) {
7053 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
7054 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
7057 /* Take out of linear mode for Caller*ID processing */
7058 dahdi_setlinear(p->subs[index].zfd, 0);
7059 for (;;) {
7060 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7061 if ((res = ioctl(p->subs[index].zfd, DAHDI_IOMUX, &i))) {
7062 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7063 callerid_free(cs);
7064 ast_hangup(chan);
7065 return NULL;
7067 if (i & DAHDI_IOMUX_SIGEVENT) {
7068 res = dahdi_get_event(p->subs[index].zfd);
7069 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
7070 /* If we get a PR event, they hung up while processing calerid */
7071 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
7072 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
7073 p->polarity = POLARITY_IDLE;
7074 callerid_free(cs);
7075 ast_hangup(chan);
7076 return NULL;
7078 res = 0;
7079 /* Let us detect callerid when the telco uses distinctive ring */
7081 curRingData[receivedRingT] = p->ringt;
7083 if (p->ringt < p->ringt_base/2)
7084 break;
7085 /* Increment the ringT counter so we can match it against
7086 values in chan_dahdi.conf for distinctive ring */
7087 if (++receivedRingT == ARRAY_LEN(curRingData))
7088 break;
7089 } else if (i & DAHDI_IOMUX_READ) {
7090 res = read(p->subs[index].zfd, buf, sizeof(buf));
7091 if (res < 0) {
7092 if (errno != ELAST) {
7093 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7094 callerid_free(cs);
7095 ast_hangup(chan);
7096 return NULL;
7098 break;
7100 if (p->ringt)
7101 p->ringt--;
7102 if (p->ringt == 1) {
7103 res = -1;
7104 break;
7106 samples += res;
7107 res = callerid_feed(cs, buf, res, AST_LAW(p));
7108 if (res < 0) {
7109 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
7110 break;
7111 } else if (res)
7112 break;
7113 else if (samples > (8000 * 10))
7114 break;
7117 if (res == 1) {
7118 callerid_get(cs, &name, &number, &flags);
7119 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
7121 if (distinctiveringaftercid == 1) {
7122 /* Clear the current ring data array so we dont have old data in it. */
7123 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
7124 curRingData[receivedRingT] = 0;
7126 receivedRingT = 0;
7127 ast_verb(3, "Detecting post-CID distinctive ring\n");
7128 for (;;) {
7129 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7130 if ((res = ioctl(p->subs[index].zfd, DAHDI_IOMUX, &i))) {
7131 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7132 callerid_free(cs);
7133 ast_hangup(chan);
7134 return NULL;
7136 if (i & DAHDI_IOMUX_SIGEVENT) {
7137 res = dahdi_get_event(p->subs[index].zfd);
7138 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
7139 res = 0;
7140 /* Let us detect callerid when the telco uses distinctive ring */
7142 curRingData[receivedRingT] = p->ringt;
7144 if (p->ringt < p->ringt_base/2)
7145 break;
7146 /* Increment the ringT counter so we can match it against
7147 values in chan_dahdi.conf for distinctive ring */
7148 if (++receivedRingT == ARRAY_LEN(curRingData))
7149 break;
7150 } else if (i & DAHDI_IOMUX_READ) {
7151 res = read(p->subs[index].zfd, buf, sizeof(buf));
7152 if (res < 0) {
7153 if (errno != ELAST) {
7154 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7155 callerid_free(cs);
7156 ast_hangup(chan);
7157 return NULL;
7159 break;
7161 if (p->ringt)
7162 p->ringt--;
7163 if (p->ringt == 1) {
7164 res = -1;
7165 break;
7170 if (p->usedistinctiveringdetection == 1) {
7171 /* this only shows up if you have n of the dring patterns filled in */
7172 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
7174 for (counter = 0; counter < 3; counter++) {
7175 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
7176 channel */
7177 /* this only shows up if you have n of the dring patterns filled in */
7178 ast_verb(3, "Checking %d,%d,%d\n",
7179 p->drings.ringnum[counter].ring[0],
7180 p->drings.ringnum[counter].ring[1],
7181 p->drings.ringnum[counter].ring[2]);
7182 distMatches = 0;
7183 for (counter1 = 0; counter1 < 3; counter1++) {
7184 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
7185 if (p->drings.ringnum[counter].ring[counter1] == -1) {
7186 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
7187 curRingData[counter1]);
7188 distMatches++;
7190 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
7191 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
7192 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
7193 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
7194 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
7195 distMatches++;
7198 if (distMatches == 3) {
7199 /* The ring matches, set the context to whatever is for distinctive ring.. */
7200 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
7201 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
7202 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
7203 break;
7207 /* Restore linear mode (if appropriate) for Caller*ID processing */
7208 dahdi_setlinear(p->subs[index].zfd, p->subs[index].linear);
7209 #if 1
7210 restore_gains(p);
7211 #endif
7212 if (res < 0) {
7213 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
7215 } else
7216 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
7219 else
7220 cs = NULL;
7222 if (number)
7223 ast_shrink_phone_number(number);
7224 ast_set_callerid(chan, number, name, number);
7226 if (smdi_msg)
7227 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
7229 if (cs)
7230 callerid_free(cs);
7231 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
7232 if (flags & CID_MSGWAITING) {
7233 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
7234 notify_message(p->mailbox, 1);
7235 ast_hangup(chan);
7236 return NULL;
7237 } else if (flags & CID_NOMSGWAITING) {
7238 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
7239 notify_message(p->mailbox, 0);
7240 ast_hangup(chan);
7241 return NULL;
7244 ast_setstate(chan, AST_STATE_RING);
7245 chan->rings = 1;
7246 p->ringt = p->ringt_base;
7247 res = ast_pbx_run(chan);
7248 if (res) {
7249 ast_hangup(chan);
7250 ast_log(LOG_WARNING, "PBX exited non-zero\n");
7252 return NULL;
7253 default:
7254 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
7255 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
7256 if (res < 0)
7257 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
7259 res = tone_zone_play_tone(p->subs[index].zfd, DAHDI_TONE_CONGESTION);
7260 if (res < 0)
7261 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
7262 ast_hangup(chan);
7263 return NULL;
7266 struct mwi_thread_data {
7267 struct dahdi_pvt *pvt;
7268 unsigned char buf[READ_SIZE];
7269 size_t len;
7272 static int calc_energy(const unsigned char *buf, int len, int law)
7274 int x;
7275 int sum = 0;
7277 if (!len)
7278 return 0;
7280 for (x = 0; x < len; x++)
7281 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
7283 return sum / len;
7286 static void *mwi_thread(void *data)
7288 struct mwi_thread_data *mtd = data;
7289 struct callerid_state *cs;
7290 pthread_attr_t attr;
7291 pthread_t threadid;
7292 int samples = 0;
7293 char *name, *number;
7294 int flags;
7295 int i, res;
7296 unsigned int spill_done = 0;
7297 int spill_result = -1;
7299 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
7300 mtd->pvt->mwimonitoractive = 0;
7302 return NULL;
7305 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
7307 bump_gains(mtd->pvt);
7309 for (;;) {
7310 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7311 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_IOMUX, &i))) {
7312 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7313 goto quit;
7316 if (i & DAHDI_IOMUX_SIGEVENT) {
7317 struct ast_channel *chan;
7319 /* If we get an event, screen out events that we do not act on.
7320 * Otherwise, cancel and go to the simple switch to let it deal with it.
7322 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].zfd);
7324 switch (res) {
7325 #ifdef HAVE_DAHDI_NEONMWI
7326 case DAHDI_EVENT_NEONMWI_ACTIVE:
7327 case DAHDI_EVENT_NEONMWI_INACTIVE:
7328 #endif
7329 case DAHDI_EVENT_NONE:
7330 case DAHDI_EVENT_BITSCHANGED:
7331 break;
7332 case DAHDI_EVENT_NOALARM:
7333 mtd->pvt->inalarm = 0;
7334 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
7335 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
7336 "Channel: %d\r\n", mtd->pvt->channel);
7337 break;
7338 case DAHDI_EVENT_ALARM:
7339 mtd->pvt->inalarm = 1;
7340 res = get_alarms(mtd->pvt);
7341 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", mtd->pvt->channel, alarm2str(res));
7342 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
7343 "Alarm: %s\r\n"
7344 "Channel: %d\r\n",
7345 alarm2str(res), mtd->pvt->channel);
7346 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
7347 default:
7348 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
7349 callerid_free(cs);
7351 restore_gains(mtd->pvt);
7352 mtd->pvt->ringt = mtd->pvt->ringt_base;
7354 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
7355 pthread_attr_init(&attr);
7356 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7358 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
7359 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
7360 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7361 if (res < 0)
7362 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
7363 ast_hangup(chan);
7364 goto quit;
7366 goto quit_no_clean;
7368 } else {
7369 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
7372 } else if (i & DAHDI_IOMUX_READ) {
7373 if ((res = read(mtd->pvt->subs[SUB_REAL].zfd, mtd->buf, sizeof(mtd->buf))) < 0) {
7374 if (errno != ELAST) {
7375 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7376 goto quit;
7378 break;
7380 samples += res;
7381 if (!spill_done) {
7382 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
7383 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
7384 break;
7385 } else if (spill_result) {
7386 spill_done = 1;
7388 } else {
7389 /* keep reading data until the energy level drops below the threshold
7390 so we don't get another 'trigger' on the remaining carrier signal
7392 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
7393 break;
7395 if (samples > (8000 * 4)) /*Termination case - time to give up*/
7396 break;
7400 if (spill_result == 1) {
7401 callerid_get(cs, &name, &number, &flags);
7402 if (flags & CID_MSGWAITING) {
7403 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
7404 notify_message(mtd->pvt->mailbox, 1);
7405 } else if (flags & CID_NOMSGWAITING) {
7406 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
7407 notify_message(mtd->pvt->mailbox, 0);
7408 } else {
7409 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
7414 quit:
7415 callerid_free(cs);
7417 restore_gains(mtd->pvt);
7419 quit_no_clean:
7420 mtd->pvt->mwimonitoractive = 0;
7422 ast_free(mtd);
7424 return NULL;
7427 /* States for sending MWI message
7428 * First three states are required for send Ring Pulse Alert Signal
7430 enum mwisend_states {
7431 MWI_SEND_SA,
7432 MWI_SEND_SA_WAIT,
7433 MWI_SEND_PAUSE,
7434 MWI_SEND_SPILL,
7435 MWI_SEND_CLEANUP,
7436 MWI_SEND_DONE
7439 static void *mwi_send_thread(void *data)
7441 struct mwi_thread_data *mtd = data;
7442 struct timeval timeout_basis, pause, now;
7443 int x, i, res;
7444 int num_read;
7445 enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
7447 /* Determine how this spill is to be sent */
7448 if(mwisend_rpas) {
7449 mwi_send_state = MWI_SEND_SA;
7452 gettimeofday(&timeout_basis, NULL);
7454 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
7455 if (!mtd->pvt->cidspill) {
7456 mtd->pvt->mwisendactive = 0;
7457 ast_free(mtd);
7458 return NULL;
7460 x = DAHDI_FLUSH_BOTH;
7461 res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_FLUSH, &x);
7462 x = 3000;
7463 ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_ONHOOKTRANSFER, &x);
7464 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
7465 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
7466 mtd->pvt->cidpos = 0;
7468 while (MWI_SEND_DONE != mwi_send_state) {
7469 num_read = 0;
7470 gettimeofday(&now, NULL);
7471 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
7472 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
7473 goto quit;
7476 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7477 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_IOMUX, &i))) {
7478 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7479 goto quit;
7482 if (i & DAHDI_IOMUX_SIGEVENT) {
7483 /* If we get an event, screen out events that we do not act on.
7484 * Otherwise, let handle_init_event determine what is needed
7486 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].zfd);
7487 switch (res) {
7488 case DAHDI_EVENT_RINGEROFF:
7489 if(mwi_send_state == MWI_SEND_SA_WAIT) {
7490 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_RINGOFF) ) {
7491 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
7492 goto quit;
7494 mwi_send_state = MWI_SEND_PAUSE;
7495 gettimeofday(&pause, NULL);
7497 break;
7498 case DAHDI_EVENT_RINGERON:
7499 case DAHDI_EVENT_HOOKCOMPLETE:
7500 break;
7501 default:
7502 /* Got to the default init event handler */
7503 if (0 < handle_init_event(mtd->pvt, res)) {
7504 /* I've spawned a thread, get out */
7505 goto quit;
7507 break;
7509 } else if (i & DAHDI_IOMUX_READ) {
7510 if ((num_read = read(mtd->pvt->subs[SUB_REAL].zfd, mtd->buf, sizeof(mtd->buf))) < 0) {
7511 if (errno != ELAST) {
7512 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7513 goto quit;
7515 break;
7518 /* Perform mwi send action */
7519 switch ( mwi_send_state) {
7520 case MWI_SEND_SA:
7521 /* Send the Ring Pulse Signal Alert */
7522 res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, &AS_RP_cadence);
7523 if (res) {
7524 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
7525 goto quit;
7527 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_RING);
7528 mwi_send_state = MWI_SEND_SA_WAIT;
7529 break;
7530 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
7531 break;
7532 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
7533 gettimeofday(&now, NULL);
7534 if ((int)(now.tv_sec - pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pause.tv_usec > 500000) {
7535 mwi_send_state = MWI_SEND_SPILL;
7537 break;
7538 case MWI_SEND_SPILL:
7539 /* We read some number of bytes. Write an equal amount of data */
7540 if(0 < num_read) {
7541 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
7542 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
7543 res = write(mtd->pvt->subs[SUB_REAL].zfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
7544 if (res > 0) {
7545 mtd->pvt->cidpos += res;
7546 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
7547 ast_free(mtd->pvt->cidspill);
7548 mtd->pvt->cidspill = NULL;
7549 mtd->pvt->cidpos = 0;
7550 mtd->pvt->cidlen = 0;
7551 mwi_send_state = MWI_SEND_CLEANUP;
7553 } else {
7554 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
7555 goto quit;
7558 break;
7559 case MWI_SEND_CLEANUP:
7560 /* For now, do nothing */
7561 mwi_send_state = MWI_SEND_DONE;
7562 break;
7563 default:
7564 /* Should not get here, punt*/
7565 goto quit;
7566 break;
7569 quit:
7570 if(mtd->pvt->cidspill) {
7571 ast_free(mtd->pvt->cidspill);
7572 mtd->pvt->cidspill = NULL;
7574 mtd->pvt->mwisendactive = 0;
7575 ast_free(mtd);
7577 return NULL;
7581 /* destroy a DAHDI channel, identified by its number */
7582 static int dahdi_destroy_channel_bynum(int channel)
7584 struct dahdi_pvt *tmp = NULL;
7585 struct dahdi_pvt *prev = NULL;
7587 tmp = iflist;
7588 while (tmp) {
7589 if (tmp->channel == channel) {
7590 destroy_channel(prev, tmp, 1);
7591 return RESULT_SUCCESS;
7593 prev = tmp;
7594 tmp = tmp->next;
7596 return RESULT_FAILURE;
7599 /* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
7600 static int handle_init_event(struct dahdi_pvt *i, int event)
7602 int res;
7603 int thread_spawned = 0;
7604 pthread_t threadid;
7605 struct ast_channel *chan;
7607 /* Handle an event on a given channel for the monitor thread. */
7609 switch (event) {
7610 case DAHDI_EVENT_NONE:
7611 case DAHDI_EVENT_BITSCHANGED:
7612 break;
7613 case DAHDI_EVENT_WINKFLASH:
7614 case DAHDI_EVENT_RINGOFFHOOK:
7615 if (i->inalarm) break;
7616 if (i->radio) break;
7617 /* Got a ring/answer. What kind of channel are we? */
7618 switch (i->sig) {
7619 case SIG_FXOLS:
7620 case SIG_FXOGS:
7621 case SIG_FXOKS:
7622 res = dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
7623 if (res && (errno == EBUSY))
7624 break;
7625 if (i->cidspill) {
7626 /* Cancel VMWI spill */
7627 ast_free(i->cidspill);
7628 i->cidspill = NULL;
7630 if (i->immediate) {
7631 dahdi_enable_ec(i);
7632 /* The channel is immediately up. Start right away */
7633 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
7634 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
7635 if (!chan) {
7636 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
7637 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7638 if (res < 0)
7639 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7641 } else {
7642 /* Check for callerid, digits, etc */
7643 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
7644 if (chan) {
7645 if (has_voicemail(i))
7646 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_STUTTER);
7647 else
7648 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_DIALTONE);
7649 if (res < 0)
7650 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
7651 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
7652 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7653 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7654 if (res < 0)
7655 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7656 ast_hangup(chan);
7657 } else {
7658 thread_spawned = 1;
7660 } else
7661 ast_log(LOG_WARNING, "Unable to create channel\n");
7663 break;
7664 case SIG_FXSLS:
7665 case SIG_FXSGS:
7666 case SIG_FXSKS:
7667 i->ringt = i->ringt_base;
7668 /* Fall through */
7669 case SIG_EMWINK:
7670 case SIG_FEATD:
7671 case SIG_FEATDMF:
7672 case SIG_FEATDMF_TA:
7673 case SIG_E911:
7674 case SIG_FGC_CAMA:
7675 case SIG_FGC_CAMAMF:
7676 case SIG_FEATB:
7677 case SIG_EM:
7678 case SIG_EM_E1:
7679 case SIG_SFWINK:
7680 case SIG_SF_FEATD:
7681 case SIG_SF_FEATDMF:
7682 case SIG_SF_FEATB:
7683 case SIG_SF:
7684 /* Check for callerid, digits, etc */
7685 if (i->cid_start == CID_START_POLARITY_IN) {
7686 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
7687 } else {
7688 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
7691 if (!chan) {
7692 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
7693 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
7694 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7695 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7696 if (res < 0) {
7697 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7699 ast_hangup(chan);
7700 } else {
7701 thread_spawned = 1;
7703 break;
7704 default:
7705 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
7706 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7707 if (res < 0)
7708 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7709 return -1;
7711 break;
7712 case DAHDI_EVENT_NOALARM:
7713 i->inalarm = 0;
7714 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
7715 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
7716 "Channel: %d\r\n", i->channel);
7717 break;
7718 case DAHDI_EVENT_ALARM:
7719 i->inalarm = 1;
7720 res = get_alarms(i);
7721 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
7722 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
7723 "Alarm: %s\r\n"
7724 "Channel: %d\r\n",
7725 alarm2str(res), i->channel);
7726 /* fall thru intentionally */
7727 case DAHDI_EVENT_ONHOOK:
7728 if (i->radio)
7729 break;
7730 /* Back on hook. Hang up. */
7731 switch (i->sig) {
7732 case SIG_FXOLS:
7733 case SIG_FXOGS:
7734 case SIG_FEATD:
7735 case SIG_FEATDMF:
7736 case SIG_FEATDMF_TA:
7737 case SIG_E911:
7738 case SIG_FGC_CAMA:
7739 case SIG_FGC_CAMAMF:
7740 case SIG_FEATB:
7741 case SIG_EM:
7742 case SIG_EM_E1:
7743 case SIG_EMWINK:
7744 case SIG_SF_FEATD:
7745 case SIG_SF_FEATDMF:
7746 case SIG_SF_FEATB:
7747 case SIG_SF:
7748 case SIG_SFWINK:
7749 case SIG_FXSLS:
7750 case SIG_FXSGS:
7751 case SIG_FXSKS:
7752 case SIG_GR303FXSKS:
7753 dahdi_disable_ec(i);
7754 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7755 dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
7756 break;
7757 case SIG_GR303FXOKS:
7758 case SIG_FXOKS:
7759 dahdi_disable_ec(i);
7760 /* Diddle the battery for the zhone */
7761 #ifdef ZHONE_HACK
7762 dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
7763 usleep(1);
7764 #endif
7765 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7766 dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
7767 break;
7768 case SIG_PRI:
7769 case SIG_SS7:
7770 case SIG_BRI:
7771 case SIG_BRI_PTMP:
7772 dahdi_disable_ec(i);
7773 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7774 break;
7775 default:
7776 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
7777 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7778 return -1;
7780 break;
7781 case DAHDI_EVENT_POLARITY:
7782 switch (i->sig) {
7783 case SIG_FXSLS:
7784 case SIG_FXSKS:
7785 case SIG_FXSGS:
7786 /* We have already got a PR before the channel was
7787 created, but it wasn't handled. We need polarity
7788 to be REV for remote hangup detection to work.
7789 At least in Spain */
7790 if (i->hanguponpolarityswitch)
7791 i->polarity = POLARITY_REV;
7792 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
7793 i->polarity = POLARITY_REV;
7794 ast_verb(2, "Starting post polarity "
7795 "CID detection on channel %d\n",
7796 i->channel);
7797 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
7798 if (!chan) {
7799 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
7800 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
7801 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7802 } else {
7803 thread_spawned = 1;
7806 break;
7807 default:
7808 ast_log(LOG_WARNING, "handle_init_event detected "
7809 "polarity reversal on non-FXO (SIG_FXS) "
7810 "interface %d\n", i->channel);
7812 break;
7813 case DAHDI_EVENT_REMOVED: /* destroy channel */
7814 ast_log(LOG_NOTICE,
7815 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
7816 i->channel);
7817 dahdi_destroy_channel_bynum(i->channel);
7818 break;
7819 #ifdef HAVE_DAHDI_NEONMWI
7820 case DAHDI_EVENT_NEONMWI_ACTIVE:
7821 if (i->mwimonitor_neon) {
7822 notify_message(i->mailbox, 1);
7823 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
7825 break;
7826 case DAHDI_EVENT_NEONMWI_INACTIVE:
7827 if (i->mwimonitor_neon) {
7828 notify_message(i->mailbox, 0);
7829 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
7831 break;
7832 #endif
7834 return thread_spawned;
7837 static void *do_monitor(void *data)
7839 int count, res, res2, spoint, pollres=0;
7840 struct dahdi_pvt *i;
7841 struct dahdi_pvt *last = NULL;
7842 time_t thispass = 0, lastpass = 0;
7843 int found;
7844 char buf[1024];
7845 struct pollfd *pfds=NULL;
7846 int lastalloc = -1;
7847 /* This thread monitors all the frame relay interfaces which are not yet in use
7848 (and thus do not have a separate thread) indefinitely */
7849 /* From here on out, we die whenever asked */
7850 #if 0
7851 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
7852 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
7853 return NULL;
7855 ast_debug(1, "Monitor starting...\n");
7856 #endif
7857 for (;;) {
7858 /* Lock the interface list */
7859 ast_mutex_lock(&iflock);
7860 if (!pfds || (lastalloc != ifcount)) {
7861 if (pfds) {
7862 ast_free(pfds);
7863 pfds = NULL;
7865 if (ifcount) {
7866 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
7867 ast_mutex_unlock(&iflock);
7868 return NULL;
7871 lastalloc = ifcount;
7873 /* Build the stuff we're going to poll on, that is the socket of every
7874 dahdi_pvt that does not have an associated owner channel */
7875 count = 0;
7876 i = iflist;
7877 while (i) {
7878 if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
7879 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
7880 /* This needs to be watched, as it lacks an owner */
7881 pfds[count].fd = i->subs[SUB_REAL].zfd;
7882 pfds[count].events = POLLPRI;
7883 pfds[count].revents = 0;
7884 /* If we are monitoring for VMWI or sending CID, we need to
7885 read from the channel as well */
7886 if (i->cidspill || i->mwimonitor_fsk)
7887 pfds[count].events |= POLLIN;
7888 count++;
7891 i = i->next;
7893 /* Okay, now that we know what to do, release the interface lock */
7894 ast_mutex_unlock(&iflock);
7896 pthread_testcancel();
7897 /* Wait at least a second for something to happen */
7898 res = poll(pfds, count, 1000);
7899 pthread_testcancel();
7900 /* Okay, poll has finished. Let's see what happened. */
7901 if (res < 0) {
7902 if ((errno != EAGAIN) && (errno != EINTR))
7903 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
7904 continue;
7906 /* Alright, lock the interface list again, and let's look and see what has
7907 happened */
7908 ast_mutex_lock(&iflock);
7909 found = 0;
7910 spoint = 0;
7911 lastpass = thispass;
7912 thispass = time(NULL);
7913 i = iflist;
7914 while (i) {
7915 if (thispass != lastpass) {
7916 if (!found && ((i == last) || ((i == iflist) && !last))) {
7917 last = i;
7918 if (last) {
7919 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
7920 res = has_voicemail(last);
7921 if (last->msgstate != res) {
7923 /* This channel has a new voicemail state,
7924 * initiate a thread to send an MWI message
7926 pthread_attr_t attr;
7927 pthread_t threadid;
7928 struct mwi_thread_data *mtd;
7929 #ifdef DAHDI_VMWI
7930 res2 = ioctl(last->subs[SUB_REAL].zfd, DAHDI_VMWI, res);
7931 if (res2) {
7932 ast_log(LOG_DEBUG, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
7934 #endif
7935 pthread_attr_init(&attr);
7936 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7937 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
7938 last->msgstate = res;
7939 mtd->pvt = last;
7940 last->mwisendactive = 1;
7941 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
7942 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
7943 ast_free(mtd);
7944 last->mwisendactive = 0;
7947 found ++;
7950 last = last->next;
7954 if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
7955 if (i->radio && !i->owner)
7957 res = dahdi_get_event(i->subs[SUB_REAL].zfd);
7958 if (res)
7960 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
7961 /* Don't hold iflock while handling init events */
7962 ast_mutex_unlock(&iflock);
7963 handle_init_event(i, res);
7964 ast_mutex_lock(&iflock);
7966 i = i->next;
7967 continue;
7969 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
7970 if (pollres & POLLIN) {
7971 if (i->owner || i->subs[SUB_REAL].owner) {
7972 #ifdef HAVE_PRI
7973 if (!i->pri)
7974 #endif
7975 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].zfd);
7976 i = i->next;
7977 continue;
7979 if (!i->cidspill && !i->mwimonitor_fsk) {
7980 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
7981 i = i->next;
7982 continue;
7984 res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
7985 if (res > 0) {
7986 if (i->mwimonitor_fsk) {
7987 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
7988 pthread_attr_t attr;
7989 pthread_t threadid;
7990 struct mwi_thread_data *mtd;
7992 pthread_attr_init(&attr);
7993 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7995 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
7996 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
7997 mtd->pvt = i;
7998 memcpy(mtd->buf, buf, res);
7999 mtd->len = res;
8000 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
8001 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
8002 ast_free(mtd);
8004 i->mwimonitoractive = 1;
8008 } else {
8009 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
8012 if (pollres & POLLPRI) {
8013 if (i->owner || i->subs[SUB_REAL].owner) {
8014 #ifdef HAVE_PRI
8015 if (!i->pri)
8016 #endif
8017 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
8018 i = i->next;
8019 continue;
8021 res = dahdi_get_event(i->subs[SUB_REAL].zfd);
8022 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
8023 /* Don't hold iflock while handling init events */
8024 ast_mutex_unlock(&iflock);
8025 handle_init_event(i, res);
8026 ast_mutex_lock(&iflock);
8029 i=i->next;
8031 ast_mutex_unlock(&iflock);
8033 /* Never reached */
8034 return NULL;
8038 static int restart_monitor(void)
8040 /* If we're supposed to be stopped -- stay stopped */
8041 if (monitor_thread == AST_PTHREADT_STOP)
8042 return 0;
8043 ast_mutex_lock(&monlock);
8044 if (monitor_thread == pthread_self()) {
8045 ast_mutex_unlock(&monlock);
8046 ast_log(LOG_WARNING, "Cannot kill myself\n");
8047 return -1;
8049 if (monitor_thread != AST_PTHREADT_NULL) {
8050 /* Wake up the thread */
8051 pthread_kill(monitor_thread, SIGURG);
8052 } else {
8053 /* Start a new monitor */
8054 if (ast_pthread_create_detached_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
8055 ast_mutex_unlock(&monlock);
8056 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
8057 return -1;
8060 ast_mutex_unlock(&monlock);
8061 return 0;
8064 #ifdef HAVE_PRI
8065 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
8067 int x;
8068 int trunkgroup;
8069 /* Get appropriate trunk group if there is one */
8070 trunkgroup = pris[*span].mastertrunkgroup;
8071 if (trunkgroup) {
8072 /* Select a specific trunk group */
8073 for (x = 0; x < NUM_SPANS; x++) {
8074 if (pris[x].trunkgroup == trunkgroup) {
8075 *span = x;
8076 return 0;
8079 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
8080 *span = -1;
8081 } else {
8082 if (pris[*span].trunkgroup) {
8083 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
8084 *span = -1;
8085 } else if (pris[*span].mastertrunkgroup) {
8086 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
8087 *span = -1;
8088 } else {
8089 if (si->totalchans == 31) { /* if it's an E1 */
8090 pris[*span].dchannels[0] = 16 + offset;
8091 } else { /* T1 or BRI: D Channel is the last Channel */
8092 pris[*span].dchannels[0] =
8093 si->totalchans + offset;
8095 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
8096 pris[*span].offset = offset;
8097 pris[*span].span = *span + 1;
8100 return 0;
8103 static int pri_create_trunkgroup(int trunkgroup, int *channels)
8105 struct dahdi_spaninfo si;
8106 DAHDI_PARAMS p;
8107 int fd;
8108 int span;
8109 int ospan=0;
8110 int x,y;
8111 for (x = 0; x < NUM_SPANS; x++) {
8112 if (pris[x].trunkgroup == trunkgroup) {
8113 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
8114 return -1;
8117 for (y = 0; y < NUM_DCHANS; y++) {
8118 if (!channels[y])
8119 break;
8120 memset(&si, 0, sizeof(si));
8121 memset(&p, 0, sizeof(p));
8122 fd = open("/dev/dahdi/channel", O_RDWR);
8123 if (fd < 0) {
8124 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
8125 return -1;
8127 x = channels[y];
8128 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
8129 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
8130 dahdi_close(fd);
8131 return -1;
8133 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
8134 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
8135 return -1;
8137 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
8138 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
8139 dahdi_close(fd);
8140 return -1;
8142 span = p.spanno - 1;
8143 if (pris[span].trunkgroup) {
8144 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
8145 dahdi_close(fd);
8146 return -1;
8148 if (pris[span].pvts[0]) {
8149 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
8150 dahdi_close(fd);
8151 return -1;
8153 if (!y) {
8154 pris[span].trunkgroup = trunkgroup;
8155 pris[span].offset = channels[y] - p.chanpos;
8156 ospan = span;
8158 pris[ospan].dchannels[y] = channels[y];
8159 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
8160 pris[span].span = span + 1;
8161 dahdi_close(fd);
8163 return 0;
8166 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
8168 if (pris[span].mastertrunkgroup) {
8169 ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
8170 return -1;
8172 pris[span].mastertrunkgroup = trunkgroup;
8173 pris[span].prilogicalspan = logicalspan;
8174 return 0;
8177 #endif
8179 #ifdef HAVE_SS7
8181 static unsigned int parse_pointcode(const char *pcstring)
8183 unsigned int code1, code2, code3;
8184 int numvals;
8186 numvals = sscanf(pcstring, "%d-%d-%d", &code1, &code2, &code3);
8187 if (numvals == 1)
8188 return code1;
8189 if (numvals == 3)
8190 return (code1 << 16) | (code2 << 8) | code3;
8192 return 0;
8195 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
8197 if ((linkset < 0) || (linkset >= NUM_SPANS))
8198 return NULL;
8199 else
8200 return &linksets[linkset - 1];
8202 #endif /* HAVE_SS7 */
8204 /* converts a DAHDI sigtype to signalling as can be configured from
8205 * chan_dahdi.conf.
8206 * While both have basically the same values, this will later be the
8207 * place to add filters and sanity checks
8209 static int sigtype_to_signalling(int sigtype)
8211 return sigtype;
8214 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
8216 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
8217 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
8218 char fn[80];
8219 #if 1
8220 struct dahdi_bufferinfo bi;
8221 #endif
8222 struct dahdi_spaninfo si;
8224 int res;
8225 int span = 0;
8226 int here = 0;
8227 int x;
8228 struct dahdi_pvt **wlist;
8229 struct dahdi_pvt **wend;
8230 DAHDI_PARAMS p;
8232 wlist = &iflist;
8233 wend = &ifend;
8235 #ifdef HAVE_PRI
8236 if (pri) {
8237 wlist = &pri->crvs;
8238 wend = &pri->crvend;
8240 #endif
8242 tmp2 = *wlist;
8243 prev = NULL;
8245 while (tmp2) {
8246 if (!tmp2->destroy) {
8247 if (tmp2->channel == channel) {
8248 tmp = tmp2;
8249 here = 1;
8250 break;
8252 if (tmp2->channel > channel) {
8253 break;
8256 prev = tmp2;
8257 tmp2 = tmp2->next;
8260 if (!here && !reloading) {
8261 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
8262 destroy_dahdi_pvt(&tmp);
8263 return NULL;
8265 ast_mutex_init(&tmp->lock);
8266 ifcount++;
8267 for (x = 0; x < 3; x++)
8268 tmp->subs[x].zfd = -1;
8269 tmp->channel = channel;
8272 if (tmp) {
8273 int chan_sig = conf->chan.sig;
8274 if (!here) {
8275 if ((channel != CHAN_PSEUDO) && !pri) {
8276 snprintf(fn, sizeof(fn), "%d", channel);
8277 /* Open non-blocking */
8278 if (!here)
8279 tmp->subs[SUB_REAL].zfd = dahdi_open(fn);
8280 /* Allocate a dahdi structure */
8281 if (tmp->subs[SUB_REAL].zfd < 0) {
8282 ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
8283 destroy_dahdi_pvt(&tmp);
8284 return NULL;
8286 memset(&p, 0, sizeof(p));
8287 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &p);
8288 if (res < 0) {
8289 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
8290 destroy_dahdi_pvt(&tmp);
8291 return NULL;
8293 if (conf->is_sig_auto)
8294 chan_sig = sigtype_to_signalling(p.sigtype);
8295 if (p.sigtype != (chan_sig & 0x3ffff)) {
8296 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
8297 destroy_dahdi_pvt(&tmp);
8298 return NULL;
8300 tmp->law = p.curlaw;
8301 tmp->span = p.spanno;
8302 span = p.spanno - 1;
8303 } else {
8304 if (channel == CHAN_PSEUDO)
8305 chan_sig = 0;
8306 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
8307 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
8308 return NULL;
8311 #ifdef HAVE_SS7
8312 if (chan_sig == SIG_SS7) {
8313 struct dahdi_ss7 *ss7;
8314 int clear = 0;
8315 if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &clear)) {
8316 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
8317 destroy_dahdi_pvt(&tmp);
8318 return NULL;
8321 ss7 = ss7_resolve_linkset(cur_linkset);
8322 if (!ss7) {
8323 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
8324 destroy_dahdi_pvt(&tmp);
8325 return NULL;
8327 if (cur_cicbeginswith < 0) {
8328 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
8329 destroy_dahdi_pvt(&tmp);
8330 return NULL;
8333 tmp->cic = cur_cicbeginswith++;
8335 /* DB: Add CIC's DPC information */
8336 tmp->dpc = cur_defaultdpc;
8338 tmp->ss7 = ss7;
8339 tmp->ss7call = NULL;
8340 ss7->pvts[ss7->numchans++] = tmp;
8342 ast_copy_string(linksets[span].internationalprefix, conf->ss7.internationalprefix, sizeof(linksets[span].internationalprefix));
8343 ast_copy_string(linksets[span].nationalprefix, conf->ss7.nationalprefix, sizeof(linksets[span].nationalprefix));
8344 ast_copy_string(linksets[span].subscriberprefix, conf->ss7.subscriberprefix, sizeof(linksets[span].subscriberprefix));
8345 ast_copy_string(linksets[span].unknownprefix, conf->ss7.unknownprefix, sizeof(linksets[span].unknownprefix));
8347 linksets[span].called_nai = conf->ss7.called_nai;
8348 linksets[span].calling_nai = conf->ss7.calling_nai;
8350 #endif
8351 #ifdef HAVE_PRI
8352 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
8353 int offset;
8354 int myswitchtype;
8355 int matchesdchan;
8356 int x,y;
8357 offset = 0;
8358 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
8359 && ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &offset)) {
8360 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
8361 destroy_dahdi_pvt(&tmp);
8362 return NULL;
8364 if (span >= NUM_SPANS) {
8365 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
8366 destroy_dahdi_pvt(&tmp);
8367 return NULL;
8368 } else {
8369 si.spanno = 0;
8370 if (ioctl(tmp->subs[SUB_REAL].zfd,DAHDI_SPANSTAT,&si) == -1) {
8371 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
8372 destroy_dahdi_pvt(&tmp);
8373 return NULL;
8375 /* Store the logical span first based upon the real span */
8376 tmp->logicalspan = pris[span].prilogicalspan;
8377 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
8378 if (span < 0) {
8379 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
8380 destroy_dahdi_pvt(&tmp);
8381 return NULL;
8383 if ((chan_sig == SIG_PRI) ||
8384 (chan_sig == SIG_BRI) ||
8385 (chan_sig == SIG_BRI_PTMP))
8386 myswitchtype = conf->pri.switchtype;
8387 else
8388 myswitchtype = PRI_SWITCH_GR303_TMC;
8389 /* Make sure this isn't a d-channel */
8390 matchesdchan=0;
8391 for (x = 0; x < NUM_SPANS; x++) {
8392 for (y = 0; y < NUM_DCHANS; y++) {
8393 if (pris[x].dchannels[y] == tmp->channel) {
8394 matchesdchan = 1;
8395 break;
8399 offset = p.chanpos;
8400 if (!matchesdchan) {
8401 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
8402 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
8403 destroy_dahdi_pvt(&tmp);
8404 return NULL;
8406 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
8407 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
8408 destroy_dahdi_pvt(&tmp);
8409 return NULL;
8411 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
8412 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
8413 destroy_dahdi_pvt(&tmp);
8414 return NULL;
8416 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
8417 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
8418 destroy_dahdi_pvt(&tmp);
8419 return NULL;
8421 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
8422 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
8423 destroy_dahdi_pvt(&tmp);
8424 return NULL;
8426 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
8427 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
8428 destroy_dahdi_pvt(&tmp);
8429 return NULL;
8431 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
8432 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
8433 destroy_dahdi_pvt(&tmp);
8434 return NULL;
8436 if (pris[span].numchans >= MAX_CHANNELS) {
8437 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
8438 pris[span].trunkgroup);
8439 destroy_dahdi_pvt(&tmp);
8440 return NULL;
8443 pris[span].sig = chan_sig;
8444 pris[span].nodetype = conf->pri.nodetype;
8445 pris[span].switchtype = myswitchtype;
8446 pris[span].nsf = conf->pri.nsf;
8447 pris[span].dialplan = conf->pri.dialplan;
8448 pris[span].localdialplan = conf->pri.localdialplan;
8449 pris[span].pvts[pris[span].numchans++] = tmp;
8450 pris[span].minunused = conf->pri.minunused;
8451 pris[span].minidle = conf->pri.minidle;
8452 pris[span].overlapdial = conf->pri.overlapdial;
8453 #ifdef HAVE_PRI_INBANDRELEASE
8454 pris[span].inbandrelease = conf->pri.inbandrelease;
8455 #endif
8456 pris[span].facilityenable = conf->pri.facilityenable;
8457 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
8458 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
8459 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
8460 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
8461 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
8462 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
8463 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
8464 pris[span].resetinterval = conf->pri.resetinterval;
8466 tmp->pri = &pris[span];
8467 tmp->prioffset = offset;
8468 tmp->call = NULL;
8469 } else {
8470 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
8471 destroy_dahdi_pvt(&tmp);
8472 return NULL;
8475 } else {
8476 tmp->prioffset = 0;
8478 #endif
8479 } else {
8480 chan_sig = tmp->sig;
8481 memset(&p, 0, sizeof(p));
8482 if (tmp->subs[SUB_REAL].zfd > -1)
8483 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &p);
8485 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
8486 switch (chan_sig) {
8487 case SIG_FXSKS:
8488 case SIG_FXSLS:
8489 case SIG_EM:
8490 case SIG_EM_E1:
8491 case SIG_EMWINK:
8492 case SIG_FEATD:
8493 case SIG_FEATDMF:
8494 case SIG_FEATDMF_TA:
8495 case SIG_FEATB:
8496 case SIG_E911:
8497 case SIG_SF:
8498 case SIG_SFWINK:
8499 case SIG_FGC_CAMA:
8500 case SIG_FGC_CAMAMF:
8501 case SIG_SF_FEATD:
8502 case SIG_SF_FEATDMF:
8503 case SIG_SF_FEATB:
8504 p.starttime = 250;
8505 break;
8508 if (tmp->radio) {
8509 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
8510 p.channo = channel;
8511 p.rxwinktime = 1;
8512 p.rxflashtime = 1;
8513 p.starttime = 1;
8514 p.debouncetime = 5;
8516 if (!tmp->radio) {
8517 p.channo = channel;
8518 /* Override timing settings based on config file */
8519 if (conf->timing.prewinktime >= 0)
8520 p.prewinktime = conf->timing.prewinktime;
8521 if (conf->timing.preflashtime >= 0)
8522 p.preflashtime = conf->timing.preflashtime;
8523 if (conf->timing.winktime >= 0)
8524 p.winktime = conf->timing.winktime;
8525 if (conf->timing.flashtime >= 0)
8526 p.flashtime = conf->timing.flashtime;
8527 if (conf->timing.starttime >= 0)
8528 p.starttime = conf->timing.starttime;
8529 if (conf->timing.rxwinktime >= 0)
8530 p.rxwinktime = conf->timing.rxwinktime;
8531 if (conf->timing.rxflashtime >= 0)
8532 p.rxflashtime = conf->timing.rxflashtime;
8533 if (conf->timing.debouncetime >= 0)
8534 p.debouncetime = conf->timing.debouncetime;
8537 /* dont set parms on a pseudo-channel (or CRV) */
8538 if (tmp->subs[SUB_REAL].zfd >= 0)
8540 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_PARAMS, &p);
8541 if (res < 0) {
8542 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
8543 destroy_dahdi_pvt(&tmp);
8544 return NULL;
8547 #if 1
8548 if (!here && (tmp->subs[SUB_REAL].zfd > -1)) {
8549 memset(&bi, 0, sizeof(bi));
8550 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_BUFINFO, &bi);
8551 if (!res) {
8552 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
8553 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
8554 bi.numbufs = numbufs;
8555 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_BUFINFO, &bi);
8556 if (res < 0) {
8557 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
8559 } else
8560 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
8562 #endif
8563 tmp->immediate = conf->chan.immediate;
8564 tmp->transfertobusy = conf->chan.transfertobusy;
8565 if (chan_sig & __DAHDI_SIG_FXS) {
8566 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
8567 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
8569 tmp->sig = chan_sig;
8570 tmp->outsigmod = conf->chan.outsigmod;
8571 tmp->ringt_base = ringt_base;
8572 tmp->firstradio = 0;
8573 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
8574 tmp->permcallwaiting = conf->chan.callwaiting;
8575 else
8576 tmp->permcallwaiting = 0;
8577 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
8578 tmp->destroy = 0;
8579 tmp->drings = conf->chan.drings;
8581 /* 10 is a nice default. */
8582 if (tmp->drings.ringnum[0].range == 0)
8583 tmp->drings.ringnum[0].range = 10;
8584 if (tmp->drings.ringnum[1].range == 0)
8585 tmp->drings.ringnum[1].range = 10;
8586 if (tmp->drings.ringnum[2].range == 0)
8587 tmp->drings.ringnum[2].range = 10;
8589 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
8590 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
8591 tmp->threewaycalling = conf->chan.threewaycalling;
8592 tmp->adsi = conf->chan.adsi;
8593 tmp->use_smdi = conf->chan.use_smdi;
8594 tmp->permhidecallerid = conf->chan.hidecallerid;
8595 tmp->callreturn = conf->chan.callreturn;
8596 tmp->echocancel = conf->chan.echocancel;
8597 tmp->echotraining = conf->chan.echotraining;
8598 tmp->pulse = conf->chan.pulse;
8599 if (tmp->echocancel.head.tap_length) {
8600 tmp->echocanbridged = conf->chan.echocanbridged;
8601 } else {
8602 if (conf->chan.echocanbridged)
8603 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
8604 tmp->echocanbridged = 0;
8606 tmp->busydetect = conf->chan.busydetect;
8607 tmp->busycount = conf->chan.busycount;
8608 tmp->busy_tonelength = conf->chan.busy_tonelength;
8609 tmp->busy_quietlength = conf->chan.busy_quietlength;
8610 tmp->callprogress = conf->chan.callprogress;
8611 tmp->cancallforward = conf->chan.cancallforward;
8612 tmp->dtmfrelax = conf->chan.dtmfrelax;
8613 tmp->callwaiting = tmp->permcallwaiting;
8614 tmp->hidecallerid = tmp->permhidecallerid;
8615 tmp->channel = channel;
8616 tmp->stripmsd = conf->chan.stripmsd;
8617 tmp->use_callerid = conf->chan.use_callerid;
8618 tmp->cid_signalling = conf->chan.cid_signalling;
8619 tmp->cid_start = conf->chan.cid_start;
8620 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
8621 tmp->restrictcid = conf->chan.restrictcid;
8622 tmp->use_callingpres = conf->chan.use_callingpres;
8623 tmp->priindication_oob = conf->chan.priindication_oob;
8624 tmp->priexclusive = conf->chan.priexclusive;
8625 if (tmp->usedistinctiveringdetection) {
8626 if (!tmp->use_callerid) {
8627 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
8628 tmp->use_callerid = 1;
8632 if (tmp->cid_signalling == CID_SIG_SMDI) {
8633 if (!tmp->use_smdi) {
8634 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
8635 tmp->use_smdi = 1;
8638 if (tmp->use_smdi) {
8639 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
8640 if (!(tmp->smdi_iface)) {
8641 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
8642 tmp->use_smdi = 0;
8646 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
8647 tmp->amaflags = conf->chan.amaflags;
8648 if (!here) {
8649 tmp->confno = -1;
8650 tmp->propconfno = -1;
8652 tmp->canpark = conf->chan.canpark;
8653 tmp->transfer = conf->chan.transfer;
8654 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
8655 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
8656 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
8657 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
8658 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
8659 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
8660 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
8661 tmp->cid_ton = 0;
8662 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
8663 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
8664 if (!ast_strlen_zero(tmp->mailbox)) {
8665 char *mailbox, *context;
8666 mailbox = context = ast_strdupa(tmp->mailbox);
8667 strsep(&context, "@");
8668 if (ast_strlen_zero(context))
8669 context = "default";
8670 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
8671 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
8672 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
8673 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
8674 AST_EVENT_IE_END);
8676 tmp->msgstate = -1;
8677 tmp->group = conf->chan.group;
8678 tmp->callgroup = conf->chan.callgroup;
8679 tmp->pickupgroup= conf->chan.pickupgroup;
8680 if (conf->chan.vars) {
8681 tmp->vars = conf->chan.vars;
8683 tmp->cid_rxgain = conf->chan.cid_rxgain;
8684 tmp->rxgain = conf->chan.rxgain;
8685 tmp->txgain = conf->chan.txgain;
8686 tmp->tonezone = conf->chan.tonezone;
8687 tmp->onhooktime = time(NULL);
8688 if (tmp->subs[SUB_REAL].zfd > -1) {
8689 set_actual_gain(tmp->subs[SUB_REAL].zfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
8690 if (tmp->dsp)
8691 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
8692 update_conf(tmp);
8693 if (!here) {
8694 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
8695 /* Hang it up to be sure it's good */
8696 dahdi_set_hook(tmp->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
8698 ioctl(tmp->subs[SUB_REAL].zfd,DAHDI_SETTONEZONE,&tmp->tonezone);
8699 #ifdef HAVE_PRI
8700 /* the dchannel is down so put the channel in alarm */
8701 if (tmp->pri && !pri_is_up(tmp->pri))
8702 tmp->inalarm = 1;
8703 else
8704 tmp->inalarm = 0;
8705 #endif
8706 memset(&si, 0, sizeof(si));
8707 if (ioctl(tmp->subs[SUB_REAL].zfd,DAHDI_SPANSTAT,&si) == -1) {
8708 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
8709 destroy_dahdi_pvt(&tmp);
8710 return NULL;
8712 if (si.alarms) tmp->inalarm = 1;
8715 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
8716 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
8717 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
8718 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
8719 if (!here) {
8720 tmp->locallyblocked = tmp->remotelyblocked = 0;
8721 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
8722 tmp->inservice = 0;
8723 else /* We default to in service on protocols that don't have a reset */
8724 tmp->inservice = 1;
8727 if (tmp && !here) {
8728 /* nothing on the iflist */
8729 if (!*wlist) {
8730 *wlist = tmp;
8731 tmp->prev = NULL;
8732 tmp->next = NULL;
8733 *wend = tmp;
8734 } else {
8735 /* at least one member on the iflist */
8736 struct dahdi_pvt *working = *wlist;
8738 /* check if we maybe have to put it on the begining */
8739 if (working->channel > tmp->channel) {
8740 tmp->next = *wlist;
8741 tmp->prev = NULL;
8742 (*wlist)->prev = tmp;
8743 *wlist = tmp;
8744 } else {
8745 /* go through all the members and put the member in the right place */
8746 while (working) {
8747 /* in the middle */
8748 if (working->next) {
8749 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
8750 tmp->next = working->next;
8751 tmp->prev = working;
8752 working->next->prev = tmp;
8753 working->next = tmp;
8754 break;
8756 } else {
8757 /* the last */
8758 if (working->channel < tmp->channel) {
8759 working->next = tmp;
8760 tmp->next = NULL;
8761 tmp->prev = working;
8762 *wend = tmp;
8763 break;
8766 working = working->next;
8771 return tmp;
8774 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
8776 int res;
8777 DAHDI_PARAMS par;
8779 /* First, check group matching */
8780 if (groupmatch) {
8781 if ((p->group & groupmatch) != groupmatch)
8782 return 0;
8783 *groupmatched = 1;
8785 /* Check to see if we have a channel match */
8786 if (channelmatch != -1) {
8787 if (p->channel != channelmatch)
8788 return 0;
8789 *channelmatched = 1;
8791 /* We're at least busy at this point */
8792 if (busy) {
8793 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
8794 *busy = 1;
8796 /* If do not disturb, definitely not */
8797 if (p->dnd)
8798 return 0;
8799 /* If guard time, definitely not */
8800 if (p->guardtime && (time(NULL) < p->guardtime))
8801 return 0;
8803 if (p->locallyblocked || p->remotelyblocked)
8804 return 0;
8806 /* If no owner definitely available */
8807 if (!p->owner) {
8808 #ifdef HAVE_PRI
8809 /* Trust PRI */
8810 if (p->pri) {
8811 if (p->resetting || p->call)
8812 return 0;
8813 else
8814 return 1;
8816 #endif
8817 #ifdef HAVE_SS7
8818 /* Trust SS7 */
8819 if (p->ss7) {
8820 if (p->ss7call)
8821 return 0;
8822 else
8823 return 1;
8825 #endif
8826 if (!(p->radio || (p->oprmode < 0)))
8828 if (!p->sig || (p->sig == SIG_FXSLS))
8829 return 1;
8830 /* Check hook state */
8831 if (p->subs[SUB_REAL].zfd > -1)
8832 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &par);
8833 else {
8834 /* Assume not off hook on CVRS */
8835 res = 0;
8836 par.rxisoffhook = 0;
8838 if (res) {
8839 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
8840 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
8841 /* When "onhook" that means no battery on the line, and thus
8842 it is out of service..., if it's on a TDM card... If it's a channel
8843 bank, there is no telling... */
8844 if (par.rxbits > -1)
8845 return 1;
8846 if (par.rxisoffhook)
8847 return 1;
8848 else
8849 #ifdef DAHDI_CHECK_HOOKSTATE
8850 return 0;
8851 #else
8852 return 1;
8853 #endif
8854 } else if (par.rxisoffhook) {
8855 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
8856 /* Not available when the other end is off hook */
8857 return 0;
8860 return 1;
8863 /* If it's not an FXO, forget about call wait */
8864 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
8865 return 0;
8867 if (!p->callwaiting) {
8868 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
8869 return 0;
8872 if (p->subs[SUB_CALLWAIT].zfd > -1) {
8873 /* If there is already a call waiting call, then we can't take a second one */
8874 return 0;
8877 if ((p->owner->_state != AST_STATE_UP) &&
8878 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
8879 /* If the current call is not up, then don't allow the call */
8880 return 0;
8882 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
8883 /* Can't take a call wait when the three way calling hasn't been merged yet. */
8884 return 0;
8886 /* We're cool */
8887 return 1;
8890 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
8892 struct dahdi_pvt *p;
8893 DAHDI_BUFFERINFO bi;
8894 int res;
8896 if ((p = ast_malloc(sizeof(*p)))) {
8897 memcpy(p, src, sizeof(struct dahdi_pvt));
8898 ast_mutex_init(&p->lock);
8899 p->subs[SUB_REAL].zfd = dahdi_open("/dev/dahdi/pseudo");
8900 /* Allocate a dahdi structure */
8901 if (p->subs[SUB_REAL].zfd < 0) {
8902 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
8903 destroy_dahdi_pvt(&p);
8904 return NULL;
8906 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_BUFINFO, &bi);
8907 if (!res) {
8908 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
8909 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
8910 bi.numbufs = numbufs;
8911 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SET_BUFINFO, &bi);
8912 if (res < 0) {
8913 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
8915 } else
8916 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
8918 p->destroy = 1;
8919 p->next = iflist;
8920 p->prev = NULL;
8921 iflist = p;
8922 if (iflist->next)
8923 iflist->next->prev = p;
8924 return p;
8928 #ifdef HAVE_PRI
8929 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
8931 int x;
8932 if (backwards)
8933 x = pri->numchans;
8934 else
8935 x = 0;
8936 for (;;) {
8937 if (backwards && (x < 0))
8938 break;
8939 if (!backwards && (x >= pri->numchans))
8940 break;
8941 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
8942 ast_debug(1, "Found empty available channel %d/%d\n",
8943 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
8944 return x;
8946 if (backwards)
8947 x--;
8948 else
8949 x++;
8951 return -1;
8953 #endif
8955 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
8957 ast_group_t groupmatch = 0;
8958 int channelmatch = -1;
8959 int roundrobin = 0;
8960 int callwait = 0;
8961 int busy = 0;
8962 struct dahdi_pvt *p;
8963 struct ast_channel *tmp = NULL;
8964 char *dest=NULL;
8965 int x;
8966 char *s;
8967 char opt=0;
8968 int res=0, y=0;
8969 int backwards = 0;
8970 #ifdef HAVE_PRI
8971 int crv;
8972 int bearer = -1;
8973 int trunkgroup;
8974 struct dahdi_pri *pri=NULL;
8975 #endif
8976 struct dahdi_pvt *exit, *start, *end;
8977 ast_mutex_t *lock;
8978 int channelmatched = 0;
8979 int groupmatched = 0;
8981 /* Assume we're locking the iflock */
8982 lock = &iflock;
8983 start = iflist;
8984 end = ifend;
8985 if (data) {
8986 dest = ast_strdupa((char *)data);
8987 } else {
8988 ast_log(LOG_WARNING, "Channel requested with no data\n");
8989 return NULL;
8991 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
8992 /* Retrieve the group number */
8993 char *stringp=NULL;
8994 stringp=dest + 1;
8995 s = strsep(&stringp, "/");
8996 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
8997 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
8998 return NULL;
9000 groupmatch = ((ast_group_t) 1 << x);
9001 if (toupper(dest[0]) == 'G') {
9002 if (dest[0] == 'G') {
9003 backwards = 1;
9004 p = ifend;
9005 } else
9006 p = iflist;
9007 } else {
9008 if (dest[0] == 'R') {
9009 backwards = 1;
9010 p = round_robin[x]?round_robin[x]->prev:ifend;
9011 if (!p)
9012 p = ifend;
9013 } else {
9014 p = round_robin[x]?round_robin[x]->next:iflist;
9015 if (!p)
9016 p = iflist;
9018 roundrobin = 1;
9020 } else {
9021 char *stringp=NULL;
9022 stringp=dest;
9023 s = strsep(&stringp, "/");
9024 p = iflist;
9025 if (!strcasecmp(s, "pseudo")) {
9026 /* Special case for pseudo */
9027 x = CHAN_PSEUDO;
9028 channelmatch = x;
9030 #ifdef HAVE_PRI
9031 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
9032 if ((trunkgroup < 1) || (crv < 1)) {
9033 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
9034 return NULL;
9036 res--;
9037 for (x = 0; x < NUM_SPANS; x++) {
9038 if (pris[x].trunkgroup == trunkgroup) {
9039 pri = pris + x;
9040 lock = &pri->lock;
9041 start = pri->crvs;
9042 end = pri->crvend;
9043 break;
9046 if (!pri) {
9047 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
9048 return NULL;
9050 channelmatch = crv;
9051 p = pris[x].crvs;
9053 #endif
9054 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
9055 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
9056 return NULL;
9057 } else {
9058 channelmatch = x;
9061 /* Search for an unowned channel */
9062 ast_mutex_lock(lock);
9063 exit = p;
9064 while (p && !tmp) {
9065 if (roundrobin)
9066 round_robin[x] = p;
9067 #if 0
9068 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
9069 #endif
9071 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
9072 ast_debug(1, "Using channel %d\n", p->channel);
9073 if (p->inalarm)
9074 goto next;
9076 callwait = (p->owner != NULL);
9077 #ifdef HAVE_PRI
9078 if (pri && (p->subs[SUB_REAL].zfd < 0)) {
9079 if (p->sig != SIG_FXSKS) {
9080 /* Gotta find an actual channel to use for this
9081 CRV if this isn't a callwait */
9082 bearer = pri_find_empty_chan(pri, 0);
9083 if (bearer < 0) {
9084 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
9085 p = NULL;
9086 break;
9088 pri_assign_bearer(p, pri, pri->pvts[bearer]);
9089 } else {
9090 if (alloc_sub(p, 0)) {
9091 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
9092 p = NULL;
9093 break;
9094 } else
9095 ast_debug(1, "Allocated placeholder pseudo channel\n");
9097 p->pri = pri;
9100 #endif
9101 if (p->channel == CHAN_PSEUDO) {
9102 p = chandup(p);
9103 if (!p) {
9104 break;
9107 if (p->owner) {
9108 if (alloc_sub(p, SUB_CALLWAIT)) {
9109 p = NULL;
9110 break;
9113 p->outgoing = 1;
9114 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
9115 #ifdef HAVE_PRI
9116 if (p->bearer) {
9117 /* Log owner to bearer channel, too */
9118 p->bearer->owner = tmp;
9120 #endif
9121 /* Make special notes */
9122 if (res > 1) {
9123 if (opt == 'c') {
9124 /* Confirm answer */
9125 p->confirmanswer = 1;
9126 } else if (opt == 'r') {
9127 /* Distinctive ring */
9128 if (res < 3)
9129 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
9130 else
9131 p->distinctivering = y;
9132 } else if (opt == 'd') {
9133 /* If this is an ISDN call, make it digital */
9134 p->digital = 1;
9135 if (tmp)
9136 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
9137 } else {
9138 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
9141 /* Note if the call is a call waiting call */
9142 if (tmp && callwait)
9143 tmp->cdrflags |= AST_CDR_CALLWAIT;
9144 break;
9146 next:
9147 if (backwards) {
9148 p = p->prev;
9149 if (!p)
9150 p = end;
9151 } else {
9152 p = p->next;
9153 if (!p)
9154 p = start;
9156 /* stop when you roll to the one that we started from */
9157 if (p == exit)
9158 break;
9160 ast_mutex_unlock(lock);
9161 restart_monitor();
9162 if (callwait)
9163 *cause = AST_CAUSE_BUSY;
9164 else if (!tmp) {
9165 if (channelmatched) {
9166 if (busy)
9167 *cause = AST_CAUSE_BUSY;
9168 } else if (groupmatched) {
9169 *cause = AST_CAUSE_CONGESTION;
9173 return tmp;
9176 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9177 static int dahdi_setlaw(int zfd, int law)
9179 return ioctl(zfd, DAHDI_SETLAW, &law);
9181 #endif
9183 #ifdef HAVE_SS7
9185 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
9187 int i;
9188 int winner = -1;
9189 for (i = 0; i < linkset->numchans; i++) {
9190 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
9191 winner = i;
9192 break;
9195 return winner;
9198 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
9200 unsigned char status[32];
9201 struct dahdi_pvt *p = NULL;
9202 int i, offset;
9204 for (i = 0; i < linkset->numchans; i++) {
9205 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
9206 p = linkset->pvts[i];
9207 offset = p->cic - startcic;
9208 status[offset] = 0;
9209 if (p->locallyblocked)
9210 status[offset] |= (1 << 0) | (1 << 4);
9211 if (p->remotelyblocked)
9212 status[offset] |= (1 << 1) | (1 << 5);
9213 if (p->ss7call) {
9214 if (p->outgoing)
9215 status[offset] |= (1 << 3);
9216 else
9217 status[offset] |= (1 << 2);
9218 } else
9219 status[offset] |= 0x3 << 2;
9223 if (p)
9224 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
9225 else
9226 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
9230 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
9232 int i;
9234 for (i = 0; i < linkset->numchans; i++) {
9235 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
9236 if (state) {
9237 if (state[i])
9238 linkset->pvts[i]->remotelyblocked = block;
9239 } else
9240 linkset->pvts[i]->remotelyblocked = block;
9245 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
9247 int i;
9249 for (i = 0; i < linkset->numchans; i++) {
9250 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
9251 linkset->pvts[i]->inservice = 1;
9255 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
9257 int i, startcic = -1, endcic, dpc;
9259 if (linkset->numchans <= 0)
9260 return;
9262 startcic = linkset->pvts[0]->cic;
9263 /* DB: CIC's DPC fix */
9264 dpc = linkset->pvts[0]->dpc;
9266 for (i = 0; i < linkset->numchans; i++) {
9267 if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
9268 continue;
9269 } else {
9270 endcic = linkset->pvts[i]->cic;
9271 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
9272 isup_grs(linkset->ss7, startcic, endcic, dpc);
9274 /* DB: CIC's DPC fix */
9275 if (linkset->pvts[i+1]) {
9276 startcic = linkset->pvts[i+1]->cic;
9277 dpc = linkset->pvts[i+1]->dpc;
9283 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
9285 if (p->loopedback != enable) {
9286 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_LOOPBACK, &enable)) {
9287 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
9288 return;
9290 p->loopedback = enable;
9294 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
9295 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
9297 struct ss7 *ss7 = linkset->ss7;
9298 int res;
9299 int law = 1;
9300 struct ast_channel *c;
9301 char tmp[256];
9303 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &law) == -1)
9304 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
9306 if (linkset->type == SS7_ITU)
9307 law = DAHDI_LAW_ALAW;
9308 else
9309 law = DAHDI_LAW_MULAW;
9311 res = dahdi_setlaw(p->subs[SUB_REAL].zfd, law);
9312 if (res < 0)
9313 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
9315 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
9316 p->proceeding = 1;
9317 isup_acm(ss7, p->ss7call);
9320 ast_mutex_unlock(&linkset->lock);
9321 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
9323 if (!c) {
9324 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
9325 /* Holding this lock is assumed entering the function */
9326 ast_mutex_lock(&linkset->lock);
9327 return;
9328 } else
9329 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
9331 dahdi_enable_ec(p);
9333 /* We only reference these variables in the context of the ss7_linkset function
9334 * when receiving either and IAM or a COT message. Since they are only accessed
9335 * from this context, we should be safe to unlock around them */
9337 ast_mutex_unlock(&p->lock);
9339 if (!ast_strlen_zero(p->charge_number)) {
9340 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
9341 /* Clear this after we set it */
9342 p->charge_number[0] = 0;
9344 if (!ast_strlen_zero(p->gen_add_number)) {
9345 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
9346 /* Clear this after we set it */
9347 p->gen_add_number[0] = 0;
9349 if (!ast_strlen_zero(p->jip_number)) {
9350 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
9351 /* Clear this after we set it */
9352 p->jip_number[0] = 0;
9354 if (!ast_strlen_zero(p->gen_dig_number)) {
9355 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
9356 /* Clear this after we set it */
9357 p->gen_dig_number[0] = 0;
9359 if (!ast_strlen_zero(p->orig_called_num)) {
9360 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
9361 /* Clear this after we set it */
9362 p->orig_called_num[0] = 0;
9365 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
9366 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
9367 /* Clear this after we set it */
9368 p->gen_dig_type = 0;
9370 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
9371 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
9372 /* Clear this after we set it */
9373 p->gen_dig_scheme = 0;
9375 if (!ast_strlen_zero(p->lspi_ident)) {
9376 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
9377 /* Clear this after we set it */
9378 p->lspi_ident[0] = 0;
9381 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
9382 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
9383 /* Clear this after we set it */
9384 p->call_ref_ident = 0;
9386 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
9387 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
9388 /* Clear this after we set it */
9389 p->call_ref_pc = 0;
9391 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
9392 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
9393 /* Clear this after we set it */
9394 p->calling_party_cat = 0;
9396 if (!ast_strlen_zero(p->redirecting_num)) {
9397 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
9398 /* Clear this after we set it */
9399 p->redirecting_num[0] = 0;
9401 if (!ast_strlen_zero(p->generic_name)) {
9402 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
9403 /* Clear this after we set it */
9404 p->generic_name[0] = 0;
9407 ast_mutex_lock(&p->lock);
9408 ast_mutex_lock(&linkset->lock);
9411 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
9413 switch (nai) {
9414 case SS7_NAI_INTERNATIONAL:
9415 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
9416 break;
9417 case SS7_NAI_NATIONAL:
9418 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
9419 break;
9420 case SS7_NAI_SUBSCRIBER:
9421 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
9422 break;
9423 case SS7_NAI_UNKNOWN:
9424 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
9425 break;
9426 default:
9427 snprintf(buf, size, "%s", number);
9428 break;
9431 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
9433 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
9436 static void *ss7_linkset(void *data)
9438 int res, i;
9439 struct timeval *next = NULL, tv;
9440 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
9441 struct ss7 *ss7 = linkset->ss7;
9442 ss7_event *e = NULL;
9443 struct dahdi_pvt *p;
9444 int chanpos;
9445 struct pollfd pollers[NUM_DCHANS];
9446 int cic;
9447 unsigned int dpc;
9448 int nextms = 0;
9450 ss7_start(ss7);
9452 while(1) {
9453 ast_mutex_lock(&linkset->lock);
9454 if ((next = ss7_schedule_next(ss7))) {
9455 tv = ast_tvnow();
9456 tv.tv_sec = next->tv_sec - tv.tv_sec;
9457 tv.tv_usec = next->tv_usec - tv.tv_usec;
9458 if (tv.tv_usec < 0) {
9459 tv.tv_usec += 1000000;
9460 tv.tv_sec -= 1;
9462 if (tv.tv_sec < 0) {
9463 tv.tv_sec = 0;
9464 tv.tv_usec = 0;
9466 nextms = tv.tv_sec * 1000;
9467 nextms += tv.tv_usec / 1000;
9469 ast_mutex_unlock(&linkset->lock);
9471 for (i = 0; i < linkset->numsigchans; i++) {
9472 pollers[i].fd = linkset->fds[i];
9473 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
9474 pollers[i].revents = 0;
9477 res = poll(pollers, linkset->numsigchans, nextms);
9478 if ((res < 0) && (errno != EINTR)) {
9479 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
9480 } else if (!res) {
9481 ast_mutex_lock(&linkset->lock);
9482 ss7_schedule_run(ss7);
9483 ast_mutex_unlock(&linkset->lock);
9484 continue;
9487 ast_mutex_lock(&linkset->lock);
9488 for (i = 0; i < linkset->numsigchans; i++) {
9489 if (pollers[i].revents & POLLPRI) {
9490 int x;
9491 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
9492 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
9494 switch (x) {
9495 case DAHDI_EVENT_OVERRUN:
9496 ast_debug(1, "Overrun detected!\n");
9497 break;
9498 case DAHDI_EVENT_BADFCS:
9499 ast_debug(1, "Bad FCS\n");
9500 break;
9501 case DAHDI_EVENT_ABORT:
9502 ast_debug(1, "HDLC Abort\n");
9503 break;
9504 case DAHDI_EVENT_ALARM:
9505 ast_log(LOG_ERROR, "Alarm on link!\n");
9506 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
9507 linkset->linkstate[i] &= ~LINKSTATE_UP;
9508 ss7_link_alarm(ss7, pollers[i].fd);
9509 break;
9510 case DAHDI_EVENT_NOALARM:
9511 ast_log(LOG_ERROR, "Alarm cleared on link\n");
9512 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
9513 linkset->linkstate[i] |= LINKSTATE_STARTING;
9514 ss7_link_noalarm(ss7, pollers[i].fd);
9515 break;
9516 default:
9517 ast_log(LOG_ERROR, "Got exception %d!\n", x);
9518 break;
9522 if (pollers[i].revents & POLLIN) {
9523 ast_mutex_lock(&linkset->lock);
9524 res = ss7_read(ss7, pollers[i].fd);
9525 ast_mutex_unlock(&linkset->lock);
9528 if (pollers[i].revents & POLLOUT) {
9529 ast_mutex_lock(&linkset->lock);
9530 res = ss7_write(ss7, pollers[i].fd);
9531 ast_mutex_unlock(&linkset->lock);
9532 if (res < 0) {
9533 ast_debug(1, "Error in write %s\n", strerror(errno));
9538 while ((e = ss7_check_event(ss7))) {
9539 switch (e->e) {
9540 case SS7_EVENT_UP:
9541 if (linkset->state != LINKSET_STATE_UP) {
9542 ast_verbose("--- SS7 Up ---\n");
9543 ss7_reset_linkset(linkset);
9545 linkset->state = LINKSET_STATE_UP;
9546 break;
9547 case SS7_EVENT_DOWN:
9548 ast_verbose("--- SS7 Down ---\n");
9549 linkset->state = LINKSET_STATE_DOWN;
9550 for (i = 0; i < linkset->numchans; i++) {
9551 struct dahdi_pvt *p = linkset->pvts[i];
9552 if (p)
9553 p->inalarm = 1;
9555 break;
9556 case MTP2_LINK_UP:
9557 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
9558 break;
9559 case MTP2_LINK_DOWN:
9560 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
9561 break;
9562 case ISUP_EVENT_CPG:
9563 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
9564 if (chanpos < 0) {
9565 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
9566 break;
9568 p = linkset->pvts[chanpos];
9569 ast_mutex_lock(&p->lock);
9570 switch (e->cpg.event) {
9571 case CPG_EVENT_ALERTING:
9572 p->alerting = 1;
9573 p->subs[SUB_REAL].needringing = 1;
9574 break;
9575 case CPG_EVENT_PROGRESS:
9576 case CPG_EVENT_INBANDINFO:
9578 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9579 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
9580 dahdi_queue_frame(p, &f, linkset);
9581 p->progress = 1;
9582 if (p->dsp && p->dsp_features) {
9583 ast_dsp_set_features(p->dsp, p->dsp_features);
9584 p->dsp_features = 0;
9587 break;
9588 default:
9589 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
9592 ast_mutex_unlock(&p->lock);
9593 break;
9594 case ISUP_EVENT_RSC:
9595 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
9596 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
9597 if (chanpos < 0) {
9598 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
9599 break;
9601 p = linkset->pvts[chanpos];
9602 ast_mutex_lock(&p->lock);
9603 p->inservice = 1;
9604 p->remotelyblocked = 0;
9605 dpc = p->dpc;
9606 isup_set_call_dpc(e->rsc.call, dpc);
9607 if (p->ss7call)
9608 p->ss7call = NULL;
9609 if (p->owner)
9610 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9611 ast_mutex_unlock(&p->lock);
9612 isup_rlc(ss7, e->rsc.call);
9613 break;
9614 case ISUP_EVENT_GRS:
9615 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
9616 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
9617 if (chanpos < 0) {
9618 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
9619 break;
9621 p = linkset->pvts[chanpos];
9622 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
9623 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
9624 break;
9625 case ISUP_EVENT_CQM:
9626 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
9627 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
9628 break;
9629 case ISUP_EVENT_GRA:
9630 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
9631 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
9632 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
9633 break;
9634 case ISUP_EVENT_IAM:
9635 ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
9636 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
9637 if (chanpos < 0) {
9638 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
9639 isup_rel(ss7, e->iam.call, -1);
9640 break;
9642 p = linkset->pvts[chanpos];
9643 ast_mutex_lock(&p->lock);
9644 if (p->owner) {
9645 if (p->ss7call == e->iam.call) {
9646 ast_mutex_unlock(&p->lock);
9647 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
9648 break;
9649 } else {
9650 ast_mutex_unlock(&p->lock);
9651 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
9652 break;
9656 dpc = p->dpc;
9657 p->ss7call = e->iam.call;
9658 isup_set_call_dpc(p->ss7call, dpc);
9660 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
9661 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
9662 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
9663 } else
9664 p->cid_num[0] = 0;
9666 if (p->immediate) {
9667 p->exten[0] = 's';
9668 p->exten[1] = '\0';
9669 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
9670 char *st;
9671 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
9672 st = strchr(p->exten, '#');
9673 if (st)
9674 *st = '\0';
9675 } else
9676 p->exten[0] = '\0';
9678 p->cid_ani[0] = '\0';
9679 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
9680 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
9681 else
9682 p->cid_name[0] = '\0';
9684 p->cid_ani2 = e->iam.oli_ani2;
9685 p->cid_ton = 0;
9686 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
9687 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
9688 p->gen_add_type = e->iam.gen_add_type;
9689 p->gen_add_nai = e->iam.gen_add_nai;
9690 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
9691 p->gen_add_num_plan = e->iam.gen_add_num_plan;
9692 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
9693 p->gen_dig_type = e->iam.gen_dig_type;
9694 p->gen_dig_scheme = e->iam.gen_dig_scheme;
9695 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
9696 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
9697 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
9698 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
9699 p->calling_party_cat = e->iam.calling_party_cat;
9701 /* Set DNID */
9702 if (!ast_strlen_zero(e->iam.called_party_num))
9703 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
9705 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
9707 if (e->iam.cot_check_required) {
9708 dahdi_loopback(p, 1);
9709 } else
9710 ss7_start_call(p, linkset);
9711 } else {
9712 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
9713 isup_rel(ss7, e->iam.call, -1);
9715 ast_mutex_unlock(&p->lock);
9716 break;
9717 case ISUP_EVENT_COT:
9718 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
9719 if (chanpos < 0) {
9720 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
9721 isup_rel(ss7, e->cot.call, -1);
9722 break;
9724 p = linkset->pvts[chanpos];
9726 ast_mutex_lock(&p->lock);
9728 if (p->loopedback) {
9729 dahdi_loopback(p, 0);
9730 ss7_start_call(p, linkset);
9733 ast_mutex_unlock(&p->lock);
9735 break;
9736 case ISUP_EVENT_CCR:
9737 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
9738 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
9739 if (chanpos < 0) {
9740 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
9741 break;
9744 p = linkset->pvts[chanpos];
9746 ast_mutex_lock(&p->lock);
9747 dahdi_loopback(p, 1);
9748 ast_mutex_unlock(&p->lock);
9750 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
9751 break;
9752 case ISUP_EVENT_CVT:
9753 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
9754 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
9755 if (chanpos < 0) {
9756 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
9757 break;
9760 p = linkset->pvts[chanpos];
9762 ast_mutex_lock(&p->lock);
9763 dahdi_loopback(p, 1);
9764 ast_mutex_unlock(&p->lock);
9766 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
9767 break;
9768 case ISUP_EVENT_REL:
9769 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
9770 if (chanpos < 0) {
9771 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
9772 break;
9774 p = linkset->pvts[chanpos];
9775 ast_mutex_lock(&p->lock);
9776 if (p->owner) {
9777 p->owner->hangupcause = e->rel.cause;
9778 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9779 } else
9780 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
9782 /* End the loopback if we have one */
9783 dahdi_loopback(p, 0);
9785 isup_rlc(ss7, e->rel.call);
9786 p->ss7call = NULL;
9788 ast_mutex_unlock(&p->lock);
9789 break;
9790 case ISUP_EVENT_ACM:
9791 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
9792 if (chanpos < 0) {
9793 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
9794 isup_rel(ss7, e->acm.call, -1);
9795 break;
9796 } else {
9797 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9799 p = linkset->pvts[chanpos];
9801 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
9803 if (e->acm.call_ref_ident > 0) {
9804 p->rlt = 1; /* Setting it but not using it here*/
9807 ast_mutex_lock(&p->lock);
9808 dahdi_queue_frame(p, &f, linkset);
9809 p->proceeding = 1;
9810 /* Send alerting if subscriber is free */
9811 if (e->acm.called_party_status_ind == 1) {
9812 p->alerting = 1;
9813 p->subs[SUB_REAL].needringing = 1;
9815 ast_mutex_unlock(&p->lock);
9817 break;
9818 case ISUP_EVENT_CGB:
9819 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
9820 if (chanpos < 0) {
9821 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
9822 break;
9824 p = linkset->pvts[chanpos];
9825 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
9826 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
9827 break;
9828 case ISUP_EVENT_CGU:
9829 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
9830 if (chanpos < 0) {
9831 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
9832 break;
9834 p = linkset->pvts[chanpos];
9835 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
9836 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
9837 break;
9838 case ISUP_EVENT_UCIC:
9839 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
9840 if (chanpos < 0) {
9841 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
9842 break;
9844 p = linkset->pvts[chanpos];
9845 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
9846 ast_mutex_lock(&p->lock);
9847 p->remotelyblocked = 1;
9848 p->inservice = 0;
9849 ast_mutex_unlock(&p->lock); //doesn't require a SS7 acknowledgement
9850 break;
9851 case ISUP_EVENT_BLO:
9852 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
9853 if (chanpos < 0) {
9854 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
9855 break;
9857 p = linkset->pvts[chanpos];
9858 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
9859 ast_mutex_lock(&p->lock);
9860 p->remotelyblocked = 1;
9861 ast_mutex_unlock(&p->lock);
9862 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
9863 break;
9864 case ISUP_EVENT_BLA:
9865 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
9866 if (chanpos < 0) {
9867 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
9868 break;
9870 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
9871 p = linkset->pvts[chanpos];
9872 ast_mutex_lock(&p->lock);
9873 p->locallyblocked = 1;
9874 ast_mutex_unlock(&p->lock);
9875 break;
9876 case ISUP_EVENT_UBL:
9877 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
9878 if (chanpos < 0) {
9879 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
9880 break;
9882 p = linkset->pvts[chanpos];
9883 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
9884 ast_mutex_lock(&p->lock);
9885 p->remotelyblocked = 0;
9886 ast_mutex_unlock(&p->lock);
9887 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
9888 break;
9889 case ISUP_EVENT_UBA:
9890 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
9891 if (chanpos < 0) {
9892 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
9893 break;
9895 p = linkset->pvts[chanpos];
9896 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
9897 ast_mutex_lock(&p->lock);
9898 p->locallyblocked = 0;
9899 ast_mutex_unlock(&p->lock);
9900 break;
9901 case ISUP_EVENT_CON:
9902 case ISUP_EVENT_ANM:
9903 if (e->e == ISUP_EVENT_CON)
9904 cic = e->con.cic;
9905 else
9906 cic = e->anm.cic;
9908 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
9909 if (chanpos < 0) {
9910 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
9911 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
9912 break;
9913 } else {
9914 p = linkset->pvts[chanpos];
9915 ast_mutex_lock(&p->lock);
9916 p->subs[SUB_REAL].needanswer = 1;
9917 if (p->dsp && p->dsp_features) {
9918 ast_dsp_set_features(p->dsp, p->dsp_features);
9919 p->dsp_features = 0;
9921 dahdi_enable_ec(p);
9922 ast_mutex_unlock(&p->lock);
9924 break;
9925 case ISUP_EVENT_RLC:
9926 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
9927 if (chanpos < 0) {
9928 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
9929 break;
9930 } else {
9931 p = linkset->pvts[chanpos];
9932 ast_mutex_lock(&p->lock);
9933 if (p->alreadyhungup)
9934 p->ss7call = NULL;
9935 else
9936 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
9937 ast_mutex_unlock(&p->lock);
9939 break;
9940 case ISUP_EVENT_FAA:
9941 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
9942 if (chanpos < 0) {
9943 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
9944 break;
9945 } else {
9946 p = linkset->pvts[chanpos];
9947 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
9948 ast_mutex_lock(&p->lock);
9949 if (p->alreadyhungup){
9950 p->ss7call = NULL;
9951 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
9953 ast_mutex_unlock(&p->lock);
9955 break;
9956 default:
9957 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
9958 break;
9961 ast_mutex_unlock(&linkset->lock);
9964 return 0;
9967 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
9969 #if 0
9970 int i;
9972 for (i = 0; i < NUM_SPANS; i++)
9973 if (linksets[i].ss7 == ss7)
9974 break;
9976 ast_verbose("[%d] %s", i+1, s);
9977 #else
9978 ast_verbose("%s", s);
9979 #endif
9982 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
9984 #if 0
9985 int i;
9987 for (i = 0; i < NUM_SPANS; i++)
9988 if (linksets[i].ss7 == ss7)
9989 break;
9991 #else
9992 ast_log(LOG_ERROR, "%s", s);
9993 #endif
9996 #endif /* HAVE_SS7 */
9998 #ifdef HAVE_PRI
9999 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
10001 struct dahdi_pvt *p;
10002 p = pri->crvs;
10003 while (p) {
10004 if (p->channel == crv)
10005 return p;
10006 p = p->next;
10008 return NULL;
10012 static int pri_find_principle(struct dahdi_pri *pri, int channel)
10014 int x;
10015 int span = PRI_SPAN(channel);
10016 int spanfd;
10017 DAHDI_PARAMS param;
10018 int principle = -1;
10019 int explicit = PRI_EXPLICIT(channel);
10020 channel = PRI_CHANNEL(channel);
10022 if (!explicit) {
10023 spanfd = pri_active_dchan_fd(pri);
10024 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10025 return -1;
10026 span = pris[param.spanno - 1].prilogicalspan;
10029 for (x = 0; x < pri->numchans; x++) {
10030 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10031 principle = x;
10032 break;
10036 return principle;
10039 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10041 int x;
10042 struct dahdi_pvt *crv;
10043 if (!c) {
10044 if (principle < 0)
10045 return -1;
10046 return principle;
10048 if ((principle > -1) &&
10049 (principle < pri->numchans) &&
10050 (pri->pvts[principle]) &&
10051 (pri->pvts[principle]->call == c))
10052 return principle;
10053 /* First, check for other bearers */
10054 for (x = 0; x < pri->numchans; x++) {
10055 if (!pri->pvts[x])
10056 continue;
10057 if (pri->pvts[x]->call == c) {
10058 /* Found our call */
10059 if (principle != x) {
10060 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10062 ast_verb(3, "Moving call from channel %d to channel %d\n",
10063 old->channel, new->channel);
10064 if (new->owner) {
10065 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10066 old->channel, new->channel, new->channel);
10067 return -1;
10069 /* Fix it all up now */
10070 new->owner = old->owner;
10071 old->owner = NULL;
10072 if (new->owner) {
10073 ast_string_field_build(new->owner, name,
10074 "DAHDI/%d:%d-%d", pri->trunkgroup,
10075 new->channel, 1);
10076 new->owner->tech_pvt = new;
10077 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].zfd);
10078 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10079 old->subs[SUB_REAL].owner = NULL;
10080 } else
10081 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
10082 new->call = old->call;
10083 old->call = NULL;
10085 /* Copy any DSP that may be present */
10086 new->dsp = old->dsp;
10087 new->dsp_features = old->dsp_features;
10088 old->dsp = NULL;
10089 old->dsp_features = 0;
10091 return principle;
10094 /* Now check for a CRV with no bearer */
10095 crv = pri->crvs;
10096 while (crv) {
10097 if (crv->call == c) {
10098 /* This is our match... Perform some basic checks */
10099 if (crv->bearer)
10100 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10101 else if (pri->pvts[principle]->owner)
10102 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10103 else {
10104 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
10105 wakeup the potential sleeper */
10106 dahdi_close(crv->subs[SUB_REAL].zfd);
10107 pri->pvts[principle]->call = crv->call;
10108 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10109 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10110 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10111 pri->trunkgroup, crv->channel);
10112 wakeup_sub(crv, SUB_REAL, pri);
10114 return principle;
10116 crv = crv->next;
10118 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10119 return -1;
10122 static void *do_idle_thread(void *vchan)
10124 struct ast_channel *chan = vchan;
10125 struct dahdi_pvt *pvt = chan->tech_pvt;
10126 struct ast_frame *f;
10127 char ex[80];
10128 /* Wait up to 30 seconds for an answer */
10129 int newms, ms = 30000;
10130 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10131 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10132 if (ast_call(chan, ex, 0)) {
10133 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10134 ast_hangup(chan);
10135 return NULL;
10137 while ((newms = ast_waitfor(chan, ms)) > 0) {
10138 f = ast_read(chan);
10139 if (!f) {
10140 /* Got hangup */
10141 break;
10143 if (f->frametype == AST_FRAME_CONTROL) {
10144 switch (f->subclass) {
10145 case AST_CONTROL_ANSWER:
10146 /* Launch the PBX */
10147 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10148 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10149 chan->priority = 1;
10150 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10151 ast_pbx_run(chan);
10152 /* It's already hungup, return immediately */
10153 return NULL;
10154 case AST_CONTROL_BUSY:
10155 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10156 break;
10157 case AST_CONTROL_CONGESTION:
10158 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10159 break;
10162 ast_frfree(f);
10163 ms = newms;
10165 /* Hangup the channel since nothing happend */
10166 ast_hangup(chan);
10167 return NULL;
10170 #ifndef PRI_RESTART
10171 #error "Upgrade your libpri"
10172 #endif
10173 static void dahdi_pri_message(struct pri *pri, char *s)
10175 int x, y;
10176 int dchan = -1, span = -1;
10177 int dchancount = 0;
10179 if (pri) {
10180 for (x = 0; x < NUM_SPANS; x++) {
10181 for (y = 0; y < NUM_DCHANS; y++) {
10182 if (pris[x].dchans[y])
10183 dchancount++;
10185 if (pris[x].dchans[y] == pri)
10186 dchan = y;
10188 if (dchan >= 0) {
10189 span = x;
10190 break;
10192 dchancount = 0;
10194 if (dchancount > 1 && (span > -1))
10195 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10196 else
10197 ast_verbose("%s", s);
10198 } else
10199 ast_verbose("%s", s);
10201 ast_mutex_lock(&pridebugfdlock);
10203 if (pridebugfd >= 0)
10204 write(pridebugfd, s, strlen(s));
10206 ast_mutex_unlock(&pridebugfdlock);
10209 static void dahdi_pri_error(struct pri *pri, char *s)
10211 int x, y;
10212 int dchan = -1, span = -1;
10213 int dchancount = 0;
10215 if (pri) {
10216 for (x = 0; x < NUM_SPANS; x++) {
10217 for (y = 0; y < NUM_DCHANS; y++) {
10218 if (pris[x].dchans[y])
10219 dchancount++;
10221 if (pris[x].dchans[y] == pri)
10222 dchan = y;
10224 if (dchan >= 0) {
10225 span = x;
10226 break;
10228 dchancount = 0;
10230 if ((dchancount > 1) && (span > -1))
10231 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10232 else
10233 ast_log(LOG_ERROR, "%s", s);
10234 } else
10235 ast_log(LOG_ERROR, "%s", s);
10237 ast_mutex_lock(&pridebugfdlock);
10239 if (pridebugfd >= 0)
10240 write(pridebugfd, s, strlen(s));
10242 ast_mutex_unlock(&pridebugfdlock);
10245 static int pri_check_restart(struct dahdi_pri *pri)
10247 do {
10248 pri->resetpos++;
10249 } while ((pri->resetpos < pri->numchans) &&
10250 (!pri->pvts[pri->resetpos] ||
10251 pri->pvts[pri->resetpos]->call ||
10252 pri->pvts[pri->resetpos]->resetting));
10253 if (pri->resetpos < pri->numchans) {
10254 /* Mark the channel as resetting and restart it */
10255 pri->pvts[pri->resetpos]->resetting = 1;
10256 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10257 } else {
10258 pri->resetting = 0;
10259 time(&pri->lastreset);
10261 return 0;
10264 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10266 int x;
10267 int redo;
10268 ast_mutex_unlock(&pri->lock);
10269 ast_mutex_lock(&p->lock);
10270 do {
10271 redo = 0;
10272 for (x = 0; x < 3; x++) {
10273 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10274 redo++;
10275 DEADLOCK_AVOIDANCE(&p->lock);
10277 if (p->subs[x].owner) {
10278 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10279 ast_channel_unlock(p->subs[x].owner);
10282 } while (redo);
10283 ast_mutex_unlock(&p->lock);
10284 ast_mutex_lock(&pri->lock);
10285 return 0;
10288 static char * redirectingreason2str(int redirectingreason)
10290 switch (redirectingreason) {
10291 case 0:
10292 return "UNKNOWN";
10293 case 1:
10294 return "BUSY";
10295 case 2:
10296 return "NO_REPLY";
10297 case 0xF:
10298 return "UNCONDITIONAL";
10299 default:
10300 return "NOREDIRECT";
10304 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10306 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10307 snprintf(buf, size, "%s", number);
10308 return;
10310 switch (plan) {
10311 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10312 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10313 break;
10314 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10315 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10316 break;
10317 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10318 snprintf(buf, size, "%s%s", pri->localprefix, number);
10319 break;
10320 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10321 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10322 break;
10323 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10324 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10325 break;
10326 default: /* other Q.931 dialplan => don't twiddle with callingnum */
10327 snprintf(buf, size, "%s", number);
10328 break;
10333 static void *pri_dchannel(void *vpri)
10335 struct dahdi_pri *pri = vpri;
10336 pri_event *e;
10337 struct pollfd fds[NUM_DCHANS];
10338 int res;
10339 int chanpos = 0;
10340 int x;
10341 int haveidles;
10342 int activeidles;
10343 int nextidle = -1;
10344 struct ast_channel *c;
10345 struct timeval tv, lowest, *next;
10346 struct timeval lastidle = ast_tvnow();
10347 int doidling=0;
10348 char *cc;
10349 char idlen[80];
10350 struct ast_channel *idle;
10351 pthread_t p;
10352 time_t t;
10353 int i, which=-1;
10354 int numdchans;
10355 int cause=0;
10356 struct dahdi_pvt *crv;
10357 pthread_t threadid;
10358 char ani2str[6];
10359 char plancallingnum[256];
10360 char plancallingani[256];
10361 char calledtonstr[10];
10363 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10364 /* Need to do idle dialing, check to be sure though */
10365 cc = strchr(pri->idleext, '@');
10366 if (cc) {
10367 *cc = '\0';
10368 cc++;
10369 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10370 #if 0
10371 /* Extensions may not be loaded yet */
10372 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10373 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10374 else
10375 #endif
10376 doidling = 1;
10377 } else
10378 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10380 for (;;) {
10381 for (i = 0; i < NUM_DCHANS; i++) {
10382 if (!pri->dchannels[i])
10383 break;
10384 fds[i].fd = pri->fds[i];
10385 fds[i].events = POLLIN | POLLPRI;
10386 fds[i].revents = 0;
10388 numdchans = i;
10389 time(&t);
10390 ast_mutex_lock(&pri->lock);
10391 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10392 if (pri->resetting && pri_is_up(pri)) {
10393 if (pri->resetpos < 0)
10394 pri_check_restart(pri);
10395 } else {
10396 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10397 pri->resetting = 1;
10398 pri->resetpos = -1;
10402 /* Look for any idle channels if appropriate */
10403 if (doidling && pri_is_up(pri)) {
10404 nextidle = -1;
10405 haveidles = 0;
10406 activeidles = 0;
10407 for (x = pri->numchans; x >= 0; x--) {
10408 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10409 !pri->pvts[x]->call) {
10410 if (haveidles < pri->minunused) {
10411 haveidles++;
10412 } else if (!pri->pvts[x]->resetting) {
10413 nextidle = x;
10414 break;
10416 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10417 activeidles++;
10419 if (nextidle > -1) {
10420 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10421 /* Don't create a new idle call more than once per second */
10422 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10423 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10424 if (idle) {
10425 pri->pvts[nextidle]->isidlecall = 1;
10426 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10427 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10428 dahdi_hangup(idle);
10430 } else
10431 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10432 lastidle = ast_tvnow();
10434 } else if ((haveidles < pri->minunused) &&
10435 (activeidles > pri->minidle)) {
10436 /* Mark something for hangup if there is something
10437 that can be hungup */
10438 for (x = pri->numchans; x >= 0; x--) {
10439 /* find a candidate channel */
10440 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10441 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10442 haveidles++;
10443 /* Stop if we have enough idle channels or
10444 can't spare any more active idle ones */
10445 if ((haveidles >= pri->minunused) ||
10446 (activeidles <= pri->minidle))
10447 break;
10452 /* Start with reasonable max */
10453 lowest = ast_tv(60, 0);
10454 for (i = 0; i < NUM_DCHANS; i++) {
10455 /* Find lowest available d-channel */
10456 if (!pri->dchannels[i])
10457 break;
10458 if ((next = pri_schedule_next(pri->dchans[i]))) {
10459 /* We need relative time here */
10460 tv = ast_tvsub(*next, ast_tvnow());
10461 if (tv.tv_sec < 0) {
10462 tv = ast_tv(0,0);
10464 if (doidling || pri->resetting) {
10465 if (tv.tv_sec > 1) {
10466 tv = ast_tv(1, 0);
10468 } else {
10469 if (tv.tv_sec > 60) {
10470 tv = ast_tv(60, 0);
10473 } else if (doidling || pri->resetting) {
10474 /* Make sure we stop at least once per second if we're
10475 monitoring idle channels */
10476 tv = ast_tv(1,0);
10477 } else {
10478 /* Don't poll for more than 60 seconds */
10479 tv = ast_tv(60, 0);
10481 if (!i || ast_tvcmp(tv, lowest) < 0) {
10482 lowest = tv;
10485 ast_mutex_unlock(&pri->lock);
10487 e = NULL;
10488 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10490 ast_mutex_lock(&pri->lock);
10491 if (!res) {
10492 for (which = 0; which < NUM_DCHANS; which++) {
10493 if (!pri->dchans[which])
10494 break;
10495 /* Just a timeout, run the scheduler */
10496 e = pri_schedule_run(pri->dchans[which]);
10497 if (e)
10498 break;
10500 } else if (res > -1) {
10501 for (which = 0; which < NUM_DCHANS; which++) {
10502 if (!pri->dchans[which])
10503 break;
10504 if (fds[which].revents & POLLPRI) {
10505 /* Check for an event */
10506 x = 0;
10507 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10508 if (x) {
10509 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
10510 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
10511 "PRIEvent: %s\r\n"
10512 "PRIEventCode: %d\r\n"
10513 "D-channel: %s\r\n"
10514 "Span: %d\r\n",
10515 event2str(x),
10517 pri_order(which),
10518 pri->span
10521 /* Keep track of alarm state */
10522 if (x == DAHDI_EVENT_ALARM) {
10523 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10524 pri_find_dchan(pri);
10525 } else if (x == DAHDI_EVENT_NOALARM) {
10526 pri->dchanavail[which] |= DCHAN_NOTINALARM;
10527 pri_restart(pri->dchans[which]);
10530 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10531 } else if (fds[which].revents & POLLIN) {
10532 e = pri_check_event(pri->dchans[which]);
10534 if (e)
10535 break;
10537 } else if (errno != EINTR)
10538 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10540 if (e) {
10541 if (pri->debug)
10542 pri_dump_event(pri->dchans[which], e);
10544 if (e->e != PRI_EVENT_DCHAN_DOWN) {
10545 if (!(pri->dchanavail[which] & DCHAN_UP)) {
10546 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10548 pri->dchanavail[which] |= DCHAN_UP;
10549 } else {
10550 if (pri->dchanavail[which] & DCHAN_UP) {
10551 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10553 pri->dchanavail[which] &= ~DCHAN_UP;
10556 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10557 /* Must be an NFAS group that has the secondary dchan active */
10558 pri->pri = pri->dchans[which];
10560 switch (e->e) {
10561 case PRI_EVENT_DCHAN_UP:
10562 if (!pri->pri) pri_find_dchan(pri);
10564 /* Note presense of D-channel */
10565 time(&pri->lastreset);
10567 /* Restart in 5 seconds */
10568 if (pri->resetinterval > -1) {
10569 pri->lastreset -= pri->resetinterval;
10570 pri->lastreset += 5;
10572 pri->resetting = 0;
10573 /* Take the channels from inalarm condition */
10574 for (i = 0; i < pri->numchans; i++)
10575 if (pri->pvts[i]) {
10576 pri->pvts[i]->inalarm = 0;
10578 break;
10579 case PRI_EVENT_DCHAN_DOWN:
10580 pri_find_dchan(pri);
10581 if (!pri_is_up(pri)) {
10582 pri->resetting = 0;
10583 /* Hangup active channels and put them in alarm mode */
10584 for (i = 0; i < pri->numchans; i++) {
10585 struct dahdi_pvt *p = pri->pvts[i];
10586 if (p) {
10587 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10588 /* T309 is not enabled : hangup calls when alarm occurs */
10589 if (p->call) {
10590 if (p->pri && p->pri->pri) {
10591 pri_hangup(p->pri->pri, p->call, -1);
10592 pri_destroycall(p->pri->pri, p->call);
10593 p->call = NULL;
10594 } else
10595 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10597 if (p->realcall) {
10598 pri_hangup_all(p->realcall, pri);
10599 } else if (p->owner)
10600 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10602 p->inalarm = 1;
10606 break;
10607 case PRI_EVENT_RESTART:
10608 if (e->restart.channel > -1) {
10609 chanpos = pri_find_principle(pri, e->restart.channel);
10610 if (chanpos < 0)
10611 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10612 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10613 else {
10614 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
10615 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10616 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10617 if (pri->pvts[chanpos]->call) {
10618 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10619 pri->pvts[chanpos]->call = NULL;
10621 /* Force soft hangup if appropriate */
10622 if (pri->pvts[chanpos]->realcall)
10623 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10624 else if (pri->pvts[chanpos]->owner)
10625 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10626 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10628 } else {
10629 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
10630 for (x = 0; x < pri->numchans; x++)
10631 if (pri->pvts[x]) {
10632 ast_mutex_lock(&pri->pvts[x]->lock);
10633 if (pri->pvts[x]->call) {
10634 pri_destroycall(pri->pri, pri->pvts[x]->call);
10635 pri->pvts[x]->call = NULL;
10637 if (pri->pvts[chanpos]->realcall)
10638 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10639 else if (pri->pvts[x]->owner)
10640 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10641 ast_mutex_unlock(&pri->pvts[x]->lock);
10644 break;
10645 case PRI_EVENT_KEYPAD_DIGIT:
10646 chanpos = pri_find_principle(pri, e->digit.channel);
10647 if (chanpos < 0) {
10648 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10649 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10650 } else {
10651 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10652 if (chanpos > -1) {
10653 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10654 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10655 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10656 /* how to do that */
10657 int digitlen = strlen(e->digit.digits);
10658 char digit;
10659 int i;
10660 for (i = 0; i < digitlen; i++) {
10661 digit = e->digit.digits[i];
10663 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10664 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10668 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10671 break;
10673 case PRI_EVENT_INFO_RECEIVED:
10674 chanpos = pri_find_principle(pri, e->ring.channel);
10675 if (chanpos < 0) {
10676 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
10677 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10678 } else {
10679 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10680 if (chanpos > -1) {
10681 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10682 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10683 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10684 /* how to do that */
10685 int digitlen = strlen(e->ring.callednum);
10686 char digit;
10687 int i;
10688 for (i = 0; i < digitlen; i++) {
10689 digit = e->ring.callednum[i];
10691 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10692 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10696 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10699 break;
10700 case PRI_EVENT_RING:
10701 crv = NULL;
10702 if (e->ring.channel == -1)
10703 chanpos = pri_find_empty_chan(pri, 1);
10704 else
10705 chanpos = pri_find_principle(pri, e->ring.channel);
10706 /* if no channel specified find one empty */
10707 if (chanpos < 0) {
10708 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
10709 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10710 } else {
10711 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10712 if (pri->pvts[chanpos]->owner) {
10713 if (pri->pvts[chanpos]->call == e->ring.call) {
10714 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10715 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10716 break;
10717 } else {
10718 /* This is where we handle initial glare */
10719 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
10720 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10721 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10722 chanpos = -1;
10725 if (chanpos > -1)
10726 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10728 if ((chanpos < 0) && (e->ring.flexible))
10729 chanpos = pri_find_empty_chan(pri, 1);
10730 if (chanpos > -1) {
10731 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10732 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10733 /* Should be safe to lock CRV AFAIK while bearer is still locked */
10734 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10735 if (crv)
10736 ast_mutex_lock(&crv->lock);
10737 if (!crv || crv->owner) {
10738 pri->pvts[chanpos]->call = NULL;
10739 if (crv) {
10740 if (crv->owner)
10741 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10742 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10743 } else
10744 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10745 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10746 if (crv)
10747 ast_mutex_unlock(&crv->lock);
10748 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10749 break;
10752 pri->pvts[chanpos]->call = e->ring.call;
10753 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10754 if (pri->pvts[chanpos]->use_callerid) {
10755 ast_shrink_phone_number(plancallingnum);
10756 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10757 #ifdef PRI_ANI
10758 if (!ast_strlen_zero(e->ring.callingani)) {
10759 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10760 ast_shrink_phone_number(plancallingani);
10761 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10762 } else {
10763 pri->pvts[chanpos]->cid_ani[0] = '\0';
10765 #endif
10766 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10767 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10768 } else {
10769 pri->pvts[chanpos]->cid_num[0] = '\0';
10770 pri->pvts[chanpos]->cid_ani[0] = '\0';
10771 pri->pvts[chanpos]->cid_name[0] = '\0';
10772 pri->pvts[chanpos]->cid_ton = 0;
10774 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10775 e->ring.redirectingnum, e->ring.callingplanrdnis);
10776 /* If immediate=yes go to s|1 */
10777 if (pri->pvts[chanpos]->immediate) {
10778 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
10779 pri->pvts[chanpos]->exten[0] = 's';
10780 pri->pvts[chanpos]->exten[1] = '\0';
10782 /* Get called number */
10783 else if (!ast_strlen_zero(e->ring.callednum)) {
10784 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10785 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10786 } else if (pri->overlapdial)
10787 pri->pvts[chanpos]->exten[0] = '\0';
10788 else {
10789 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
10790 pri->pvts[chanpos]->exten[0] = 's';
10791 pri->pvts[chanpos]->exten[1] = '\0';
10793 /* Set DNID on all incoming calls -- even immediate */
10794 if (!ast_strlen_zero(e->ring.callednum))
10795 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10796 /* No number yet, but received "sending complete"? */
10797 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10798 ast_verb(3, "Going to extension s|1 because of Complete received\n");
10799 pri->pvts[chanpos]->exten[0] = 's';
10800 pri->pvts[chanpos]->exten[1] = '\0';
10802 /* Make sure extension exists (or in overlap dial mode, can exist) */
10803 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10804 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10805 /* Setup law */
10806 int law;
10807 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10808 /* Set to audio mode at this point */
10809 law = 1;
10810 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &law) == -1)
10811 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10813 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10814 law = DAHDI_LAW_ALAW;
10815 else
10816 law = DAHDI_LAW_MULAW;
10817 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
10818 if (res < 0)
10819 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10820 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10821 if (res < 0)
10822 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10823 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10824 /* Just announce proceeding */
10825 pri->pvts[chanpos]->proceeding = 1;
10826 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10827 } else {
10828 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
10829 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10830 else
10831 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10833 /* Get the use_callingpres state */
10834 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10836 /* Start PBX */
10837 if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10838 /* Release the PRI lock while we create the channel */
10839 ast_mutex_unlock(&pri->lock);
10840 if (crv) {
10841 /* Set bearer and such */
10842 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10843 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10844 pri->pvts[chanpos]->owner = &inuse;
10845 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10846 } else {
10847 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10850 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10852 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10853 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10855 if (e->ring.ani2 >= 0) {
10856 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
10857 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10858 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
10861 #ifdef SUPPORT_USERUSER
10862 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10863 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10865 #endif
10867 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10868 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10869 if (e->ring.redirectingreason >= 0)
10870 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10872 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10873 ast_mutex_lock(&pri->lock);
10874 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
10875 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10876 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10877 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10878 } else {
10879 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10880 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10881 if (c)
10882 ast_hangup(c);
10883 else {
10884 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10885 pri->pvts[chanpos]->call = NULL;
10888 } else {
10889 ast_mutex_unlock(&pri->lock);
10890 /* Release PRI lock while we create the channel */
10891 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
10892 if (c) {
10893 char calledtonstr[10];
10895 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10897 if (e->ring.ani2 >= 0) {
10898 snprintf(ani2str, 5, "%d", e->ring.ani2);
10899 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10900 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
10903 #ifdef SUPPORT_USERUSER
10904 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10905 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10907 #endif
10909 if (e->ring.redirectingreason >= 0)
10910 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10912 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10913 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10915 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10916 ast_mutex_lock(&pri->lock);
10918 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10919 plancallingnum, pri->pvts[chanpos]->exten,
10920 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10922 dahdi_enable_ec(pri->pvts[chanpos]);
10923 } else {
10925 ast_mutex_lock(&pri->lock);
10927 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10928 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10929 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10930 pri->pvts[chanpos]->call = NULL;
10933 } else {
10934 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10935 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
10936 pri->pvts[chanpos]->prioffset, pri->span);
10937 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10938 pri->pvts[chanpos]->call = NULL;
10939 pri->pvts[chanpos]->exten[0] = '\0';
10941 if (crv)
10942 ast_mutex_unlock(&crv->lock);
10943 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10944 } else {
10945 if (e->ring.flexible)
10946 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10947 else
10948 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10950 break;
10951 case PRI_EVENT_RINGING:
10952 chanpos = pri_find_principle(pri, e->ringing.channel);
10953 if (chanpos < 0) {
10954 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
10955 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10956 } else {
10957 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10958 if (chanpos < 0) {
10959 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
10960 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10961 } else {
10962 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10963 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10964 dahdi_enable_ec(pri->pvts[chanpos]);
10965 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10966 pri->pvts[chanpos]->alerting = 1;
10967 } else
10968 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
10970 #ifdef PRI_PROGRESS_MASK
10971 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10972 #else
10973 if (e->ringing.progress == 8) {
10974 #endif
10975 /* Now we can do call progress detection */
10976 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10977 /* RINGING detection isn't required because we got ALERTING signal */
10978 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10979 pri->pvts[chanpos]->dsp_features = 0;
10983 #ifdef SUPPORT_USERUSER
10984 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10985 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10986 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10987 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10988 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10990 #endif
10992 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10995 break;
10996 case PRI_EVENT_PROGRESS:
10997 /* Get chan value if e->e is not PRI_EVNT_RINGING */
10998 chanpos = pri_find_principle(pri, e->proceeding.channel);
10999 if (chanpos > -1) {
11000 #ifdef PRI_PROGRESS_MASK
11001 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11002 #else
11003 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11004 #endif
11005 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11007 if (e->proceeding.cause > -1) {
11008 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11010 /* Work around broken, out of spec USER_BUSY cause in a progress message */
11011 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11012 if (pri->pvts[chanpos]->owner) {
11013 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11015 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11016 f.subclass = AST_CONTROL_BUSY;
11021 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11022 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11023 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11024 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11025 #ifdef PRI_PROGRESS_MASK
11026 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11027 #else
11028 if (e->proceeding.progress == 8) {
11029 #endif
11030 /* Now we can do call progress detection */
11031 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11032 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11033 pri->pvts[chanpos]->dsp_features = 0;
11036 pri->pvts[chanpos]->progress = 1;
11037 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11040 break;
11041 case PRI_EVENT_PROCEEDING:
11042 chanpos = pri_find_principle(pri, e->proceeding.channel);
11043 if (chanpos > -1) {
11044 if (!pri->pvts[chanpos]->proceeding) {
11045 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11047 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11048 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11049 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11050 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11051 #ifdef PRI_PROGRESS_MASK
11052 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11053 #else
11054 if (e->proceeding.progress == 8) {
11055 #endif
11056 /* Now we can do call progress detection */
11057 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11058 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11059 pri->pvts[chanpos]->dsp_features = 0;
11061 /* Bring voice path up */
11062 f.subclass = AST_CONTROL_PROGRESS;
11063 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11065 pri->pvts[chanpos]->proceeding = 1;
11066 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11069 break;
11070 case PRI_EVENT_FACNAME:
11071 chanpos = pri_find_principle(pri, e->facname.channel);
11072 if (chanpos < 0) {
11073 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11074 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11075 } else {
11076 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11077 if (chanpos < 0) {
11078 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11079 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11080 } else {
11081 /* Re-use *69 field for PRI */
11082 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11083 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11084 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11085 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11086 dahdi_enable_ec(pri->pvts[chanpos]);
11087 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11090 break;
11091 case PRI_EVENT_ANSWER:
11092 chanpos = pri_find_principle(pri, e->answer.channel);
11093 if (chanpos < 0) {
11094 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11095 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11096 } else {
11097 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11098 if (chanpos < 0) {
11099 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11100 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11101 } else {
11102 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11103 /* Now we can do call progress detection */
11105 /* We changed this so it turns on the DSP no matter what... progress or no progress.
11106 * By this time, we need DTMF detection and other features that were previously disabled
11107 * -- Matt F */
11108 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11109 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11110 pri->pvts[chanpos]->dsp_features = 0;
11112 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11113 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11114 x = DAHDI_START;
11115 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
11116 if (res < 0) {
11117 if (errno != EINPROGRESS) {
11118 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11121 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11122 pri->pvts[chanpos]->dialing = 1;
11123 /* Send any "w" waited stuff */
11124 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11125 if (res < 0) {
11126 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11127 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11128 } else
11129 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11131 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11132 } else if (pri->pvts[chanpos]->confirmanswer) {
11133 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11134 } else {
11135 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11136 /* Enable echo cancellation if it's not on already */
11137 dahdi_enable_ec(pri->pvts[chanpos]);
11140 #ifdef SUPPORT_USERUSER
11141 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11142 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11143 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11144 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11145 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11147 #endif
11149 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11152 break;
11153 case PRI_EVENT_HANGUP:
11154 chanpos = pri_find_principle(pri, e->hangup.channel);
11155 if (chanpos < 0) {
11156 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11157 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11158 } else {
11159 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11160 if (chanpos > -1) {
11161 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11162 if (!pri->pvts[chanpos]->alreadyhungup) {
11163 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11164 pri->pvts[chanpos]->alreadyhungup = 1;
11165 if (pri->pvts[chanpos]->realcall)
11166 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11167 else if (pri->pvts[chanpos]->owner) {
11168 /* Queue a BUSY instead of a hangup if our cause is appropriate */
11169 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11170 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11171 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11172 else {
11173 switch (e->hangup.cause) {
11174 case PRI_CAUSE_USER_BUSY:
11175 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11176 break;
11177 case PRI_CAUSE_CALL_REJECTED:
11178 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11179 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11180 case PRI_CAUSE_SWITCH_CONGESTION:
11181 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11182 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11183 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11184 break;
11185 default:
11186 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11190 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11191 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11192 } else {
11193 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11194 pri->pvts[chanpos]->call = NULL;
11196 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11197 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11198 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11199 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11200 pri->pvts[chanpos]->resetting = 1;
11202 if (e->hangup.aoc_units > -1)
11203 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11204 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11206 #ifdef SUPPORT_USERUSER
11207 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11208 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11209 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11210 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11211 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11213 #endif
11215 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11216 } else {
11217 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11218 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11221 break;
11222 #ifndef PRI_EVENT_HANGUP_REQ
11223 #error please update libpri
11224 #endif
11225 case PRI_EVENT_HANGUP_REQ:
11226 chanpos = pri_find_principle(pri, e->hangup.channel);
11227 if (chanpos < 0) {
11228 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11229 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11230 } else {
11231 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11232 if (chanpos > -1) {
11233 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11234 if (pri->pvts[chanpos]->realcall)
11235 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11236 else if (pri->pvts[chanpos]->owner) {
11237 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11238 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11239 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11240 else {
11241 switch (e->hangup.cause) {
11242 case PRI_CAUSE_USER_BUSY:
11243 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11244 break;
11245 case PRI_CAUSE_CALL_REJECTED:
11246 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11247 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11248 case PRI_CAUSE_SWITCH_CONGESTION:
11249 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11250 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11251 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11252 break;
11253 default:
11254 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11257 ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
11258 if (e->hangup.aoc_units > -1)
11259 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11260 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11261 } else {
11262 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11263 pri->pvts[chanpos]->call = NULL;
11265 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11266 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11267 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11268 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11269 pri->pvts[chanpos]->resetting = 1;
11272 #ifdef SUPPORT_USERUSER
11273 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11274 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11275 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11276 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11277 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11279 #endif
11281 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11282 } else {
11283 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11286 break;
11287 case PRI_EVENT_HANGUP_ACK:
11288 chanpos = pri_find_principle(pri, e->hangup.channel);
11289 if (chanpos < 0) {
11290 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11291 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11292 } else {
11293 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11294 if (chanpos > -1) {
11295 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11296 pri->pvts[chanpos]->call = NULL;
11297 pri->pvts[chanpos]->resetting = 0;
11298 if (pri->pvts[chanpos]->owner) {
11299 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11302 #ifdef SUPPORT_USERUSER
11303 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11304 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11305 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11306 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11307 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11309 #endif
11311 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11314 break;
11315 case PRI_EVENT_CONFIG_ERR:
11316 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11317 break;
11318 case PRI_EVENT_RESTART_ACK:
11319 chanpos = pri_find_principle(pri, e->restartack.channel);
11320 if (chanpos < 0) {
11321 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11322 channel number, so we have to figure it out... This must be why
11323 everybody resets exactly a channel at a time. */
11324 for (x = 0; x < pri->numchans; x++) {
11325 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11326 chanpos = x;
11327 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11328 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11329 pri->pvts[chanpos]->prioffset, pri->span);
11330 if (pri->pvts[chanpos]->realcall)
11331 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11332 else if (pri->pvts[chanpos]->owner) {
11333 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11334 pri->pvts[chanpos]->prioffset, pri->span);
11335 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11337 pri->pvts[chanpos]->resetting = 0;
11338 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11339 pri->pvts[chanpos]->prioffset, pri->span);
11340 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11341 if (pri->resetting)
11342 pri_check_restart(pri);
11343 break;
11346 if (chanpos < 0) {
11347 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11348 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11350 } else {
11351 if (pri->pvts[chanpos]) {
11352 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11353 if (pri->pvts[chanpos]->realcall)
11354 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11355 else if (pri->pvts[chanpos]->owner) {
11356 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11357 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11358 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11360 pri->pvts[chanpos]->resetting = 0;
11361 pri->pvts[chanpos]->inservice = 1;
11362 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11363 pri->pvts[chanpos]->prioffset, pri->span);
11364 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11365 if (pri->resetting)
11366 pri_check_restart(pri);
11369 break;
11370 case PRI_EVENT_SETUP_ACK:
11371 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11372 if (chanpos < 0) {
11373 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11374 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11375 } else {
11376 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11377 if (chanpos > -1) {
11378 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11379 pri->pvts[chanpos]->setup_ack = 1;
11380 /* Send any queued digits */
11381 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11382 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11383 pri_information(pri->pri, pri->pvts[chanpos]->call,
11384 pri->pvts[chanpos]->dialdest[x]);
11386 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11387 } else
11388 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11390 break;
11391 case PRI_EVENT_NOTIFY:
11392 chanpos = pri_find_principle(pri, e->notify.channel);
11393 if (chanpos < 0) {
11394 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11395 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11396 } else {
11397 struct ast_frame f = { AST_FRAME_CONTROL, };
11398 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11399 switch (e->notify.info) {
11400 case PRI_NOTIFY_REMOTE_HOLD:
11401 f.subclass = AST_CONTROL_HOLD;
11402 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11403 break;
11404 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11405 f.subclass = AST_CONTROL_UNHOLD;
11406 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11407 break;
11409 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11411 break;
11412 default:
11413 ast_debug(1, "Event: %d\n", e->e);
11416 ast_mutex_unlock(&pri->lock);
11418 /* Never reached */
11419 return NULL;
11422 static int start_pri(struct dahdi_pri *pri)
11424 int res, x;
11425 DAHDI_PARAMS p;
11426 DAHDI_BUFFERINFO bi;
11427 struct dahdi_spaninfo si;
11428 int i;
11430 for (i = 0; i < NUM_DCHANS; i++) {
11431 if (!pri->dchannels[i])
11432 break;
11433 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11434 x = pri->dchannels[i];
11435 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11436 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11437 return -1;
11439 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11440 if (res) {
11441 dahdi_close(pri->fds[i]);
11442 pri->fds[i] = -1;
11443 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11444 return -1;
11446 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11447 dahdi_close(pri->fds[i]);
11448 pri->fds[i] = -1;
11449 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
11450 return -1;
11452 memset(&si, 0, sizeof(si));
11453 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11454 if (res) {
11455 dahdi_close(pri->fds[i]);
11456 pri->fds[i] = -1;
11457 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11459 if (!si.alarms)
11460 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11461 else
11462 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11463 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11464 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11465 bi.numbufs = 32;
11466 bi.bufsize = 1024;
11467 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11468 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11469 dahdi_close(pri->fds[i]);
11470 pri->fds[i] = -1;
11471 return -1;
11473 switch (pri->sig) {
11474 case SIG_BRI:
11475 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
11476 break;
11477 case SIG_BRI_PTMP:
11478 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
11479 break;
11480 default:
11481 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11483 /* Force overlap dial if we're doing GR-303! */
11484 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11485 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11486 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11487 #ifdef HAVE_PRI_INBANDRELEASE
11488 pri_set_inbandrelease(pri->dchans[i], pri->inbandrelease);
11489 #endif
11490 /* Enslave to master if appropriate */
11491 if (i)
11492 pri_enslave(pri->dchans[0], pri->dchans[i]);
11493 if (!pri->dchans[i]) {
11494 dahdi_close(pri->fds[i]);
11495 pri->fds[i] = -1;
11496 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11497 return -1;
11499 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11500 pri_set_nsf(pri->dchans[i], pri->nsf);
11501 #ifdef PRI_GETSET_TIMERS
11502 for (x = 0; x < PRI_MAX_TIMERS; x++) {
11503 if (pritimers[x] != 0)
11504 pri_set_timer(pri->dchans[i], x, pritimers[x]);
11506 #endif
11508 /* Assume primary is the one we use */
11509 pri->pri = pri->dchans[0];
11510 pri->resetpos = -1;
11511 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11512 for (i = 0; i < NUM_DCHANS; i++) {
11513 if (!pri->dchannels[i])
11514 break;
11515 dahdi_close(pri->fds[i]);
11516 pri->fds[i] = -1;
11518 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11519 return -1;
11521 return 0;
11524 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11526 int which, span;
11527 char *ret = NULL;
11529 if (pos != rpos)
11530 return ret;
11532 for (which = span = 0; span < NUM_SPANS; span++) {
11533 if (pris[span].pri && ++which > state) {
11534 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
11535 break;
11538 return ret;
11541 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11543 return complete_span_helper(line,word,pos,state,3);
11546 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11548 return complete_span_helper(line,word,pos,state,4);
11551 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11553 switch (cmd) {
11554 case CLI_INIT:
11555 e->command = "pri unset debug file";
11556 e->usage = "Usage: pri unset debug file\n"
11557 " Stop sending debug output to the previously \n"
11558 " specified file\n";
11559 return NULL;
11560 case CLI_GENERATE:
11561 return NULL;
11563 /* Assume it is unset */
11564 ast_mutex_lock(&pridebugfdlock);
11565 close(pridebugfd);
11566 pridebugfd = -1;
11567 ast_cli(a->fd, "PRI debug output to file disabled\n");
11568 ast_mutex_unlock(&pridebugfdlock);
11569 return CLI_SUCCESS;
11572 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11574 int myfd;
11575 switch (cmd) {
11576 case CLI_INIT:
11577 e->command = "pri set debug file";
11578 e->usage = "Usage: pri set debug file [output-file]\n"
11579 " Sends PRI debug output to the specified output file\n";
11580 return NULL;
11581 case CLI_GENERATE:
11582 return NULL;
11584 if (a->argc < 5)
11585 return CLI_SHOWUSAGE;
11587 if (ast_strlen_zero(a->argv[4]))
11588 return CLI_SHOWUSAGE;
11590 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
11591 if (myfd < 0) {
11592 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
11593 return CLI_SUCCESS;
11596 ast_mutex_lock(&pridebugfdlock);
11598 if (pridebugfd >= 0)
11599 close(pridebugfd);
11601 pridebugfd = myfd;
11602 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
11603 ast_mutex_unlock(&pridebugfdlock);
11604 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
11605 return CLI_SUCCESS;
11608 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11610 int span;
11611 int x;
11612 switch (cmd) {
11613 case CLI_INIT:
11614 e->command = "pri debug span";
11615 e->usage =
11616 "Usage: pri debug span <span>\n"
11617 " Enables debugging on a given PRI span\n";
11618 return NULL;
11619 case CLI_GENERATE:
11620 return complete_span_4(a->line, a->word, a->pos, a->n);
11622 if (a->argc < 4) {
11623 return CLI_SHOWUSAGE;
11625 span = atoi(a->argv[3]);
11626 if ((span < 1) || (span > NUM_SPANS)) {
11627 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
11628 return CLI_SUCCESS;
11630 if (!pris[span-1].pri) {
11631 ast_cli(a->fd, "No PRI running on span %d\n", span);
11632 return CLI_SUCCESS;
11634 for (x = 0; x < NUM_DCHANS; x++) {
11635 if (pris[span-1].dchans[x])
11636 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11637 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11638 PRI_DEBUG_Q921_STATE);
11640 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
11641 return CLI_SUCCESS;
11646 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11648 int span;
11649 int x;
11650 switch (cmd) {
11651 case CLI_INIT:
11652 e->command = "pri no debug span";
11653 e->usage =
11654 "Usage: pri no debug span <span>\n"
11655 " Disables debugging on a given PRI span\n";
11656 return NULL;
11657 case CLI_GENERATE:
11658 return complete_span_5(a->line, a->word, a->pos, a->n);
11660 if (a->argc < 5)
11661 return CLI_SHOWUSAGE;
11663 span = atoi(a->argv[4]);
11664 if ((span < 1) || (span > NUM_SPANS)) {
11665 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
11666 return CLI_SUCCESS;
11668 if (!pris[span-1].pri) {
11669 ast_cli(a->fd, "No PRI running on span %d\n", span);
11670 return CLI_SUCCESS;
11672 for (x = 0; x < NUM_DCHANS; x++) {
11673 if (pris[span-1].dchans[x])
11674 pri_set_debug(pris[span-1].dchans[x], 0);
11676 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
11677 return CLI_SUCCESS;
11680 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11682 int span;
11683 int x;
11684 switch (cmd) {
11685 case CLI_INIT:
11686 e->command = "pri intensive debug span";
11687 e->usage =
11688 "Usage: pri intensive debug span <span>\n"
11689 " Enables debugging down to the Q.921 level\n";
11690 return NULL;
11691 case CLI_GENERATE:
11692 return complete_span_5(a->line, a->word, a->pos, a->n);
11695 if (a->argc < 5)
11696 return CLI_SHOWUSAGE;
11697 span = atoi(a->argv[4]);
11698 if ((span < 1) || (span > NUM_SPANS)) {
11699 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
11700 return CLI_SUCCESS;
11702 if (!pris[span-1].pri) {
11703 ast_cli(a->fd, "No PRI running on span %d\n", span);
11704 return CLI_SUCCESS;
11706 for (x = 0; x < NUM_DCHANS; x++) {
11707 if (pris[span-1].dchans[x])
11708 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11709 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11710 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11712 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11713 return CLI_SUCCESS;
11716 static void build_status(char *s, size_t len, int status, int active)
11718 if (!s || len < 1) {
11719 return;
11721 s[0] = '\0';
11722 if (status & DCHAN_PROVISIONED)
11723 strncat(s, "Provisioned, ", len - strlen(s) - 1);
11724 if (!(status & DCHAN_NOTINALARM))
11725 strncat(s, "In Alarm, ", len - strlen(s) - 1);
11726 if (status & DCHAN_UP)
11727 strncat(s, "Up", len - strlen(s) - 1);
11728 else
11729 strncat(s, "Down", len - strlen(s) - 1);
11730 if (active)
11731 strncat(s, ", Active", len - strlen(s) - 1);
11732 else
11733 strncat(s, ", Standby", len - strlen(s) - 1);
11734 s[len - 1] = '\0';
11737 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11739 int span;
11740 int x;
11741 char status[256];
11743 switch (cmd) {
11744 case CLI_INIT:
11745 e->command = "pri show spans";
11746 e->usage =
11747 "Usage: pri show spans\n"
11748 " Displays PRI Information\n";
11749 return NULL;
11750 case CLI_GENERATE:
11751 return NULL;
11754 if (a->argc != 3)
11755 return CLI_SHOWUSAGE;
11757 for (span = 0; span < NUM_SPANS; span++) {
11758 if (pris[span].pri) {
11759 for (x = 0; x < NUM_DCHANS; x++) {
11760 if (pris[span].dchannels[x]) {
11761 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11762 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11767 return CLI_SUCCESS;
11770 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11772 int span;
11773 int x;
11774 char status[256];
11775 switch (cmd) {
11776 case CLI_INIT:
11777 e->command = "pri show span";
11778 e->usage =
11779 "Usage: pri show span <span>\n"
11780 " Displays PRI Information on a given PRI span\n";
11781 return NULL;
11782 case CLI_GENERATE:
11783 return complete_span_4(a->line, a->word, a->pos, a->n);
11786 if (a->argc < 4)
11787 return CLI_SHOWUSAGE;
11788 span = atoi(a->argv[3]);
11789 if ((span < 1) || (span > NUM_SPANS)) {
11790 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
11791 return CLI_SUCCESS;
11793 if (!pris[span-1].pri) {
11794 ast_cli(a->fd, "No PRI running on span %d\n", span);
11795 return CLI_SUCCESS;
11797 for (x = 0; x < NUM_DCHANS; x++) {
11798 if (pris[span-1].dchannels[x]) {
11799 #ifdef PRI_DUMP_INFO_STR
11800 char *info_str = NULL;
11801 #endif
11802 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11803 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11804 ast_cli(a->fd, "Status: %s\n", status);
11805 #ifdef PRI_DUMP_INFO_STR
11806 info_str = pri_dump_info_str(pris[span-1].pri);
11807 if (info_str) {
11808 ast_cli(a->fd, "%s", info_str);
11809 ast_free(info_str);
11811 #else
11812 pri_dump_info(pris[span-1].pri);
11813 #endif
11814 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11817 return CLI_SUCCESS;
11820 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11822 int x;
11823 int span;
11824 int count=0;
11825 int debug=0;
11827 switch (cmd) {
11828 case CLI_INIT:
11829 e->command = "pri show debug";
11830 return NULL;
11831 case CLI_GENERATE:
11832 return NULL;
11835 for (span = 0; span < NUM_SPANS; span++) {
11836 if (pris[span].pri) {
11837 for (x = 0; x < NUM_DCHANS; x++) {
11838 debug = 0;
11839 if (pris[span].dchans[x]) {
11840 debug = pri_get_debug(pris[span].dchans[x]);
11841 ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
11842 count++;
11848 ast_mutex_lock(&pridebugfdlock);
11849 if (pridebugfd >= 0)
11850 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
11851 ast_mutex_unlock(&pridebugfdlock);
11853 if (!count)
11854 ast_cli(a->fd, "No debug set or no PRI running\n");
11855 return CLI_SUCCESS;
11858 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11860 switch (cmd) {
11861 case CLI_INIT:
11862 e->command = "pri show version";
11863 return NULL;
11864 case CLI_GENERATE:
11865 return NULL;
11868 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
11870 return CLI_SUCCESS;
11873 static struct ast_cli_entry dahdi_pri_cli[] = {
11874 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
11875 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
11876 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
11877 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
11878 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
11879 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
11880 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
11881 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
11882 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
11885 #endif /* HAVE_PRI */
11887 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11889 int channel;
11890 int ret;
11891 switch (cmd) {
11892 case CLI_INIT:
11893 e->command = "dahdi destroy channel";
11894 e->usage =
11895 "Usage: dahdi destroy channel <chan num>\n"
11896 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
11897 return NULL;
11898 case CLI_GENERATE:
11899 return NULL;
11901 if (a->argc != 4)
11902 return CLI_SHOWUSAGE;
11904 channel = atoi(a->argv[3]);
11905 ret = dahdi_destroy_channel_bynum(channel);
11906 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
11909 static char *handle_cli_zap_destroy_channel_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11911 switch (cmd) {
11912 case CLI_INIT:
11913 e->command = "zap destroy channel";
11914 e->usage =
11915 "Usage: zap destroy channel <chan num>\n"
11916 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
11917 return NULL;
11918 case CLI_GENERATE:
11919 return NULL;
11920 case CLI_HANDLER:
11921 return dahdi_destroy_channel(e, cmd, a);
11924 return CLI_FAILURE;
11927 static int setup_dahdi(int reload);
11928 static int dahdi_restart(void)
11930 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
11931 while (iflist) {
11932 ast_debug(1, "Destroying DAHDI channel no. %d\n", iflist->channel);
11933 /* Also updates iflist: */
11934 destroy_channel(NULL, iflist, 1);
11936 ast_debug(1, "Channels destroyed. Now re-reading config.\n");
11937 if (setup_dahdi(2) != 0) {
11938 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
11939 return 1;
11941 return 0;
11944 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11946 switch (cmd) {
11947 case CLI_INIT:
11948 e->command = "dahdi restart";
11949 e->usage =
11950 "Usage: dahdi restart\n"
11951 " Restarts the DAHDI channels: destroys them all and then\n"
11952 " re-reads them from chan_dahdi.conf.\n"
11953 " Note that this will STOP any running CALL on DAHDI channels.\n"
11955 return NULL;
11956 case CLI_GENERATE:
11957 return NULL;
11959 if (a->argc != 2)
11960 return CLI_SHOWUSAGE;
11962 if (dahdi_restart() != 0)
11963 return CLI_FAILURE;
11964 return CLI_SUCCESS;
11967 static char *handle_cli_zap_restart_cmd_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11969 switch (cmd) {
11970 case CLI_INIT:
11971 e->command = "zap restart";
11972 e->usage =
11973 "Usage: zap restart\n"
11974 " Restarts the zap channels: destroys them all and then\n"
11975 " re-reads them from chan_dahdi.conf.\n"
11976 " Note that this will STOP any running CALL on zap channels.\n"
11978 return NULL;
11979 case CLI_GENERATE:
11980 return NULL;
11981 case CLI_HANDLER:
11982 return dahdi_restart_cmd(e, cmd, a);
11985 return CLI_FAILURE;
11988 static int action_dahdirestart(struct mansession *s, const struct message *m)
11990 if (dahdi_restart() != 0) {
11991 astman_send_error(s, m, "Failed rereading DAHDI configuration");
11992 return 1;
11994 astman_send_ack(s, m, "DAHDIRestart: Success");
11995 return 0;
11998 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12000 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12001 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12002 unsigned int targetnum = 0;
12003 int filtertype = 0;
12004 struct dahdi_pvt *tmp = NULL;
12005 char tmps[20] = "";
12006 char statestr[20] = "";
12007 char blockstr[20] = "";
12008 ast_mutex_t *lock;
12009 struct dahdi_pvt *start;
12010 #ifdef HAVE_PRI
12011 int trunkgroup;
12012 struct dahdi_pri *pri = NULL;
12013 int x;
12014 #endif
12015 switch (cmd) {
12016 case CLI_INIT:
12017 e->command = "dahdi show channels [trunkgroup|group|context]";
12018 e->usage =
12019 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12020 " Shows a list of available channels with optional filtering\n"
12021 " <group> must be a number between 0 and 63\n";
12022 return NULL;
12023 case CLI_GENERATE:
12024 return NULL;
12027 lock = &iflock;
12028 start = iflist;
12030 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12032 if (!((a->argc == 3) || (a->argc == 5)))
12033 return CLI_SHOWUSAGE;
12035 if (a->argc == 5) {
12036 #ifdef HAVE_PRI
12037 if (!strcasecmp(a->argv[3], "trunkgroup")) {
12038 /* this option requires no special handling, so leave filtertype to zero */
12039 if ((trunkgroup = atoi(a->argv[4])) < 1)
12040 return CLI_SHOWUSAGE;
12041 for (x = 0; x < NUM_SPANS; x++) {
12042 if (pris[x].trunkgroup == trunkgroup) {
12043 pri = pris + x;
12044 break;
12047 if (pri) {
12048 start = pri->crvs;
12049 lock = &pri->lock;
12050 } else {
12051 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12052 return CLI_FAILURE;
12054 } else
12055 #endif
12056 if (!strcasecmp(a->argv[3], "group")) {
12057 targetnum = atoi(a->argv[4]);
12058 if ((targetnum < 0) || (targetnum > 63))
12059 return CLI_SHOWUSAGE;
12060 targetnum = 1 << targetnum;
12061 filtertype = 1;
12062 } else if (!strcasecmp(a->argv[3], "context")) {
12063 filtertype = 2;
12067 ast_mutex_lock(lock);
12068 #ifdef HAVE_PRI
12069 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12070 #else
12071 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12072 #endif
12074 tmp = start;
12075 while (tmp) {
12076 if (filtertype) {
12077 switch(filtertype) {
12078 case 1: /* dahdi show channels group <group> */
12079 if (tmp->group != targetnum) {
12080 tmp = tmp->next;
12081 continue;
12083 break;
12084 case 2: /* dahdi show channels context <context> */
12085 if (strcasecmp(tmp->context, a->argv[4])) {
12086 tmp = tmp->next;
12087 continue;
12089 break;
12090 default:
12094 if (tmp->channel > 0) {
12095 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12096 } else
12097 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12099 if (tmp->locallyblocked)
12100 blockstr[0] = 'L';
12101 else
12102 blockstr[0] = ' ';
12104 if (tmp->remotelyblocked)
12105 blockstr[1] = 'R';
12106 else
12107 blockstr[1] = ' ';
12109 blockstr[2] = '\0';
12111 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12113 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12114 tmp = tmp->next;
12116 ast_mutex_unlock(lock);
12117 return CLI_SUCCESS;
12118 #undef FORMAT
12119 #undef FORMAT2
12122 static char *handle_cli_zap_show_channels_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12124 switch (cmd) {
12125 case CLI_INIT:
12126 e->command = "zap show channels [trunkgroup|group|context]";
12127 e->usage =
12128 "Usage: zap show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12129 " Shows a list of available channels with optional filtering\n"
12130 " <group> must be a number between 0 and 63\n";
12131 return NULL;
12132 case CLI_GENERATE:
12133 return NULL;
12134 case CLI_HANDLER:
12135 return dahdi_show_channels(e, cmd, a);
12138 return CLI_FAILURE;
12141 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12143 int channel;
12144 struct dahdi_pvt *tmp = NULL;
12145 DAHDI_CONFINFO ci;
12146 DAHDI_PARAMS ps;
12147 int x;
12148 ast_mutex_t *lock;
12149 struct dahdi_pvt *start;
12150 #ifdef HAVE_PRI
12151 char *c;
12152 int trunkgroup;
12153 struct dahdi_pri *pri=NULL;
12154 #endif
12155 switch (cmd) {
12156 case CLI_INIT:
12157 e->command = "dahdi show channel";
12158 e->usage =
12159 "Usage: dahdi show channel <chan num>\n"
12160 " Detailed information about a given channel\n";
12161 return NULL;
12162 case CLI_GENERATE:
12163 return NULL;
12166 lock = &iflock;
12167 start = iflist;
12169 if (a->argc != 4)
12170 return CLI_SHOWUSAGE;
12171 #ifdef HAVE_PRI
12172 if ((c = strchr(a->argv[3], ':'))) {
12173 if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2)
12174 return CLI_SHOWUSAGE;
12175 if ((trunkgroup < 1) || (channel < 1))
12176 return CLI_SHOWUSAGE;
12177 for (x = 0; x < NUM_SPANS; x++) {
12178 if (pris[x].trunkgroup == trunkgroup) {
12179 pri = pris + x;
12180 break;
12183 if (pri) {
12184 start = pri->crvs;
12185 lock = &pri->lock;
12186 } else {
12187 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12188 return CLI_FAILURE;
12190 } else
12191 #endif
12192 channel = atoi(a->argv[3]);
12194 ast_mutex_lock(lock);
12195 tmp = start;
12196 while (tmp) {
12197 if (tmp->channel == channel) {
12198 #ifdef HAVE_PRI
12199 if (pri)
12200 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12201 else
12202 #endif
12203 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12204 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
12205 ast_cli(a->fd, "Span: %d\n", tmp->span);
12206 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12207 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12208 ast_cli(a->fd, "Context: %s\n", tmp->context);
12209 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12210 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12211 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12212 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12213 if (tmp->vars) {
12214 struct ast_variable *v;
12215 ast_cli(a->fd, "Variables:\n");
12216 for (v = tmp->vars ; v ; v = v->next)
12217 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12219 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12220 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12221 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12222 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12223 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12224 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
12225 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
12226 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
12227 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12228 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12229 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12230 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12231 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12232 if (tmp->busydetect) {
12233 #if defined(BUSYDETECT_TONEONLY)
12234 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12235 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12236 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12237 #endif
12238 #ifdef BUSYDETECT_DEBUG
12239 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12240 #endif
12241 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12242 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
12244 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12245 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12246 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12247 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12248 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12249 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12250 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12251 ast_cli(a->fd, "Echo Cancellation:\n");
12253 if (tmp->echocancel.head.tap_length) {
12254 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12255 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12256 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12258 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12259 } else {
12260 ast_cli(a->fd, "\tnone\n");
12262 if (tmp->master)
12263 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12264 for (x = 0; x < MAX_SLAVES; x++) {
12265 if (tmp->slaves[x])
12266 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12268 #ifdef HAVE_SS7
12269 if (tmp->ss7) {
12270 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12272 #endif
12273 #ifdef HAVE_PRI
12274 if (tmp->pri) {
12275 ast_cli(a->fd, "PRI Flags: ");
12276 if (tmp->resetting)
12277 ast_cli(a->fd, "Resetting ");
12278 if (tmp->call)
12279 ast_cli(a->fd, "Call ");
12280 if (tmp->bearer)
12281 ast_cli(a->fd, "Bearer ");
12282 ast_cli(a->fd, "\n");
12283 if (tmp->logicalspan)
12284 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12285 else
12286 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12289 #endif
12290 memset(&ci, 0, sizeof(ci));
12291 ps.channo = tmp->channel;
12292 if (tmp->subs[SUB_REAL].zfd > -1) {
12293 if (!ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GETCONF, &ci)) {
12294 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12296 #ifdef DAHDI_GETCONFMUTE
12297 if (!ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GETCONFMUTE, &x)) {
12298 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12300 #endif
12301 if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps) < 0) {
12302 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12303 } else {
12304 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12307 ast_mutex_unlock(lock);
12308 return CLI_SUCCESS;
12310 tmp = tmp->next;
12313 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12314 ast_mutex_unlock(lock);
12315 return CLI_FAILURE;
12318 static char *handle_cli_zap_show_channel_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12320 switch (cmd) {
12321 case CLI_INIT:
12322 e->command = "zap show channel";
12323 e->usage =
12324 "Usage: zap show channel <chan num>\n"
12325 " Detailed information about a given channel\n";
12326 return NULL;
12327 case CLI_GENERATE:
12328 return NULL;
12329 case CLI_HANDLER:
12330 return dahdi_show_channel(e, cmd, a);
12333 return CLI_FAILURE;
12336 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12338 int i, j;
12339 switch (cmd) {
12340 case CLI_INIT:
12341 e->command = "dahdi show cadences";
12342 e->usage =
12343 "Usage: dahdi show cadences\n"
12344 " Shows all cadences currently defined\n";
12345 return NULL;
12346 case CLI_GENERATE:
12347 return NULL;
12349 for (i = 0; i < num_cadence; i++) {
12350 char output[1024];
12351 char tmp[16], tmp2[64];
12352 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12353 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12355 for (j = 0; j < 16; j++) {
12356 if (cadences[i].ringcadence[j] == 0)
12357 break;
12358 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12359 if (cidrings[i] * 2 - 1 == j)
12360 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12361 else
12362 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12363 if (j != 0)
12364 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12365 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12367 ast_cli(a->fd,"%s\n",output);
12369 return CLI_SUCCESS;
12372 static char *handle_cli_zap_show_cadences_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12374 switch(cmd) {
12375 case CLI_INIT:
12376 e->command = "zap show cadences";
12377 e->usage =
12378 "Usage: zap show cadences\n"
12379 " Shows all cadences currently defined\n";
12380 return NULL;
12381 case CLI_GENERATE:
12382 return NULL;
12383 case CLI_HANDLER:
12384 return handle_dahdi_show_cadences(e, cmd, a);
12387 return CLI_FAILURE;
12390 /* Based on irqmiss.c */
12391 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12393 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
12394 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12395 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12396 #else
12397 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
12398 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
12399 #endif
12400 int span;
12401 int res;
12402 char alarms[50];
12404 int ctl;
12405 DAHDI_SPANINFO s;
12407 switch (cmd) {
12408 case CLI_INIT:
12409 e->command = "dahdi show status";
12410 e->usage =
12411 "Usage: dahdi show status\n"
12412 " Shows a list of DAHDI cards with status\n";
12413 return NULL;
12414 case CLI_GENERATE:
12415 return NULL;
12417 ctl = open("/dev/dahdi/ctl", O_RDWR);
12418 if (ctl < 0) {
12419 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
12420 return CLI_FAILURE;
12422 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"
12423 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
12424 , "Framing", "Coding", "Options", "LBO"
12425 #endif
12428 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12429 s.spanno = span;
12430 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12431 if (res) {
12432 continue;
12434 alarms[0] = '\0';
12435 if (s.alarms > 0) {
12436 if (s.alarms & DAHDI_ALARM_BLUE)
12437 strcat(alarms, "BLU/");
12438 if (s.alarms & DAHDI_ALARM_YELLOW)
12439 strcat(alarms, "YEL/");
12440 if (s.alarms & DAHDI_ALARM_RED)
12441 strcat(alarms, "RED/");
12442 if (s.alarms & DAHDI_ALARM_LOOPBACK)
12443 strcat(alarms, "LB/");
12444 if (s.alarms & DAHDI_ALARM_RECOVER)
12445 strcat(alarms, "REC/");
12446 if (s.alarms & DAHDI_ALARM_NOTOPEN)
12447 strcat(alarms, "NOP/");
12448 if (!strlen(alarms))
12449 strcat(alarms, "UUU/");
12450 if (strlen(alarms)) {
12451 /* Strip trailing / */
12452 alarms[strlen(alarms) - 1] = '\0';
12454 } else {
12455 if (s.numchans)
12456 strcpy(alarms, "OK");
12457 else
12458 strcpy(alarms, "UNCONFIGURED");
12461 ast_cli(a->fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count
12462 #ifdef DAHDI_SPANINFO_HAS_LINECONFIG
12463 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
12464 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
12465 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
12466 "CAS"
12467 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
12468 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
12469 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
12470 "Unk"
12471 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
12472 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
12473 , lbostr[s.lbo]
12474 #endif
12477 close(ctl);
12479 return CLI_SUCCESS;
12480 #undef FORMAT
12481 #undef FORMAT2
12484 static char *handle_cli_zap_show_status_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12486 switch (cmd) {
12487 case CLI_INIT:
12488 e->command = "zap show status";
12489 e->usage =
12490 "Usage: zap show status\n"
12491 " Shows a list of zap cards with status\n";
12492 return NULL;
12493 case CLI_GENERATE:
12494 return NULL;
12495 case CLI_HANDLER:
12496 return dahdi_show_status(e, cmd, a);
12499 return CLI_FAILURE;
12502 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12504 int pseudo_fd = -1;
12505 struct dahdi_versioninfo vi;
12507 switch (cmd) {
12508 case CLI_INIT:
12509 e->command = "dahdi show version";
12510 e->usage =
12511 "Usage: dahdi show version\n"
12512 " Shows the DAHDI version in use\n";
12513 return NULL;
12514 case CLI_GENERATE:
12515 return NULL;
12517 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
12518 ast_cli(a->fd, "Failed to open control file to get version.\n");
12519 return CLI_SUCCESS;
12522 strcpy(vi.version, "Unknown");
12523 strcpy(vi.echo_canceller, "Unknown");
12525 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
12526 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
12527 else
12528 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
12530 close(pseudo_fd);
12532 return CLI_SUCCESS;
12535 static char *handle_cli_zap_show_version_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12537 switch (cmd) {
12538 case CLI_INIT:
12539 e->command = "zap show version";
12540 e->usage =
12541 "Usage: zap show version\n"
12542 " Shows the zap version in use\n";
12543 return NULL;
12544 case CLI_GENERATE:
12545 return NULL;
12546 case CLI_HANDLER:
12547 return dahdi_show_version(e, cmd, a);
12550 return CLI_FAILURE;
12553 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12555 int channel;
12556 int gain;
12557 int tx;
12558 struct dahdi_hwgain hwgain;
12559 struct dahdi_pvt *tmp = NULL;
12561 switch (cmd) {
12562 case CLI_INIT:
12563 e->command = "dahdi set hwgain";
12564 e->usage =
12565 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
12566 " Sets the hardware gain on a a given channel, overriding the\n"
12567 " value provided at module loadtime, whether the channel is in\n"
12568 " use or not. Changes take effect immediately.\n"
12569 " <rx|tx> which direction do you want to change (relative to our module)\n"
12570 " <chan num> is the channel number relative to the device\n"
12571 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12572 return NULL;
12573 case CLI_GENERATE:
12574 return NULL;
12577 if (a->argc != 6)
12578 return CLI_SHOWUSAGE;
12580 if (!strcasecmp("rx", a->argv[3]))
12581 tx = 0; /* rx */
12582 else if (!strcasecmp("tx", a->argv[3]))
12583 tx = 1; /* tx */
12584 else
12585 return CLI_SHOWUSAGE;
12587 channel = atoi(a->argv[4]);
12588 gain = atof(a->argv[5])*10.0;
12590 ast_mutex_lock(&iflock);
12592 for (tmp = iflist; tmp; tmp = tmp->next) {
12594 if (tmp->channel != channel)
12595 continue;
12597 if (tmp->subs[SUB_REAL].zfd == -1)
12598 break;
12600 hwgain.newgain = gain;
12601 hwgain.tx = tx;
12602 if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
12603 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
12604 ast_mutex_unlock(&iflock);
12605 return CLI_FAILURE;
12607 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
12608 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
12609 break;
12612 ast_mutex_unlock(&iflock);
12614 if (tmp)
12615 return CLI_SUCCESS;
12617 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12618 return CLI_FAILURE;
12622 static char *handle_cli_zap_set_hwgain_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12624 switch (cmd) {
12625 case CLI_INIT:
12626 e->command = "zap set hwgain";
12627 e->usage =
12628 "Usage: zap set hwgain <rx|tx> <chan#> <gain>\n"
12629 " Sets the hardware gain on a a given channel, overriding the\n"
12630 " value provided at module loadtime, whether the channel is in\n"
12631 " use or not. Changes take effect immediately.\n"
12632 " <rx|tx> which direction do you want to change (relative to our module)\n"
12633 " <chan num> is the channel number relative to the device\n"
12634 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12635 return NULL;
12636 case CLI_GENERATE:
12637 return NULL;
12638 case CLI_HANDLER:
12639 return dahdi_set_hwgain(e, cmd, a);
12642 return CLI_FAILURE;
12645 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12647 int channel;
12648 float gain;
12649 int tx;
12650 int res;
12651 ast_mutex_t *lock;
12652 struct dahdi_pvt *tmp = NULL;
12654 switch (cmd) {
12655 case CLI_INIT:
12656 e->command = "dahdi set swgain";
12657 e->usage =
12658 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
12659 " Sets the software gain on a a given channel, overriding the\n"
12660 " value provided at module loadtime, whether the channel is in\n"
12661 " use or not. Changes take effect immediately.\n"
12662 " <rx|tx> which direction do you want to change (relative to our module)\n"
12663 " <chan num> is the channel number relative to the device\n"
12664 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12665 return NULL;
12666 case CLI_GENERATE:
12667 return NULL;
12670 lock = &iflock;
12672 if (a->argc != 6)
12673 return CLI_SHOWUSAGE;
12675 if (!strcasecmp("rx", a->argv[3]))
12676 tx = 0; /* rx */
12677 else if (!strcasecmp("tx", a->argv[3]))
12678 tx = 1; /* tx */
12679 else
12680 return CLI_SHOWUSAGE;
12682 channel = atoi(a->argv[4]);
12683 gain = atof(a->argv[5]);
12685 ast_mutex_lock(lock);
12686 for (tmp = iflist; tmp; tmp = tmp->next) {
12688 if (tmp->channel != channel)
12689 continue;
12691 if (tmp->subs[SUB_REAL].zfd == -1)
12692 break;
12694 if (tx)
12695 res = set_actual_txgain(tmp->subs[SUB_REAL].zfd, channel, gain, tmp->law);
12696 else
12697 res = set_actual_rxgain(tmp->subs[SUB_REAL].zfd, channel, gain, tmp->law);
12699 if (res) {
12700 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
12701 ast_mutex_unlock(lock);
12702 return CLI_FAILURE;
12705 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
12706 tx ? "tx" : "rx", gain, channel);
12707 break;
12709 ast_mutex_unlock(lock);
12711 if (tmp)
12712 return CLI_SUCCESS;
12714 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12715 return CLI_FAILURE;
12719 static char *handle_cli_zap_set_swgain_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12721 switch (cmd) {
12722 case CLI_INIT:
12723 e->command = "zap set swgain";
12724 e->usage =
12725 "Usage: zap set swgain <rx|tx> <chan#> <gain>\n"
12726 " Sets the software gain on a a given channel, overriding the\n"
12727 " value provided at module loadtime, whether the channel is in\n"
12728 " use or not. Changes take effect immediately.\n"
12729 " <rx|tx> which direction do you want to change (relative to our module)\n"
12730 " <chan num> is the channel number relative to the device\n"
12731 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12732 return NULL;
12733 case CLI_GENERATE:
12734 return NULL;
12735 case CLI_HANDLER:
12736 return dahdi_set_swgain(e, cmd, a);
12739 return CLI_FAILURE;
12742 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12744 int channel;
12745 int on;
12746 struct dahdi_pvt *dahdi_chan = NULL;
12748 switch (cmd) {
12749 case CLI_INIT:
12750 e->command = "dahdi set dnd";
12751 e->usage =
12752 "Usage: dahdi set dnd <chan#> <on|off>\n"
12753 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
12754 " Changes take effect immediately.\n"
12755 " <chan num> is the channel number\n"
12756 " <on|off> Enable or disable DND mode?\n"
12758 return NULL;
12759 case CLI_GENERATE:
12760 return NULL;
12763 if (a->argc != 5)
12764 return CLI_SHOWUSAGE;
12766 if ((channel = atoi(a->argv[3])) <= 0) {
12767 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
12768 return CLI_SHOWUSAGE;
12771 if (ast_true(a->argv[4]))
12772 on = 1;
12773 else if (ast_false(a->argv[4]))
12774 on = 0;
12775 else {
12776 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
12777 return CLI_SHOWUSAGE;
12780 ast_mutex_lock(&iflock);
12781 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
12782 if (dahdi_chan->channel != channel)
12783 continue;
12785 /* Found the channel. Actually set it */
12786 dahdi_dnd(dahdi_chan, on);
12787 break;
12789 ast_mutex_unlock(&iflock);
12791 if (!dahdi_chan) {
12792 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12793 return CLI_FAILURE;
12796 return CLI_SUCCESS;
12799 static char *handle_cli_zap_set_dnd_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12801 switch (cmd) {
12802 case CLI_INIT:
12803 e->command = "zap set dnd";
12804 e->usage =
12805 "Usage: zap set dnd <chan#> <on|off>\n"
12806 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
12807 " Changes take effect immediately.\n"
12808 " <chan num> is the channel number\n"
12809 " <on|off> Enable or disable DND mode?\n"
12811 return NULL;
12812 case CLI_GENERATE:
12813 return NULL;
12814 case CLI_HANDLER:
12815 return dahdi_set_dnd(e, cmd, a);
12818 return CLI_FAILURE;
12821 static struct ast_cli_entry cli_zap_show_cadences_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_cadences_deprecated, "List cadences");
12822 static struct ast_cli_entry cli_zap_show_channels_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_channels_deprecated, "Show active channels");
12823 static struct ast_cli_entry cli_zap_show_channel_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_channel_deprecated, "Show information on a channel");
12824 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = AST_CLI_DEFINE(handle_cli_zap_destroy_channel_deprecated, "Destroy a channel");
12825 static struct ast_cli_entry cli_zap_restart_cmd_deprecated = AST_CLI_DEFINE(handle_cli_zap_restart_cmd_deprecated, "Fully restart channels");
12826 static struct ast_cli_entry cli_zap_show_status_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_status_deprecated, "Show all cards status");
12827 static struct ast_cli_entry cli_zap_show_version_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_version_deprecated, "Show DAHDI version in use");
12828 static struct ast_cli_entry cli_zap_set_hwgain_deprecated = AST_CLI_DEFINE(handle_cli_zap_set_hwgain_deprecated, "Set hardware gain on a channel");
12829 static struct ast_cli_entry cli_zap_set_swgain_deprecated = AST_CLI_DEFINE(handle_cli_zap_set_swgain_deprecated, "Set software gain on a channel");
12830 static struct ast_cli_entry cli_zap_set_dnd_deprecated = AST_CLI_DEFINE(handle_cli_zap_set_dnd_deprecated, "Set software gain on a channel");
12832 static struct ast_cli_entry dahdi_cli[] = {
12833 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences", .deprecate_cmd = &cli_zap_show_cadences_deprecated),
12834 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels", .deprecate_cmd = &cli_zap_show_channels_deprecated),
12835 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel", .deprecate_cmd = &cli_zap_show_channel_deprecated),
12836 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel", .deprecate_cmd = &cli_zap_destroy_channel_deprecated),
12837 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels", .deprecate_cmd = &cli_zap_restart_cmd_deprecated),
12838 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status", .deprecate_cmd = &cli_zap_show_status_deprecated),
12839 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use", .deprecate_cmd = &cli_zap_show_version_deprecated),
12840 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel", .deprecate_cmd = &cli_zap_set_hwgain_deprecated),
12841 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel", .deprecate_cmd = &cli_zap_set_swgain_deprecated),
12842 AST_CLI_DEFINE(dahdi_set_dnd, "Set software gain on a channel", .deprecate_cmd = &cli_zap_set_dnd_deprecated),
12845 #define TRANSFER 0
12846 #define HANGUP 1
12848 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12850 if (p) {
12851 switch (mode) {
12852 case TRANSFER:
12853 p->fake_event = DAHDI_EVENT_WINKFLASH;
12854 break;
12855 case HANGUP:
12856 p->fake_event = DAHDI_EVENT_ONHOOK;
12857 break;
12858 default:
12859 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
12862 return 0;
12864 static struct dahdi_pvt *find_channel(int channel)
12866 struct dahdi_pvt *p = iflist;
12867 while (p) {
12868 if (p->channel == channel) {
12869 break;
12871 p = p->next;
12873 return p;
12876 static int action_dahdidndon(struct mansession *s, const struct message *m)
12878 struct dahdi_pvt *p = NULL;
12879 const char *channel = astman_get_header(m, "DAHDIChannel");
12881 if (ast_strlen_zero(channel)) {
12882 astman_send_error(s, m, "No channel specified");
12883 return 0;
12885 p = find_channel(atoi(channel));
12886 if (!p) {
12887 astman_send_error(s, m, "No such channel");
12888 return 0;
12890 p->dnd = 1;
12891 astman_send_ack(s, m, "DND Enabled");
12892 return 0;
12895 static int action_dahdidndoff(struct mansession *s, const struct message *m)
12897 struct dahdi_pvt *p = NULL;
12898 const char *channel = astman_get_header(m, "DAHDIChannel");
12900 if (ast_strlen_zero(channel)) {
12901 astman_send_error(s, m, "No channel specified");
12902 return 0;
12904 p = find_channel(atoi(channel));
12905 if (!p) {
12906 astman_send_error(s, m, "No such channel");
12907 return 0;
12909 p->dnd = 0;
12910 astman_send_ack(s, m, "DND Disabled");
12911 return 0;
12914 static int action_transfer(struct mansession *s, const struct message *m)
12916 struct dahdi_pvt *p = NULL;
12917 const char *channel = astman_get_header(m, "DAHDIChannel");
12919 if (ast_strlen_zero(channel)) {
12920 astman_send_error(s, m, "No channel specified");
12921 return 0;
12923 p = find_channel(atoi(channel));
12924 if (!p) {
12925 astman_send_error(s, m, "No such channel");
12926 return 0;
12928 dahdi_fake_event(p,TRANSFER);
12929 astman_send_ack(s, m, "DAHDITransfer");
12930 return 0;
12933 static int action_transferhangup(struct mansession *s, const struct message *m)
12935 struct dahdi_pvt *p = NULL;
12936 const char *channel = astman_get_header(m, "DAHDIChannel");
12938 if (ast_strlen_zero(channel)) {
12939 astman_send_error(s, m, "No channel specified");
12940 return 0;
12942 p = find_channel(atoi(channel));
12943 if (!p) {
12944 astman_send_error(s, m, "No such channel");
12945 return 0;
12947 dahdi_fake_event(p,HANGUP);
12948 astman_send_ack(s, m, "DAHDIHangup");
12949 return 0;
12952 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
12954 struct dahdi_pvt *p = NULL;
12955 const char *channel = astman_get_header(m, "DAHDIChannel");
12956 const char *number = astman_get_header(m, "Number");
12957 int i;
12959 if (ast_strlen_zero(channel)) {
12960 astman_send_error(s, m, "No channel specified");
12961 return 0;
12963 if (ast_strlen_zero(number)) {
12964 astman_send_error(s, m, "No number specified");
12965 return 0;
12967 p = find_channel(atoi(channel));
12968 if (!p) {
12969 astman_send_error(s, m, "No such channel");
12970 return 0;
12972 if (!p->owner) {
12973 astman_send_error(s, m, "Channel does not have it's owner");
12974 return 0;
12976 for (i = 0; i < strlen(number); i++) {
12977 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12978 dahdi_queue_frame(p, &f, NULL);
12980 astman_send_ack(s, m, "DAHDIDialOffhook");
12981 return 0;
12984 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
12986 struct dahdi_pvt *tmp = NULL;
12987 const char *id = astman_get_header(m, "ActionID");
12988 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
12989 char idText[256] = "";
12990 int channels = 0;
12991 int dahdichanquery = -1;
12992 if (!ast_strlen_zero(dahdichannel)) {
12993 dahdichanquery = atoi(dahdichannel);
12996 astman_send_ack(s, m, "DAHDI channel status will follow");
12997 if (!ast_strlen_zero(id))
12998 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13000 ast_mutex_lock(&iflock);
13002 tmp = iflist;
13003 while (tmp) {
13004 if (tmp->channel > 0) {
13005 int alarm = get_alarms(tmp);
13007 /* If a specific channel is queried for, only deliver status for that channel */
13008 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13009 continue;
13011 channels++;
13012 if (tmp->owner) {
13013 /* Add data if we have a current call */
13014 astman_append(s,
13015 "Event: DAHDIShowChannels\r\n"
13016 "DAHDIChannel: %d\r\n"
13017 "Channel: %s\r\n"
13018 "Uniqueid: %s\r\n"
13019 "AccountCode: %s\r\n"
13020 "Signalling: %s\r\n"
13021 "SignallingCode: %d\r\n"
13022 "Context: %s\r\n"
13023 "DND: %s\r\n"
13024 "Alarm: %s\r\n"
13025 "%s"
13026 "\r\n",
13027 tmp->channel,
13028 tmp->owner->name,
13029 tmp->owner->uniqueid,
13030 tmp->owner->accountcode,
13031 sig2str(tmp->sig),
13032 tmp->sig,
13033 tmp->context,
13034 tmp->dnd ? "Enabled" : "Disabled",
13035 alarm2str(alarm), idText);
13036 } else {
13037 astman_append(s,
13038 "Event: DAHDIShowChannels\r\n"
13039 "DAHDIChannel: %d\r\n"
13040 "Signalling: %s\r\n"
13041 "SignallingCode: %d\r\n"
13042 "Context: %s\r\n"
13043 "DND: %s\r\n"
13044 "Alarm: %s\r\n"
13045 "%s"
13046 "\r\n",
13047 tmp->channel, sig2str(tmp->sig), tmp->sig,
13048 tmp->context,
13049 tmp->dnd ? "Enabled" : "Disabled",
13050 alarm2str(alarm), idText);
13054 tmp = tmp->next;
13057 ast_mutex_unlock(&iflock);
13059 astman_append(s,
13060 "Event: DAHDIShowChannelsComplete\r\n"
13061 "%s"
13062 "Items: %d\r\n"
13063 "\r\n",
13064 idText,
13065 channels);
13066 return 0;
13069 static int __unload_module(void)
13071 int x;
13072 struct dahdi_pvt *p, *pl;
13073 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13074 int i;
13075 #endif
13077 #if defined(HAVE_PRI)
13078 for (i = 0; i < NUM_SPANS; i++) {
13079 if (pris[i].master != AST_PTHREADT_NULL)
13080 pthread_cancel(pris[i].master);
13082 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13083 ast_unregister_application(dahdi_send_keypad_facility_app);
13084 #endif
13086 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13087 ast_manager_unregister( "DAHDIDialOffhook" );
13088 ast_manager_unregister( "DAHDIHangup" );
13089 ast_manager_unregister( "DAHDITransfer" );
13090 ast_manager_unregister( "DAHDIDNDoff" );
13091 ast_manager_unregister( "DAHDIDNDon" );
13092 ast_manager_unregister("DAHDIShowChannels");
13093 ast_manager_unregister("DAHDIRestart");
13094 ast_channel_unregister(&dahdi_tech);
13095 ast_mutex_lock(&iflock);
13096 /* Hangup all interfaces if they have an owner */
13097 p = iflist;
13098 while (p) {
13099 if (p->owner)
13100 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
13101 p = p->next;
13103 ast_mutex_unlock(&iflock);
13104 ast_mutex_lock(&monlock);
13105 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13106 pthread_cancel(monitor_thread);
13107 pthread_kill(monitor_thread, SIGURG);
13108 pthread_join(monitor_thread, NULL);
13110 monitor_thread = AST_PTHREADT_STOP;
13111 ast_mutex_unlock(&monlock);
13113 ast_mutex_lock(&iflock);
13114 /* Destroy all the interfaces and free their memory */
13115 p = iflist;
13116 while (p) {
13117 /* Free any callerid */
13118 if (p->cidspill)
13119 ast_free(p->cidspill);
13120 /* Close the DAHDI thingy */
13121 if (p->subs[SUB_REAL].zfd > -1)
13122 dahdi_close(p->subs[SUB_REAL].zfd);
13123 pl = p;
13124 p = p->next;
13125 x = pl->channel;
13126 /* Free associated memory */
13127 if (pl)
13128 destroy_dahdi_pvt(&pl);
13129 ast_verb(3, "Unregistered channel %d\n", x);
13131 iflist = NULL;
13132 ifcount = 0;
13133 ast_mutex_unlock(&iflock);
13135 #if defined(HAVE_PRI)
13136 for (i = 0; i < NUM_SPANS; i++) {
13137 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
13138 pthread_join(pris[i].master, NULL);
13139 dahdi_close(pris[i].fds[i]);
13141 #endif /* HAVE_PRI */
13143 #if defined(HAVE_SS7)
13144 for (i = 0; i < NUM_SPANS; i++) {
13145 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
13146 pthread_join(linksets[i].master, NULL);
13147 dahdi_close(linksets[i].fds[i]);
13149 #endif /* HAVE_SS7 */
13151 return 0;
13154 #ifdef HAVE_SS7
13155 static int linkset_addsigchan(int sigchan)
13157 struct dahdi_ss7 *link;
13158 int res;
13159 int curfd;
13160 DAHDI_PARAMS p;
13161 DAHDI_BUFFERINFO bi;
13162 struct dahdi_spaninfo si;
13165 link = ss7_resolve_linkset(cur_linkset);
13166 if (!link) {
13167 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
13168 return -1;
13171 if (cur_ss7type < 0) {
13172 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13173 return -1;
13176 if (!link->ss7)
13177 link->ss7 = ss7_new(cur_ss7type);
13179 if (!link->ss7) {
13180 ast_log(LOG_ERROR, "Can't create new SS7!\n");
13181 return -1;
13184 link->type = cur_ss7type;
13186 if (cur_pointcode < 0) {
13187 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13188 return -1;
13189 } else
13190 ss7_set_pc(link->ss7, cur_pointcode);
13192 if (sigchan < 0) {
13193 ast_log(LOG_ERROR, "Invalid sigchan!\n");
13194 return -1;
13195 } else {
13196 if (link->numsigchans >= NUM_DCHANS) {
13197 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13198 return -1;
13200 curfd = link->numsigchans;
13202 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13203 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13204 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13205 return -1;
13207 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13208 if (res) {
13209 dahdi_close(link->fds[curfd]);
13210 link->fds[curfd] = -1;
13211 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13212 return -1;
13214 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13215 dahdi_close(link->fds[curfd]);
13216 link->fds[curfd] = -1;
13217 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13218 return -1;
13221 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13222 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13223 bi.numbufs = 32;
13224 bi.bufsize = 512;
13226 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13227 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13228 dahdi_close(link->fds[curfd]);
13229 link->fds[curfd] = -1;
13230 return -1;
13233 if (p.sigtype == DAHDI_SIG_MTP2)
13234 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13235 else
13236 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13238 link->numsigchans++;
13240 memset(&si, 0, sizeof(si));
13241 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13242 if (res) {
13243 dahdi_close(link->fds[curfd]);
13244 link->fds[curfd] = -1;
13245 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13248 if (!si.alarms) {
13249 link->linkstate[curfd] = LINKSTATE_DOWN;
13250 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13251 } else {
13252 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13253 ss7_link_alarm(link->ss7, link->fds[curfd]);
13257 if (cur_adjpointcode < 0) {
13258 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13259 return -1;
13260 } else {
13261 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13264 if (cur_defaultdpc < 0) {
13265 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13266 return -1;
13269 if (cur_networkindicator < 0) {
13270 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13271 return -1;
13272 } else
13273 ss7_set_network_ind(link->ss7, cur_networkindicator);
13275 return 0;
13278 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13280 int span;
13281 switch (cmd) {
13282 case CLI_INIT:
13283 e->command = "ss7 no debug linkset";
13284 e->usage =
13285 "Usage: ss7 no debug linkset <span>\n"
13286 " Disables debugging on a given SS7 linkset\n";
13287 return NULL;
13288 case CLI_GENERATE:
13289 return NULL;
13291 if (a->argc < 5)
13292 return CLI_SHOWUSAGE;
13293 span = atoi(a->argv[4]);
13294 if ((span < 1) || (span > NUM_SPANS)) {
13295 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13296 return CLI_SUCCESS;
13298 if (!linksets[span-1].ss7) {
13299 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13300 return CLI_SUCCESS;
13302 if (linksets[span-1].ss7)
13303 ss7_set_debug(linksets[span-1].ss7, 0);
13305 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13306 return CLI_SUCCESS;
13309 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13311 int span;
13312 switch (cmd) {
13313 case CLI_INIT:
13314 e->command = "ss7 debug linkset";
13315 e->usage =
13316 "Usage: ss7 debug linkset <linkset>\n"
13317 " Enables debugging on a given SS7 linkset\n";
13318 return NULL;
13319 case CLI_GENERATE:
13320 return NULL;
13322 if (a->argc < 4)
13323 return CLI_SHOWUSAGE;
13324 span = atoi(a->argv[3]);
13325 if ((span < 1) || (span > NUM_SPANS)) {
13326 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13327 return CLI_SUCCESS;
13329 if (!linksets[span-1].ss7) {
13330 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13331 return CLI_SUCCESS;
13333 if (linksets[span-1].ss7)
13334 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13336 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13337 return CLI_SUCCESS;
13340 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13342 int linkset, cic;
13343 int blocked = -1, i;
13344 switch (cmd) {
13345 case CLI_INIT:
13346 e->command = "ss7 block cic";
13347 e->usage =
13348 "Usage: ss7 block cic <linkset> <CIC>\n"
13349 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13350 return NULL;
13351 case CLI_GENERATE:
13352 return NULL;
13354 if (a->argc == 5)
13355 linkset = atoi(a->argv[3]);
13356 else
13357 return CLI_SHOWUSAGE;
13359 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13360 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13361 return CLI_SUCCESS;
13364 if (!linksets[linkset-1].ss7) {
13365 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13366 return CLI_SUCCESS;
13369 cic = atoi(a->argv[4]);
13371 if (cic < 1) {
13372 ast_cli(a->fd, "Invalid CIC specified!\n");
13373 return CLI_SUCCESS;
13376 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13377 if (linksets[linkset-1].pvts[i]->cic == cic) {
13378 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13379 if (!blocked) {
13380 ast_mutex_lock(&linksets[linkset-1].lock);
13381 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13382 ast_mutex_unlock(&linksets[linkset-1].lock);
13387 if (blocked < 0) {
13388 ast_cli(a->fd, "Invalid CIC specified!\n");
13389 return CLI_SUCCESS;
13392 if (!blocked)
13393 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13394 else
13395 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13397 return CLI_SUCCESS;
13400 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13402 int linkset;
13403 int i;
13404 switch (cmd) {
13405 case CLI_INIT:
13406 e->command = "ss7 block linkset";
13407 e->usage =
13408 "Usage: ss7 block linkset <linkset number>\n"
13409 " Sends a remote blocking request for all CICs on the given linkset\n";
13410 return NULL;
13411 case CLI_GENERATE:
13412 return NULL;
13414 if (a->argc == 4)
13415 linkset = atoi(a->argv[3]);
13416 else
13417 return CLI_SHOWUSAGE;
13419 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13420 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13421 return CLI_SUCCESS;
13424 if (!linksets[linkset-1].ss7) {
13425 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13426 return CLI_SUCCESS;
13429 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13430 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13431 ast_mutex_lock(&linksets[linkset-1].lock);
13432 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13433 ast_mutex_unlock(&linksets[linkset-1].lock);
13436 return CLI_SUCCESS;
13439 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13441 int linkset, cic;
13442 int i, blocked = -1;
13443 switch (cmd) {
13444 case CLI_INIT:
13445 e->command = "ss7 unblock cic";
13446 e->usage =
13447 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13448 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13449 return NULL;
13450 case CLI_GENERATE:
13451 return NULL;
13454 if (a->argc == 5)
13455 linkset = atoi(a->argv[3]);
13456 else
13457 return CLI_SHOWUSAGE;
13459 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13460 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13461 return CLI_SUCCESS;
13464 if (!linksets[linkset-1].ss7) {
13465 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13466 return CLI_SUCCESS;
13469 cic = atoi(a->argv[4]);
13471 if (cic < 1) {
13472 ast_cli(a->fd, "Invalid CIC specified!\n");
13473 return CLI_SUCCESS;
13476 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13477 if (linksets[linkset-1].pvts[i]->cic == cic) {
13478 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13479 if (blocked) {
13480 ast_mutex_lock(&linksets[linkset-1].lock);
13481 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13482 ast_mutex_unlock(&linksets[linkset-1].lock);
13487 if (blocked > 0)
13488 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13489 return CLI_SUCCESS;
13492 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13494 int linkset;
13495 int i;
13496 switch (cmd) {
13497 case CLI_INIT:
13498 e->command = "ss7 unblock linkset";
13499 e->usage =
13500 "Usage: ss7 unblock linkset <linkset number>\n"
13501 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13502 return NULL;
13503 case CLI_GENERATE:
13504 return NULL;
13507 if (a->argc == 4)
13508 linkset = atoi(a->argv[3]);
13509 else
13510 return CLI_SHOWUSAGE;
13512 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13513 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13514 return CLI_SUCCESS;
13517 if (!linksets[linkset-1].ss7) {
13518 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13519 return CLI_SUCCESS;
13522 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13523 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13524 ast_mutex_lock(&linksets[linkset-1].lock);
13525 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13526 ast_mutex_unlock(&linksets[linkset-1].lock);
13529 return CLI_SUCCESS;
13532 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13534 int linkset;
13535 struct dahdi_ss7 *ss7;
13536 switch (cmd) {
13537 case CLI_INIT:
13538 e->command = "ss7 show linkset";
13539 e->usage =
13540 "Usage: ss7 show linkset <span>\n"
13541 " Shows the status of an SS7 linkset.\n";
13542 return NULL;
13543 case CLI_GENERATE:
13544 return NULL;
13547 if (a->argc < 4)
13548 return CLI_SHOWUSAGE;
13549 linkset = atoi(a->argv[3]);
13550 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13551 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13552 return CLI_SUCCESS;
13554 if (!linksets[linkset-1].ss7) {
13555 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13556 return CLI_SUCCESS;
13558 if (linksets[linkset-1].ss7)
13559 ss7 = &linksets[linkset-1];
13561 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13563 return CLI_SUCCESS;
13566 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13568 switch (cmd) {
13569 case CLI_INIT:
13570 e->command = "ss7 show version";
13571 return NULL;
13572 case CLI_GENERATE:
13573 return NULL;
13576 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
13578 return CLI_SUCCESS;
13581 static struct ast_cli_entry dahdi_ss7_cli[] = {
13582 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
13583 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
13584 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
13585 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
13586 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
13587 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
13588 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
13589 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
13591 #endif /* HAVE_SS7 */
13593 static int unload_module(void)
13595 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13596 int y;
13597 #endif
13598 #ifdef HAVE_PRI
13599 for (y = 0; y < NUM_SPANS; y++)
13600 ast_mutex_destroy(&pris[y].lock);
13601 #endif
13602 #ifdef HAVE_SS7
13603 for (y = 0; y < NUM_SPANS; y++)
13604 ast_mutex_destroy(&linksets[y].lock);
13605 #endif /* HAVE_SS7 */
13606 return __unload_module();
13609 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
13611 char *c, *chan;
13612 int x, start, finish;
13613 struct dahdi_pvt *tmp;
13614 #ifdef HAVE_PRI
13615 struct dahdi_pri *pri;
13616 int trunkgroup, y;
13617 #endif
13619 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
13620 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
13621 return -1;
13624 c = ast_strdupa(value);
13626 #ifdef HAVE_PRI
13627 pri = NULL;
13628 if (iscrv) {
13629 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
13630 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
13631 return -1;
13633 if (trunkgroup < 1) {
13634 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
13635 return -1;
13637 c += y;
13638 for (y = 0; y < NUM_SPANS; y++) {
13639 if (pris[y].trunkgroup == trunkgroup) {
13640 pri = pris + y;
13641 break;
13644 if (!pri) {
13645 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
13646 return -1;
13649 #endif
13651 while ((chan = strsep(&c, ","))) {
13652 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
13653 /* Range */
13654 } else if (sscanf(chan, "%d", &start)) {
13655 /* Just one */
13656 finish = start;
13657 } else if (!strcasecmp(chan, "pseudo")) {
13658 finish = start = CHAN_PSEUDO;
13659 if (found_pseudo)
13660 *found_pseudo = 1;
13661 } else {
13662 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
13663 return -1;
13665 if (finish < start) {
13666 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
13667 x = finish;
13668 finish = start;
13669 start = x;
13672 for (x = start; x <= finish; x++) {
13673 #ifdef HAVE_PRI
13674 tmp = mkintf(x, conf, pri, reload);
13675 #else
13676 tmp = mkintf(x, conf, NULL, reload);
13677 #endif
13679 if (tmp) {
13680 #ifdef HAVE_PRI
13681 if (pri)
13682 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
13683 else
13684 #endif
13685 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
13686 } else {
13687 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
13688 (reload == 1) ? "reconfigure" : "register", value);
13689 return -1;
13694 return 0;
13697 /** The length of the parameters list of 'dahdichan'.
13698 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
13699 #define MAX_CHANLIST_LEN 80
13701 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
13703 char *parse = ast_strdupa(data);
13704 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
13705 unsigned int param_count;
13706 unsigned int x;
13708 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
13709 return;
13711 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
13713 /* first parameter is tap length, process it here */
13715 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
13717 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
13718 confp->chan.echocancel.head.tap_length = x;
13719 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
13720 confp->chan.echocancel.head.tap_length = 128;
13722 /* now process any remaining parameters */
13724 for (x = 1; x < param_count; x++) {
13725 struct {
13726 char *name;
13727 char *value;
13728 } param;
13730 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
13731 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
13732 continue;
13735 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
13736 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
13737 continue;
13740 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
13742 if (param.value) {
13743 if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
13744 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
13745 continue;
13748 confp->chan.echocancel.head.param_count++;
13752 /*! process_dahdi() - ignore keyword 'channel' and similar */
13753 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
13754 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
13755 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
13757 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
13759 struct dahdi_pvt *tmp;
13760 const char *ringc; /* temporary string for parsing the dring number. */
13761 int y;
13762 int found_pseudo = 0;
13763 char dahdichan[MAX_CHANLIST_LEN] = {};
13765 for (; v; v = v->next) {
13766 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
13767 continue;
13769 /* must have parkinglot in confp before build_channels is called */
13770 if (!strcasecmp(v->name, "parkinglot")) {
13771 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
13774 /* Create the interface list */
13775 if (!strcasecmp(v->name, "channel")
13776 #ifdef HAVE_PRI
13777 || !strcasecmp(v->name, "crv")
13778 #endif
13780 int iscrv;
13781 if (options && PROC_DAHDI_OPT_NOCHAN)
13782 continue;
13783 iscrv = !strcasecmp(v->name, "crv");
13784 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
13785 return -1;
13786 } else if (!strcasecmp(v->name, "dahdichan")) {
13787 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
13788 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
13789 usedistinctiveringdetection = ast_true(v->value);
13790 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
13791 distinctiveringaftercid = ast_true(v->value);
13792 } else if (!strcasecmp(v->name, "dring1context")) {
13793 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
13794 } else if (!strcasecmp(v->name, "dring2context")) {
13795 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
13796 } else if (!strcasecmp(v->name, "dring3context")) {
13797 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
13798 } else if (!strcasecmp(v->name, "dring1range")) {
13799 confp->chan.drings.ringnum[0].range = atoi(v->value);
13800 } else if (!strcasecmp(v->name, "dring2range")) {
13801 confp->chan.drings.ringnum[1].range = atoi(v->value);
13802 } else if (!strcasecmp(v->name, "dring3range")) {
13803 confp->chan.drings.ringnum[2].range = atoi(v->value);
13804 } else if (!strcasecmp(v->name, "dring1")) {
13805 ringc = v->value;
13806 sscanf(ringc, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
13807 } else if (!strcasecmp(v->name, "dring2")) {
13808 ringc = v->value;
13809 sscanf(ringc,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
13810 } else if (!strcasecmp(v->name, "dring3")) {
13811 ringc = v->value;
13812 sscanf(ringc, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
13813 } else if (!strcasecmp(v->name, "usecallerid")) {
13814 confp->chan.use_callerid = ast_true(v->value);
13815 } else if (!strcasecmp(v->name, "cidsignalling")) {
13816 if (!strcasecmp(v->value, "bell"))
13817 confp->chan.cid_signalling = CID_SIG_BELL;
13818 else if (!strcasecmp(v->value, "v23"))
13819 confp->chan.cid_signalling = CID_SIG_V23;
13820 else if (!strcasecmp(v->value, "dtmf"))
13821 confp->chan.cid_signalling = CID_SIG_DTMF;
13822 else if (!strcasecmp(v->value, "smdi"))
13823 confp->chan.cid_signalling = CID_SIG_SMDI;
13824 else if (!strcasecmp(v->value, "v23_jp"))
13825 confp->chan.cid_signalling = CID_SIG_V23_JP;
13826 else if (ast_true(v->value))
13827 confp->chan.cid_signalling = CID_SIG_BELL;
13828 } else if (!strcasecmp(v->name, "cidstart")) {
13829 if (!strcasecmp(v->value, "ring"))
13830 confp->chan.cid_start = CID_START_RING;
13831 else if (!strcasecmp(v->value, "polarity_in"))
13832 confp->chan.cid_start = CID_START_POLARITY_IN;
13833 else if (!strcasecmp(v->value, "polarity"))
13834 confp->chan.cid_start = CID_START_POLARITY;
13835 else if (ast_true(v->value))
13836 confp->chan.cid_start = CID_START_RING;
13837 } else if (!strcasecmp(v->name, "threewaycalling")) {
13838 confp->chan.threewaycalling = ast_true(v->value);
13839 } else if (!strcasecmp(v->name, "cancallforward")) {
13840 confp->chan.cancallforward = ast_true(v->value);
13841 } else if (!strcasecmp(v->name, "relaxdtmf")) {
13842 if (ast_true(v->value))
13843 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
13844 else
13845 confp->chan.dtmfrelax = 0;
13846 } else if (!strcasecmp(v->name, "mailbox")) {
13847 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
13848 } else if (!strcasecmp(v->name, "hasvoicemail")) {
13849 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
13850 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
13852 } else if (!strcasecmp(v->name, "adsi")) {
13853 confp->chan.adsi = ast_true(v->value);
13854 } else if (!strcasecmp(v->name, "usesmdi")) {
13855 confp->chan.use_smdi = ast_true(v->value);
13856 } else if (!strcasecmp(v->name, "smdiport")) {
13857 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
13858 } else if (!strcasecmp(v->name, "transfer")) {
13859 confp->chan.transfer = ast_true(v->value);
13860 } else if (!strcasecmp(v->name, "canpark")) {
13861 confp->chan.canpark = ast_true(v->value);
13862 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
13863 confp->chan.echocanbridged = ast_true(v->value);
13864 } else if (!strcasecmp(v->name, "busydetect")) {
13865 confp->chan.busydetect = ast_true(v->value);
13866 } else if (!strcasecmp(v->name, "busycount")) {
13867 confp->chan.busycount = atoi(v->value);
13868 } else if (!strcasecmp(v->name, "busypattern")) {
13869 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
13870 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
13872 } else if (!strcasecmp(v->name, "callprogress")) {
13873 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
13874 if (ast_true(v->value))
13875 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
13876 } else if (!strcasecmp(v->name, "faxdetect")) {
13877 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
13878 if (!strcasecmp(v->value, "incoming")) {
13879 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
13880 } else if (!strcasecmp(v->value, "outgoing")) {
13881 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
13882 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13883 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
13884 } else if (!strcasecmp(v->name, "echocancel")) {
13885 process_echocancel(confp, v->value, v->lineno);
13886 } else if (!strcasecmp(v->name, "echotraining")) {
13887 if (sscanf(v->value, "%d", &y) == 1) {
13888 if ((y < 10) || (y > 4000)) {
13889 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
13890 } else {
13891 confp->chan.echotraining = y;
13893 } else if (ast_true(v->value)) {
13894 confp->chan.echotraining = 400;
13895 } else
13896 confp->chan.echotraining = 0;
13897 } else if (!strcasecmp(v->name, "hidecallerid")) {
13898 confp->chan.hidecallerid = ast_true(v->value);
13899 } else if (!strcasecmp(v->name, "hidecalleridname")) {
13900 confp->chan.hidecalleridname = ast_true(v->value);
13901 } else if (!strcasecmp(v->name, "pulsedial")) {
13902 confp->chan.pulse = ast_true(v->value);
13903 } else if (!strcasecmp(v->name, "callreturn")) {
13904 confp->chan.callreturn = ast_true(v->value);
13905 } else if (!strcasecmp(v->name, "callwaiting")) {
13906 confp->chan.callwaiting = ast_true(v->value);
13907 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13908 confp->chan.callwaitingcallerid = ast_true(v->value);
13909 } else if (!strcasecmp(v->name, "context")) {
13910 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13911 } else if (!strcasecmp(v->name, "language")) {
13912 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13913 } else if (!strcasecmp(v->name, "progzone")) {
13914 ast_copy_string(progzone, v->value, sizeof(progzone));
13915 } else if (!strcasecmp(v->name, "mohinterpret")
13916 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13917 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13918 } else if (!strcasecmp(v->name, "mohsuggest")) {
13919 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13920 } else if (!strcasecmp(v->name, "parkinglot")) {
13921 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
13922 } else if (!strcasecmp(v->name, "stripmsd")) {
13923 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
13924 confp->chan.stripmsd = atoi(v->value);
13925 } else if (!strcasecmp(v->name, "jitterbuffers")) {
13926 numbufs = atoi(v->value);
13927 } else if (!strcasecmp(v->name, "group")) {
13928 confp->chan.group = ast_get_group(v->value);
13929 } else if (!strcasecmp(v->name, "callgroup")) {
13930 if (!strcasecmp(v->value, "none"))
13931 confp->chan.callgroup = 0;
13932 else
13933 confp->chan.callgroup = ast_get_group(v->value);
13934 } else if (!strcasecmp(v->name, "pickupgroup")) {
13935 if (!strcasecmp(v->value, "none"))
13936 confp->chan.pickupgroup = 0;
13937 else
13938 confp->chan.pickupgroup = ast_get_group(v->value);
13939 } else if (!strcasecmp(v->name, "setvar")) {
13940 char *varname = ast_strdupa(v->value), *varval = NULL;
13941 struct ast_variable *tmpvar;
13942 if (varname && (varval = strchr(varname, '='))) {
13943 *varval++ = '\0';
13944 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
13945 tmpvar->next = confp->chan.vars;
13946 confp->chan.vars = tmpvar;
13949 } else if (!strcasecmp(v->name, "immediate")) {
13950 confp->chan.immediate = ast_true(v->value);
13951 } else if (!strcasecmp(v->name, "transfertobusy")) {
13952 confp->chan.transfertobusy = ast_true(v->value);
13953 } else if (!strcasecmp(v->name, "mwimonitor")) {
13954 if (!strcasecmp(v->value, "neon")) {
13955 confp->chan.mwimonitor_neon = 1;
13956 confp->chan.mwimonitor_fsk = 0;
13957 } else {
13958 confp->chan.mwimonitor_neon = 0;
13959 if (!strcasecmp(v->value, "fsk"))
13960 confp->chan.mwimonitor_fsk = 1;
13961 else
13962 confp->chan.mwimonitor_fsk = ast_true(v->value) ? 1 : 0;
13964 } else if (!strcasecmp(v->name, "cid_rxgain")) {
13965 if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
13966 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
13968 } else if (!strcasecmp(v->name, "rxgain")) {
13969 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
13970 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
13972 } else if (!strcasecmp(v->name, "txgain")) {
13973 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
13974 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
13976 } else if (!strcasecmp(v->name, "tonezone")) {
13977 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
13978 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
13980 } else if (!strcasecmp(v->name, "callerid")) {
13981 if (!strcasecmp(v->value, "asreceived")) {
13982 confp->chan.cid_num[0] = '\0';
13983 confp->chan.cid_name[0] = '\0';
13984 } else {
13985 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13987 } else if (!strcasecmp(v->name, "fullname")) {
13988 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13989 } else if (!strcasecmp(v->name, "cid_number")) {
13990 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13991 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
13992 confp->chan.dahditrcallerid = ast_true(v->value);
13993 } else if (!strcasecmp(v->name, "restrictcid")) {
13994 confp->chan.restrictcid = ast_true(v->value);
13995 } else if (!strcasecmp(v->name, "usecallingpres")) {
13996 confp->chan.use_callingpres = ast_true(v->value);
13997 } else if (!strcasecmp(v->name, "accountcode")) {
13998 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13999 } else if (!strcasecmp(v->name, "amaflags")) {
14000 y = ast_cdr_amaflags2int(v->value);
14001 if (y < 0)
14002 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14003 else
14004 confp->chan.amaflags = y;
14005 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14006 confp->chan.polarityonanswerdelay = atoi(v->value);
14007 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14008 confp->chan.answeronpolarityswitch = ast_true(v->value);
14009 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14010 confp->chan.hanguponpolarityswitch = ast_true(v->value);
14011 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14012 confp->chan.sendcalleridafter = atoi(v->value);
14013 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14014 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14015 } else if (!strcasecmp(v->name, "mwisendtype")) {
14016 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
14017 mwisend_rpas = 1;
14018 } else {
14019 mwisend_rpas = 0;
14021 } else if (!reload){
14022 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14023 int orig_radio = confp->chan.radio;
14024 int orig_outsigmod = confp->chan.outsigmod;
14025 int orig_auto = confp->is_sig_auto;
14027 confp->chan.radio = 0;
14028 confp->chan.outsigmod = -1;
14029 confp->is_sig_auto = 0;
14030 if (!strcasecmp(v->value, "em")) {
14031 confp->chan.sig = SIG_EM;
14032 } else if (!strcasecmp(v->value, "em_e1")) {
14033 confp->chan.sig = SIG_EM_E1;
14034 } else if (!strcasecmp(v->value, "em_w")) {
14035 confp->chan.sig = SIG_EMWINK;
14036 } else if (!strcasecmp(v->value, "fxs_ls")) {
14037 confp->chan.sig = SIG_FXSLS;
14038 } else if (!strcasecmp(v->value, "fxs_gs")) {
14039 confp->chan.sig = SIG_FXSGS;
14040 } else if (!strcasecmp(v->value, "fxs_ks")) {
14041 confp->chan.sig = SIG_FXSKS;
14042 } else if (!strcasecmp(v->value, "fxo_ls")) {
14043 confp->chan.sig = SIG_FXOLS;
14044 } else if (!strcasecmp(v->value, "fxo_gs")) {
14045 confp->chan.sig = SIG_FXOGS;
14046 } else if (!strcasecmp(v->value, "fxo_ks")) {
14047 confp->chan.sig = SIG_FXOKS;
14048 } else if (!strcasecmp(v->value, "fxs_rx")) {
14049 confp->chan.sig = SIG_FXSKS;
14050 confp->chan.radio = 1;
14051 } else if (!strcasecmp(v->value, "fxo_rx")) {
14052 confp->chan.sig = SIG_FXOLS;
14053 confp->chan.radio = 1;
14054 } else if (!strcasecmp(v->value, "fxs_tx")) {
14055 confp->chan.sig = SIG_FXSLS;
14056 confp->chan.radio = 1;
14057 } else if (!strcasecmp(v->value, "fxo_tx")) {
14058 confp->chan.sig = SIG_FXOGS;
14059 confp->chan.radio = 1;
14060 } else if (!strcasecmp(v->value, "em_rx")) {
14061 confp->chan.sig = SIG_EM;
14062 confp->chan.radio = 1;
14063 } else if (!strcasecmp(v->value, "em_tx")) {
14064 confp->chan.sig = SIG_EM;
14065 confp->chan.radio = 1;
14066 } else if (!strcasecmp(v->value, "em_rxtx")) {
14067 confp->chan.sig = SIG_EM;
14068 confp->chan.radio = 2;
14069 } else if (!strcasecmp(v->value, "em_txrx")) {
14070 confp->chan.sig = SIG_EM;
14071 confp->chan.radio = 2;
14072 } else if (!strcasecmp(v->value, "sf")) {
14073 confp->chan.sig = SIG_SF;
14074 } else if (!strcasecmp(v->value, "sf_w")) {
14075 confp->chan.sig = SIG_SFWINK;
14076 } else if (!strcasecmp(v->value, "sf_featd")) {
14077 confp->chan.sig = SIG_FEATD;
14078 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14079 confp->chan.sig = SIG_FEATDMF;
14080 } else if (!strcasecmp(v->value, "sf_featb")) {
14081 confp->chan.sig = SIG_SF_FEATB;
14082 } else if (!strcasecmp(v->value, "sf")) {
14083 confp->chan.sig = SIG_SF;
14084 } else if (!strcasecmp(v->value, "sf_rx")) {
14085 confp->chan.sig = SIG_SF;
14086 confp->chan.radio = 1;
14087 } else if (!strcasecmp(v->value, "sf_tx")) {
14088 confp->chan.sig = SIG_SF;
14089 confp->chan.radio = 1;
14090 } else if (!strcasecmp(v->value, "sf_rxtx")) {
14091 confp->chan.sig = SIG_SF;
14092 confp->chan.radio = 2;
14093 } else if (!strcasecmp(v->value, "sf_txrx")) {
14094 confp->chan.sig = SIG_SF;
14095 confp->chan.radio = 2;
14096 } else if (!strcasecmp(v->value, "featd")) {
14097 confp->chan.sig = SIG_FEATD;
14098 } else if (!strcasecmp(v->value, "featdmf")) {
14099 confp->chan.sig = SIG_FEATDMF;
14100 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14101 confp->chan.sig = SIG_FEATDMF_TA;
14102 } else if (!strcasecmp(v->value, "e911")) {
14103 confp->chan.sig = SIG_E911;
14104 } else if (!strcasecmp(v->value, "fgccama")) {
14105 confp->chan.sig = SIG_FGC_CAMA;
14106 } else if (!strcasecmp(v->value, "fgccamamf")) {
14107 confp->chan.sig = SIG_FGC_CAMAMF;
14108 } else if (!strcasecmp(v->value, "featb")) {
14109 confp->chan.sig = SIG_FEATB;
14110 #ifdef HAVE_PRI
14111 } else if (!strcasecmp(v->value, "pri_net")) {
14112 confp->chan.sig = SIG_PRI;
14113 confp->pri.nodetype = PRI_NETWORK;
14114 } else if (!strcasecmp(v->value, "pri_cpe")) {
14115 confp->chan.sig = SIG_PRI;
14116 confp->pri.nodetype = PRI_CPE;
14117 } else if (!strcasecmp(v->value, "bri_cpe")) {
14118 confp->chan.sig = SIG_BRI;
14119 confp->pri.nodetype = PRI_CPE;
14120 } else if (!strcasecmp(v->value, "bri_net")) {
14121 confp->chan.sig = SIG_BRI;
14122 confp->pri.nodetype = PRI_NETWORK;
14123 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14124 confp->chan.sig = SIG_BRI_PTMP;
14125 confp->pri.nodetype = PRI_CPE;
14126 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14127 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
14128 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14129 confp->chan.sig = SIG_GR303FXOKS;
14130 confp->pri.nodetype = PRI_NETWORK;
14131 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14132 confp->chan.sig = SIG_GR303FXSKS;
14133 confp->pri.nodetype = PRI_CPE;
14134 #endif
14135 #ifdef HAVE_SS7
14136 } else if (!strcasecmp(v->value, "ss7")) {
14137 confp->chan.sig = SIG_SS7;
14138 #endif
14139 } else if (!strcasecmp(v->value, "auto")) {
14140 confp->is_sig_auto = 1;
14141 } else {
14142 confp->chan.outsigmod = orig_outsigmod;
14143 confp->chan.radio = orig_radio;
14144 confp->is_sig_auto = orig_auto;
14145 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14147 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14148 if (!strcasecmp(v->value, "em")) {
14149 confp->chan.outsigmod = SIG_EM;
14150 } else if (!strcasecmp(v->value, "em_e1")) {
14151 confp->chan.outsigmod = SIG_EM_E1;
14152 } else if (!strcasecmp(v->value, "em_w")) {
14153 confp->chan.outsigmod = SIG_EMWINK;
14154 } else if (!strcasecmp(v->value, "sf")) {
14155 confp->chan.outsigmod = SIG_SF;
14156 } else if (!strcasecmp(v->value, "sf_w")) {
14157 confp->chan.outsigmod = SIG_SFWINK;
14158 } else if (!strcasecmp(v->value, "sf_featd")) {
14159 confp->chan.outsigmod = SIG_FEATD;
14160 } else if (!strcasecmp(v->value, "sf_featdmf")) {
14161 confp->chan.outsigmod = SIG_FEATDMF;
14162 } else if (!strcasecmp(v->value, "sf_featb")) {
14163 confp->chan.outsigmod = SIG_SF_FEATB;
14164 } else if (!strcasecmp(v->value, "sf")) {
14165 confp->chan.outsigmod = SIG_SF;
14166 } else if (!strcasecmp(v->value, "featd")) {
14167 confp->chan.outsigmod = SIG_FEATD;
14168 } else if (!strcasecmp(v->value, "featdmf")) {
14169 confp->chan.outsigmod = SIG_FEATDMF;
14170 } else if (!strcasecmp(v->value, "featdmf_ta")) {
14171 confp->chan.outsigmod = SIG_FEATDMF_TA;
14172 } else if (!strcasecmp(v->value, "e911")) {
14173 confp->chan.outsigmod = SIG_E911;
14174 } else if (!strcasecmp(v->value, "fgccama")) {
14175 confp->chan.outsigmod = SIG_FGC_CAMA;
14176 } else if (!strcasecmp(v->value, "fgccamamf")) {
14177 confp->chan.outsigmod = SIG_FGC_CAMAMF;
14178 } else if (!strcasecmp(v->value, "featb")) {
14179 confp->chan.outsigmod = SIG_FEATB;
14180 } else {
14181 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14183 #ifdef HAVE_PRI
14184 } else if (!strcasecmp(v->name, "pridialplan")) {
14185 if (!strcasecmp(v->value, "national")) {
14186 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14187 } else if (!strcasecmp(v->value, "unknown")) {
14188 confp->pri.dialplan = PRI_UNKNOWN + 1;
14189 } else if (!strcasecmp(v->value, "private")) {
14190 confp->pri.dialplan = PRI_PRIVATE + 1;
14191 } else if (!strcasecmp(v->value, "international")) {
14192 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14193 } else if (!strcasecmp(v->value, "local")) {
14194 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14195 } else if (!strcasecmp(v->value, "dynamic")) {
14196 confp->pri.dialplan = -1;
14197 } else if (!strcasecmp(v->value, "redundant")) {
14198 confp->pri.dialplan = -2;
14199 } else {
14200 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14202 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14203 if (!strcasecmp(v->value, "national")) {
14204 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14205 } else if (!strcasecmp(v->value, "unknown")) {
14206 confp->pri.localdialplan = PRI_UNKNOWN + 1;
14207 } else if (!strcasecmp(v->value, "private")) {
14208 confp->pri.localdialplan = PRI_PRIVATE + 1;
14209 } else if (!strcasecmp(v->value, "international")) {
14210 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14211 } else if (!strcasecmp(v->value, "local")) {
14212 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14213 } else if (!strcasecmp(v->value, "dynamic")) {
14214 confp->pri.localdialplan = -1;
14215 } else if (!strcasecmp(v->value, "redundant")) {
14216 confp->pri.localdialplan = -2;
14217 } else {
14218 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14220 } else if (!strcasecmp(v->name, "switchtype")) {
14221 if (!strcasecmp(v->value, "national"))
14222 confp->pri.switchtype = PRI_SWITCH_NI2;
14223 else if (!strcasecmp(v->value, "ni1"))
14224 confp->pri.switchtype = PRI_SWITCH_NI1;
14225 else if (!strcasecmp(v->value, "dms100"))
14226 confp->pri.switchtype = PRI_SWITCH_DMS100;
14227 else if (!strcasecmp(v->value, "4ess"))
14228 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14229 else if (!strcasecmp(v->value, "5ess"))
14230 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14231 else if (!strcasecmp(v->value, "euroisdn"))
14232 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14233 else if (!strcasecmp(v->value, "qsig"))
14234 confp->pri.switchtype = PRI_SWITCH_QSIG;
14235 else {
14236 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14237 return -1;
14239 } else if (!strcasecmp(v->name, "nsf")) {
14240 if (!strcasecmp(v->value, "sdn"))
14241 confp->pri.nsf = PRI_NSF_SDN;
14242 else if (!strcasecmp(v->value, "megacom"))
14243 confp->pri.nsf = PRI_NSF_MEGACOM;
14244 else if (!strcasecmp(v->value, "tollfreemegacom"))
14245 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14246 else if (!strcasecmp(v->value, "accunet"))
14247 confp->pri.nsf = PRI_NSF_ACCUNET;
14248 else if (!strcasecmp(v->value, "none"))
14249 confp->pri.nsf = PRI_NSF_NONE;
14250 else {
14251 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14252 confp->pri.nsf = PRI_NSF_NONE;
14254 } else if (!strcasecmp(v->name, "priindication")) {
14255 if (!strcasecmp(v->value, "outofband"))
14256 confp->chan.priindication_oob = 1;
14257 else if (!strcasecmp(v->value, "inband"))
14258 confp->chan.priindication_oob = 0;
14259 else
14260 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14261 v->value, v->lineno);
14262 } else if (!strcasecmp(v->name, "priexclusive")) {
14263 confp->chan.priexclusive = ast_true(v->value);
14264 } else if (!strcasecmp(v->name, "internationalprefix")) {
14265 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14266 } else if (!strcasecmp(v->name, "nationalprefix")) {
14267 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14268 } else if (!strcasecmp(v->name, "localprefix")) {
14269 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14270 } else if (!strcasecmp(v->name, "privateprefix")) {
14271 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14272 } else if (!strcasecmp(v->name, "unknownprefix")) {
14273 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14274 } else if (!strcasecmp(v->name, "resetinterval")) {
14275 if (!strcasecmp(v->value, "never"))
14276 confp->pri.resetinterval = -1;
14277 else if (atoi(v->value) >= 60)
14278 confp->pri.resetinterval = atoi(v->value);
14279 else
14280 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14281 v->value, v->lineno);
14282 } else if (!strcasecmp(v->name, "minunused")) {
14283 confp->pri.minunused = atoi(v->value);
14284 } else if (!strcasecmp(v->name, "minidle")) {
14285 confp->pri.minidle = atoi(v->value);
14286 } else if (!strcasecmp(v->name, "idleext")) {
14287 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14288 } else if (!strcasecmp(v->name, "idledial")) {
14289 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14290 } else if (!strcasecmp(v->name, "overlapdial")) {
14291 if (ast_true(v->value)) {
14292 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14293 } else if (!strcasecmp(v->value, "incoming")) {
14294 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14295 } else if (!strcasecmp(v->value, "outgoing")) {
14296 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14297 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14298 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14299 } else {
14300 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14302 #ifdef HAVE_PRI_INBANDRELEASE
14303 } else if (!strcasecmp(v->name, "inbandrelease")) {
14304 confp->pri.inbandrelease = ast_true(v->value);
14305 #endif
14306 } else if (!strcasecmp(v->name, "pritimer")) {
14307 #ifdef PRI_GETSET_TIMERS
14308 char tmp[20], *timerc, *c = tmp;
14309 int timer, timeridx;
14310 ast_copy_string(tmp, v->value, sizeof(tmp));
14311 timerc = strsep(&c, ",");
14312 if (timerc) {
14313 timer = atoi(c);
14314 if (!timer)
14315 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno);
14316 else {
14317 if ((timeridx = pri_timer2idx(timerc)) >= 0)
14318 pritimers[timeridx] = timer;
14319 else
14320 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno);
14322 } else
14323 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno);
14325 } else if (!strcasecmp(v->name, "facilityenable")) {
14326 confp->pri.facilityenable = ast_true(v->value);
14327 #endif /* PRI_GETSET_TIMERS */
14328 #endif /* HAVE_PRI */
14329 #ifdef HAVE_SS7
14330 } else if (!strcasecmp(v->name, "ss7type")) {
14331 if (!strcasecmp(v->value, "itu")) {
14332 cur_ss7type = SS7_ITU;
14333 } else if (!strcasecmp(v->value, "ansi")) {
14334 cur_ss7type = SS7_ANSI;
14335 } else
14336 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14337 } else if (!strcasecmp(v->name, "linkset")) {
14338 cur_linkset = atoi(v->value);
14339 } else if (!strcasecmp(v->name, "pointcode")) {
14340 cur_pointcode = parse_pointcode(v->value);
14341 } else if (!strcasecmp(v->name, "adjpointcode")) {
14342 cur_adjpointcode = parse_pointcode(v->value);
14343 } else if (!strcasecmp(v->name, "defaultdpc")) {
14344 cur_defaultdpc = parse_pointcode(v->value);
14345 } else if (!strcasecmp(v->name, "cicbeginswith")) {
14346 cur_cicbeginswith = atoi(v->value);
14347 } else if (!strcasecmp(v->name, "networkindicator")) {
14348 if (!strcasecmp(v->value, "national"))
14349 cur_networkindicator = SS7_NI_NAT;
14350 else if (!strcasecmp(v->value, "national_spare"))
14351 cur_networkindicator = SS7_NI_NAT_SPARE;
14352 else if (!strcasecmp(v->value, "international"))
14353 cur_networkindicator = SS7_NI_INT;
14354 else if (!strcasecmp(v->value, "international_spare"))
14355 cur_networkindicator = SS7_NI_INT_SPARE;
14356 else
14357 cur_networkindicator = -1;
14358 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14359 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14360 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14361 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14362 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14363 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14364 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14365 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14366 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14367 if (!strcasecmp(v->value, "national")) {
14368 confp->ss7.called_nai = SS7_NAI_NATIONAL;
14369 } else if (!strcasecmp(v->value, "international")) {
14370 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14371 } else if (!strcasecmp(v->value, "subscriber")) {
14372 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14373 } else if (!strcasecmp(v->value, "dynamic")) {
14374 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14375 } else {
14376 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14378 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14379 if (!strcasecmp(v->value, "national")) {
14380 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14381 } else if (!strcasecmp(v->value, "international")) {
14382 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14383 } else if (!strcasecmp(v->value, "subscriber")) {
14384 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14385 } else if (!strcasecmp(v->value, "dynamic")) {
14386 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14387 } else {
14388 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14390 } else if (!strcasecmp(v->name, "sigchan")) {
14391 int sigchan, res;
14392 sigchan = atoi(v->value);
14393 res = linkset_addsigchan(sigchan);
14394 if (res < 0)
14395 return -1;
14397 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14398 struct dahdi_ss7 *link;
14399 link = ss7_resolve_linkset(cur_linkset);
14400 if (!link) {
14401 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
14402 return -1;
14404 if (ast_true(v->value))
14405 link->flags |= LINKSET_FLAG_EXPLICITACM;
14407 #endif /* HAVE_SS7 */
14408 } else if (!strcasecmp(v->name, "cadence")) {
14409 /* setup to scan our argument */
14410 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14411 int i;
14412 struct dahdi_ring_cadence new_cadence;
14413 int cid_location = -1;
14414 int firstcadencepos = 0;
14415 char original_args[80];
14416 int cadence_is_ok = 1;
14418 ast_copy_string(original_args, v->value, sizeof(original_args));
14419 /* 16 cadences allowed (8 pairs) */
14420 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
14422 /* Cadence must be even (on/off) */
14423 if (element_count % 2 == 1) {
14424 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14425 cadence_is_ok = 0;
14428 /* Ring cadences cannot be negative */
14429 for (i = 0; i < element_count; i++) {
14430 if (c[i] == 0) {
14431 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14432 cadence_is_ok = 0;
14433 break;
14434 } else if (c[i] < 0) {
14435 if (i % 2 == 1) {
14436 /* Silence duration, negative possibly okay */
14437 if (cid_location == -1) {
14438 cid_location = i;
14439 c[i] *= -1;
14440 } else {
14441 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14442 cadence_is_ok = 0;
14443 break;
14445 } else {
14446 if (firstcadencepos == 0) {
14447 firstcadencepos = i; /* only recorded to avoid duplicate specification */
14448 /* duration will be passed negative to the DAHDI driver */
14449 } else {
14450 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14451 cadence_is_ok = 0;
14452 break;
14458 /* Substitute our scanned cadence */
14459 for (i = 0; i < 16; i++) {
14460 new_cadence.ringcadence[i] = c[i];
14463 if (cadence_is_ok) {
14464 /* ---we scanned it without getting annoyed; now some sanity checks--- */
14465 if (element_count < 2) {
14466 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14467 } else {
14468 if (cid_location == -1) {
14469 /* user didn't say; default to first pause */
14470 cid_location = 1;
14471 } else {
14472 /* convert element_index to cidrings value */
14473 cid_location = (cid_location + 1) / 2;
14475 /* ---we like their cadence; try to install it--- */
14476 if (!user_has_defined_cadences++)
14477 /* this is the first user-defined cadence; clear the default user cadences */
14478 num_cadence = 0;
14479 if ((num_cadence+1) >= NUM_CADENCE_MAX)
14480 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
14481 else {
14482 cadences[num_cadence] = new_cadence;
14483 cidrings[num_cadence++] = cid_location;
14484 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
14488 } else if (!strcasecmp(v->name, "ringtimeout")) {
14489 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
14490 } else if (!strcasecmp(v->name, "prewink")) {
14491 confp->timing.prewinktime = atoi(v->value);
14492 } else if (!strcasecmp(v->name, "preflash")) {
14493 confp->timing.preflashtime = atoi(v->value);
14494 } else if (!strcasecmp(v->name, "wink")) {
14495 confp->timing.winktime = atoi(v->value);
14496 } else if (!strcasecmp(v->name, "flash")) {
14497 confp->timing.flashtime = atoi(v->value);
14498 } else if (!strcasecmp(v->name, "start")) {
14499 confp->timing.starttime = atoi(v->value);
14500 } else if (!strcasecmp(v->name, "rxwink")) {
14501 confp->timing.rxwinktime = atoi(v->value);
14502 } else if (!strcasecmp(v->name, "rxflash")) {
14503 confp->timing.rxflashtime = atoi(v->value);
14504 } else if (!strcasecmp(v->name, "debounce")) {
14505 confp->timing.debouncetime = atoi(v->value);
14506 } else if (!strcasecmp(v->name, "toneduration")) {
14507 int toneduration;
14508 int ctlfd;
14509 int res;
14510 struct dahdi_dialparams dps;
14512 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
14513 if (ctlfd == -1) {
14514 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
14515 return -1;
14518 toneduration = atoi(v->value);
14519 if (toneduration > -1) {
14520 memset(&dps, 0, sizeof(dps));
14522 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
14523 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
14524 if (res < 0) {
14525 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
14526 return -1;
14529 close(ctlfd);
14530 } else if (!strcasecmp(v->name, "defaultcic")) {
14531 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
14532 } else if (!strcasecmp(v->name, "defaultozz")) {
14533 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
14534 } else if (!strcasecmp(v->name, "mwilevel")) {
14535 mwilevel = atoi(v->value);
14537 } else if (!(options && PROC_DAHDI_OPT_NOWARN) )
14538 ast_log(LOG_WARNING, "Ignoring %s at line %d.\n", v->name, v->lineno);
14540 if (dahdichan[0]) {
14541 /* The user has set 'dahdichan' */
14542 /*< \todo pass proper line number instead of 0 */
14543 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
14544 return -1;
14547 /*< \todo why check for the pseudo in the per-channel section.
14548 * Any actual use for manual setup of the pseudo channel? */
14549 if (!found_pseudo && reload == 0) {
14550 /* Make sure pseudo isn't a member of any groups if
14551 we're automatically making it. */
14553 confp->chan.group = 0;
14554 confp->chan.callgroup = 0;
14555 confp->chan.pickupgroup = 0;
14557 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
14559 if (tmp) {
14560 ast_verb(3, "Automatically generated pseudo channel\n");
14561 } else {
14562 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
14565 return 0;
14568 static int setup_dahdi(int reload)
14570 struct ast_config *cfg, *ucfg;
14571 struct ast_variable *v;
14572 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
14573 struct dahdi_chan_conf conf;
14574 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
14575 const char *cat;
14576 int res;
14578 #ifdef HAVE_PRI
14579 char *c;
14580 int spanno;
14581 int i;
14582 int logicalspan;
14583 int trunkgroup;
14584 int dchannels[NUM_DCHANS];
14585 #endif
14587 cfg = ast_config_load(config, config_flags);
14589 /* Error if we have no config file */
14590 if (!cfg) {
14591 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
14592 return 0;
14593 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
14594 ucfg = ast_config_load("users.conf", config_flags);
14595 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
14596 return 0;
14597 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14598 cfg = ast_config_load(config, config_flags);
14599 } else {
14600 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14601 ucfg = ast_config_load("users.conf", config_flags);
14604 /* It's a little silly to lock it, but we mind as well just to be sure */
14605 ast_mutex_lock(&iflock);
14606 #ifdef HAVE_PRI
14607 if (!reload) {
14608 /* Process trunkgroups first */
14609 v = ast_variable_browse(cfg, "trunkgroups");
14610 while (v) {
14611 if (!strcasecmp(v->name, "trunkgroup")) {
14612 trunkgroup = atoi(v->value);
14613 if (trunkgroup > 0) {
14614 if ((c = strchr(v->value, ','))) {
14615 i = 0;
14616 memset(dchannels, 0, sizeof(dchannels));
14617 while (c && (i < NUM_DCHANS)) {
14618 dchannels[i] = atoi(c + 1);
14619 if (dchannels[i] < 0) {
14620 ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14621 } else
14622 i++;
14623 c = strchr(c + 1, ',');
14625 if (i) {
14626 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
14627 ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
14628 } else
14629 ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
14630 } else
14631 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14632 } else
14633 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14634 } else
14635 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
14636 } else if (!strcasecmp(v->name, "spanmap")) {
14637 spanno = atoi(v->value);
14638 if (spanno > 0) {
14639 if ((c = strchr(v->value, ','))) {
14640 trunkgroup = atoi(c + 1);
14641 if (trunkgroup > 0) {
14642 if ((c = strchr(c + 1, ',')))
14643 logicalspan = atoi(c + 1);
14644 else
14645 logicalspan = 0;
14646 if (logicalspan >= 0) {
14647 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
14648 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14649 } else
14650 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14651 } else
14652 ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
14653 } else
14654 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
14655 } else
14656 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
14657 } else
14658 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
14659 } else {
14660 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
14662 v = v->next;
14665 #endif
14667 /* Copy the default jb config over global_jbconf */
14668 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
14670 mwimonitornotify[0] = '\0';
14672 v = ast_variable_browse(cfg, "channels");
14673 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
14674 ast_mutex_unlock(&iflock);
14675 ast_config_destroy(cfg);
14676 if (ucfg) {
14677 ast_config_destroy(ucfg);
14679 return res;
14682 /* Now get configuration from all normal sections in chan_dahdi.conf: */
14683 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
14684 /* [channels] and [trunkgroups] are used. Let's also reserve
14685 * [globals] and [general] for future use
14687 if (!strcasecmp(cat, "general") ||
14688 !strcasecmp(cat, "trunkgroups") ||
14689 !strcasecmp(cat, "globals") ||
14690 !strcasecmp(cat, "channels")) {
14691 continue;
14694 memcpy(&conf, &base_conf, sizeof(conf));
14696 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
14697 ast_mutex_unlock(&iflock);
14698 ast_config_destroy(cfg);
14699 if (ucfg) {
14700 ast_config_destroy(cfg);
14702 return res;
14706 ast_config_destroy(cfg);
14708 if (ucfg) {
14709 const char *chans;
14711 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
14713 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
14714 if (!strcasecmp(cat, "general")) {
14715 continue;
14718 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
14720 if (ast_strlen_zero(chans)) {
14721 continue;
14724 memcpy(&conf, &base_conf, sizeof(conf));
14726 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
14727 ast_config_destroy(ucfg);
14728 ast_mutex_unlock(&iflock);
14729 return res;
14732 ast_config_destroy(ucfg);
14734 ast_mutex_unlock(&iflock);
14736 #ifdef HAVE_PRI
14737 if (!reload) {
14738 int x;
14739 for (x = 0; x < NUM_SPANS; x++) {
14740 if (pris[x].pvts[0]) {
14741 if (start_pri(pris + x)) {
14742 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
14743 return -1;
14744 } else
14745 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
14749 #endif
14750 #ifdef HAVE_SS7
14751 if (!reload) {
14752 int x;
14753 for (x = 0; x < NUM_SPANS; x++) {
14754 if (linksets[x].ss7) {
14755 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
14756 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
14757 return -1;
14758 } else
14759 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
14763 #endif
14764 /* And start the monitor for the first time */
14765 restart_monitor();
14766 return 0;
14769 static int load_module(void)
14771 int res;
14772 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14773 int y, i;
14774 #endif
14776 #ifdef HAVE_PRI
14777 memset(pris, 0, sizeof(pris));
14778 for (y = 0; y < NUM_SPANS; y++) {
14779 ast_mutex_init(&pris[y].lock);
14780 pris[y].offset = -1;
14781 pris[y].master = AST_PTHREADT_NULL;
14782 for (i = 0; i < NUM_DCHANS; i++)
14783 pris[y].fds[i] = -1;
14785 pri_set_error(dahdi_pri_error);
14786 pri_set_message(dahdi_pri_message);
14787 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
14788 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
14789 #endif
14790 #ifdef HAVE_SS7
14791 memset(linksets, 0, sizeof(linksets));
14792 for (y = 0; y < NUM_SPANS; y++) {
14793 ast_mutex_init(&linksets[y].lock);
14794 linksets[y].master = AST_PTHREADT_NULL;
14795 for (i = 0; i < NUM_DCHANS; i++)
14796 linksets[y].fds[i] = -1;
14798 ss7_set_error(dahdi_ss7_error);
14799 ss7_set_message(dahdi_ss7_message);
14800 #endif /* HAVE_SS7 */
14801 res = setup_dahdi(0);
14802 /* Make sure we can register our DAHDI channel type */
14803 if (res)
14804 return AST_MODULE_LOAD_DECLINE;
14805 if (ast_channel_register(&dahdi_tech)) {
14806 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
14807 __unload_module();
14808 return AST_MODULE_LOAD_FAILURE;
14810 #ifdef HAVE_PRI
14811 ast_string_field_init(&inuse, 16);
14812 ast_string_field_set(&inuse, name, "GR-303InUse");
14813 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
14814 #endif
14815 #ifdef HAVE_SS7
14816 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
14817 #endif
14819 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14821 memset(round_robin, 0, sizeof(round_robin));
14822 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
14823 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
14824 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
14825 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
14826 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
14827 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
14828 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
14830 return res;
14833 static int dahdi_sendtext(struct ast_channel *c, const char *text)
14835 #define END_SILENCE_LEN 400
14836 #define HEADER_MS 50
14837 #define TRAILER_MS 5
14838 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14839 #define ASCII_BYTES_PER_CHAR 80
14841 unsigned char *buf,*mybuf;
14842 struct dahdi_pvt *p = c->tech_pvt;
14843 struct pollfd fds[1];
14844 int size,res,fd,len,x;
14845 int bytes=0;
14846 /* Initial carrier (imaginary) */
14847 float cr = 1.0;
14848 float ci = 0.0;
14849 float scont = 0.0;
14850 int index;
14852 index = dahdi_get_index(c, p, 0);
14853 if (index < 0) {
14854 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
14855 return -1;
14857 if (!text[0]) return(0); /* if nothing to send, dont */
14858 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
14859 if (p->mate)
14860 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
14861 else
14862 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
14863 if (!buf)
14864 return -1;
14865 mybuf = buf;
14866 if (p->mate) {
14867 int codec = AST_LAW(p);
14868 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
14869 PUT_CLID_MARKMS;
14871 /* Put actual message */
14872 for (x = 0; text[x]; x++) {
14873 PUT_CLID(text[x]);
14875 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
14876 PUT_CLID_MARKMS;
14878 len = bytes;
14879 buf = mybuf;
14880 } else {
14881 len = tdd_generate(p->tdd, buf, text);
14882 if (len < 1) {
14883 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
14884 ast_free(mybuf);
14885 return -1;
14888 memset(buf + len, 0x7f, END_SILENCE_LEN);
14889 len += END_SILENCE_LEN;
14890 fd = p->subs[index].zfd;
14891 while (len) {
14892 if (ast_check_hangup(c)) {
14893 ast_free(mybuf);
14894 return -1;
14896 size = len;
14897 if (size > READ_SIZE)
14898 size = READ_SIZE;
14899 fds[0].fd = fd;
14900 fds[0].events = POLLOUT | POLLPRI;
14901 fds[0].revents = 0;
14902 res = poll(fds, 1, -1);
14903 if (!res) {
14904 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
14905 continue;
14907 /* if got exception */
14908 if (fds[0].revents & POLLPRI) {
14909 ast_free(mybuf);
14910 return -1;
14912 if (!(fds[0].revents & POLLOUT)) {
14913 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
14914 continue;
14916 res = write(fd, buf, size);
14917 if (res != size) {
14918 if (res == -1) {
14919 ast_free(mybuf);
14920 return -1;
14922 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14923 break;
14925 len -= size;
14926 buf += size;
14928 ast_free(mybuf);
14929 return(0);
14933 static int reload(void)
14935 int res = 0;
14937 res = setup_dahdi(1);
14938 if (res) {
14939 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14940 return -1;
14942 return 0;
14945 /* This is a workaround so that menuselect displays a proper description
14946 * AST_MODULE_INFO(, , "DAHDI Telephony"
14949 #ifdef DAHDI_PRI
14950 #define tdesc "DAHDI Telephony w/PRI"
14951 #else
14952 #define tdesc "DAHDI Telephony"
14953 #endif
14955 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14956 .load = load_module,
14957 .unload = unload_module,
14958 .reload = reload,