Merged revisions 138148 via svnmerge from
[asterisk-bristuff.git] / channels / chan_dahdi.c
blob7ca68ff2467a0af60d41e90653f33210dfef1afb
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 static const char *lbostr[] = {
107 "0 db (CSU)/0-133 feet (DSX-1)",
108 "133-266 feet (DSX-1)",
109 "266-399 feet (DSX-1)",
110 "399-533 feet (DSX-1)",
111 "533-655 feet (DSX-1)",
112 "-7.5db (CSU)",
113 "-15db (CSU)",
114 "-22.5db (CSU)"
117 /*! Global jitterbuffer configuration - by default, jb is disabled */
118 static struct ast_jb_conf default_jbconf =
120 .flags = 0,
121 .max_size = -1,
122 .resync_threshold = -1,
123 .impl = ""
125 static struct ast_jb_conf global_jbconf;
127 /* define this to send PRI user-user information elements */
128 #undef SUPPORT_USERUSER
130 /*!
131 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
132 * the user hangs up to reset the state machine so ring works properly.
133 * This is used to be able to support kewlstart by putting the zhone in
134 * groundstart mode since their forward disconnect supervision is entirely
135 * broken even though their documentation says it isn't and their support
136 * is entirely unwilling to provide any assistance with their channel banks
137 * even though their web site says they support their products for life.
139 /* #define ZHONE_HACK */
141 /*! \note
142 * Define if you want to check the hook state for an FXO (FXS signalled) interface
143 * before dialing on it. Certain FXO interfaces always think they're out of
144 * service with this method however.
146 /* #define DAHDI_CHECK_HOOKSTATE */
148 /*! \brief Typically, how many rings before we should send Caller*ID */
149 #define DEFAULT_CIDRINGS 1
151 #define CHANNEL_PSEUDO -12
153 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
156 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
157 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
159 static const char tdesc[] = "DAHDI Telephony Driver"
160 #ifdef HAVE_PRI
161 " w/PRI"
162 #endif
163 #ifdef HAVE_SS7
164 " w/SS7"
165 #endif
168 static const char config[] = "chan_dahdi.conf";
170 #define SIG_EM DAHDI_SIG_EM
171 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
172 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
173 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
174 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
175 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
176 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
177 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
178 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
179 #define SIG_FXSLS DAHDI_SIG_FXSLS
180 #define SIG_FXSGS DAHDI_SIG_FXSGS
181 #define SIG_FXSKS DAHDI_SIG_FXSKS
182 #define SIG_FXOLS DAHDI_SIG_FXOLS
183 #define SIG_FXOGS DAHDI_SIG_FXOGS
184 #define SIG_FXOKS DAHDI_SIG_FXOKS
185 #define SIG_PRI DAHDI_SIG_CLEAR
186 #define SIG_BRI (0x2000000 | DAHDI_SIG_CLEAR)
187 #define SIG_BRI_PTMP (0X4000000 | DAHDI_SIG_CLEAR)
188 #define SIG_SS7 (0x1000000 | DAHDI_SIG_CLEAR)
189 #define SIG_SF DAHDI_SIG_SF
190 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
191 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
192 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
193 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
194 #define SIG_EM_E1 DAHDI_SIG_EM_E1
195 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
196 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
198 #ifdef LOTS_OF_SPANS
199 #define NUM_SPANS DAHDI_MAX_SPANS
200 #else
201 #define NUM_SPANS 32
202 #endif
203 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
204 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
206 #define CHAN_PSEUDO -2
208 #define DCHAN_PROVISIONED (1 << 0)
209 #define DCHAN_NOTINALARM (1 << 1)
210 #define DCHAN_UP (1 << 2)
212 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
214 /* Overlap dialing option types */
215 #define DAHDI_OVERLAPDIAL_NONE 0
216 #define DAHDI_OVERLAPDIAL_OUTGOING 1
217 #define DAHDI_OVERLAPDIAL_INCOMING 2
218 #define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
221 #define CALLPROGRESS_PROGRESS 1
222 #define CALLPROGRESS_FAX_OUTGOING 2
223 #define CALLPROGRESS_FAX_INCOMING 4
224 #define CALLPROGRESS_FAX (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
226 static char defaultcic[64] = "";
227 static char defaultozz[64] = "";
229 static char parkinglot[AST_MAX_EXTENSION] = ""; /*!< Default parking lot for this channel */
231 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
232 static char mwimonitornotify[PATH_MAX] = "";
233 static int mwisend_rpas = 0;
235 static char progzone[10] = "";
237 static int usedistinctiveringdetection = 0;
238 static int distinctiveringaftercid = 0;
240 static int numbufs = 4;
242 static int mwilevel = 512;
244 #ifdef HAVE_PRI
245 static struct ast_channel inuse;
246 #ifdef PRI_GETSET_TIMERS
247 static int pritimers[PRI_MAX_TIMERS];
248 #endif
249 static int pridebugfd = -1;
250 static char pridebugfilename[1024] = "";
251 #endif
253 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
254 static int firstdigittimeout = 16000;
256 /*! \brief How long to wait for following digits (FXO logic) */
257 static int gendigittimeout = 8000;
259 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
260 static int matchdigittimeout = 3000;
262 /*! \brief Protect the interface list (of dahdi_pvt's) */
263 AST_MUTEX_DEFINE_STATIC(iflock);
266 static int ifcount = 0;
268 #ifdef HAVE_PRI
269 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
270 #endif
272 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
273 when it's doing something critical. */
274 AST_MUTEX_DEFINE_STATIC(monlock);
276 /*! \brief This is the thread for the monitor which checks for input on the channels
277 which are not currently in use. */
278 static pthread_t monitor_thread = AST_PTHREADT_NULL;
280 static int restart_monitor(void);
282 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
284 static int dahdi_sendtext(struct ast_channel *c, const char *text);
286 static void mwi_event_cb(const struct ast_event *event, void *userdata)
288 /* This module does not handle MWI in an event-based manner. However, it
289 * subscribes to MWI for each mailbox that is configured so that the core
290 * knows that we care about it. Then, chan_dahdi will get the MWI from the
291 * event cache instead of checking the mailbox directly. */
294 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
295 static inline int dahdi_get_event(int fd)
297 int j;
298 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
299 return -1;
300 return j;
303 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
304 static inline int dahdi_wait_event(int fd)
306 int i, j = 0;
307 i = DAHDI_IOMUX_SIGEVENT;
308 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
309 return -1;
310 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
311 return -1;
312 return j;
315 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
316 #define READ_SIZE 160
318 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
319 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
321 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
322 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
323 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
324 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
325 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
327 struct dahdi_pvt;
329 static int ringt_base = DEFAULT_RINGT;
331 #ifdef HAVE_SS7
333 #define LINKSTATE_INALARM (1 << 0)
334 #define LINKSTATE_STARTING (1 << 1)
335 #define LINKSTATE_UP (1 << 2)
336 #define LINKSTATE_DOWN (1 << 3)
338 #define SS7_NAI_DYNAMIC -1
340 #define LINKSET_FLAG_EXPLICITACM (1 << 0)
342 struct dahdi_ss7 {
343 pthread_t master; /*!< Thread of master */
344 ast_mutex_t lock;
345 int fds[NUM_DCHANS];
346 int numsigchans;
347 int linkstate[NUM_DCHANS];
348 int numchans;
349 int type;
350 enum {
351 LINKSET_STATE_DOWN = 0,
352 LINKSET_STATE_UP
353 } state;
354 char called_nai; /*!< Called Nature of Address Indicator */
355 char calling_nai; /*!< Calling Nature of Address Indicator */
356 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
357 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
358 char subscriberprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
359 char unknownprefix[20]; /*!< for unknown dialplans */
360 struct ss7 *ss7;
361 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
362 int flags; /*!< Linkset flags */
365 static struct dahdi_ss7 linksets[NUM_SPANS];
367 static int cur_ss7type = -1;
368 static int cur_linkset = -1;
369 static int cur_pointcode = -1;
370 static int cur_cicbeginswith = -1;
371 static int cur_adjpointcode = -1;
372 static int cur_networkindicator = -1;
373 static int cur_defaultdpc = -1;
374 #endif /* HAVE_SS7 */
376 #ifdef HAVE_PRI
378 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
379 #define PRI_CHANNEL(p) ((p) & 0xff)
380 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
381 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
383 struct dahdi_pri {
384 pthread_t master; /*!< Thread of master */
385 ast_mutex_t lock; /*!< Mutex */
386 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
387 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
388 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
389 int minunused; /*!< Min # of channels to keep empty */
390 int minidle; /*!< Min # of "idling" calls to keep active */
391 int nodetype; /*!< Node type */
392 int switchtype; /*!< Type of switch to emulate */
393 int nsf; /*!< Network-Specific Facilities */
394 int dialplan; /*!< Dialing plan */
395 int localdialplan; /*!< Local dialing plan */
396 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
397 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
398 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
399 char privateprefix[20]; /*!< for private dialplans */
400 char unknownprefix[20]; /*!< for unknown dialplans */
401 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
402 int trunkgroup; /*!< What our trunkgroup is */
403 int mastertrunkgroup; /*!< What trunk group is our master */
404 int prilogicalspan; /*!< Logical span number within trunk group */
405 int numchans; /*!< Num of channels we represent */
406 int overlapdial; /*!< In overlap dialing mode */
407 int facilityenable; /*!< Enable facility IEs */
408 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
409 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
410 struct pri *pri; /*!< Currently active D-channel */
411 int debug;
412 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
413 int offset;
414 int span;
415 int resetting;
416 int resetpos;
417 #ifdef HAVE_PRI_INBANDDISCONNECT
418 unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */
419 #endif
420 time_t lastreset; /*!< time when unused channels were last reset */
421 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
422 int sig;
423 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
424 struct dahdi_pvt *crvs; /*!< Member CRV structs */
425 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
429 static struct dahdi_pri pris[NUM_SPANS];
431 #if 0
432 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
433 #else
434 #define DEFAULT_PRI_DEBUG 0
435 #endif
437 static inline void pri_rel(struct dahdi_pri *pri)
439 ast_mutex_unlock(&pri->lock);
442 #else
443 /*! Shut up the compiler */
444 struct dahdi_pri;
445 #endif
447 #define SUB_REAL 0 /*!< Active call */
448 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
449 #define SUB_THREEWAY 2 /*!< Three-way call */
451 /* Polarity states */
452 #define POLARITY_IDLE 0
453 #define POLARITY_REV 1
456 struct distRingData {
457 int ring[3];
458 int range;
460 struct ringContextData {
461 char contextData[AST_MAX_CONTEXT];
463 struct dahdi_distRings {
464 struct distRingData ringnum[3];
465 struct ringContextData ringContext[3];
468 static char *subnames[] = {
469 "Real",
470 "Callwait",
471 "Threeway"
474 struct dahdi_subchannel {
475 int zfd;
476 struct ast_channel *owner;
477 int chan;
478 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
479 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
480 unsigned int needringing:1;
481 unsigned int needbusy:1;
482 unsigned int needcongestion:1;
483 unsigned int needcallerid:1;
484 unsigned int needanswer:1;
485 unsigned int needflash:1;
486 unsigned int needhold:1;
487 unsigned int needunhold:1;
488 unsigned int linear:1;
489 unsigned int inthreeway:1;
490 struct dahdi_confinfo curconf;
493 #define CONF_USER_REAL (1 << 0)
494 #define CONF_USER_THIRDCALL (1 << 1)
496 #define MAX_SLAVES 4
498 static struct dahdi_pvt {
499 ast_mutex_t lock;
500 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
501 /*!< Up to three channels can be associated with this call */
503 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
504 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
505 struct dahdi_confinfo saveconf; /*!< Saved conference info */
507 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
508 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
509 int inconference; /*!< If our real should be in the conference */
511 int buf_no; /*!< Number of buffers */
512 int buf_policy; /*!< Buffer policy */
513 int sig; /*!< Signalling style */
514 int radio; /*!< radio type */
515 int outsigmod; /*!< Outbound Signalling style (modifier) */
516 int oprmode; /*!< "Operator Services" mode */
517 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
518 float cid_rxgain; /*!< "Gain to apply during caller id */
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 struct dahdi_dialoperation 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 struct dahdi_params timing;
733 int is_sig_auto; /*!< Use channel signalling from DAHDI? */
735 char smdi_port[SMDI_MAX_FILENAME_LEN];
738 /*! returns a new dahdi_chan_conf with default values (by-value) */
739 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
740 /* recall that if a field is not included here it is initialized
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 .buf_policy = DAHDI_POLICY_IMMEDIATE,
807 .buf_no = numbufs
809 .timing = {
810 .prewinktime = -1,
811 .preflashtime = -1,
812 .winktime = -1,
813 .flashtime = -1,
814 .starttime = -1,
815 .rxwinktime = -1,
816 .rxflashtime = -1,
817 .debouncetime = -1
819 .is_sig_auto = 1,
820 .smdi_port = "/dev/ttyS0",
823 return conf;
827 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
828 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
829 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
830 static int dahdi_sendtext(struct ast_channel *c, const char *text);
831 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
832 static int dahdi_hangup(struct ast_channel *ast);
833 static int dahdi_answer(struct ast_channel *ast);
834 static struct ast_frame *dahdi_read(struct ast_channel *ast);
835 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
836 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
837 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
838 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
839 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
840 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
841 static int handle_init_event(struct dahdi_pvt *i, int event);
843 static const struct ast_channel_tech dahdi_tech = {
844 .type = "DAHDI",
845 .description = tdesc,
846 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
847 .requester = dahdi_request,
848 .send_digit_begin = dahdi_digit_begin,
849 .send_digit_end = dahdi_digit_end,
850 .send_text = dahdi_sendtext,
851 .call = dahdi_call,
852 .hangup = dahdi_hangup,
853 .answer = dahdi_answer,
854 .read = dahdi_read,
855 .write = dahdi_write,
856 .bridge = dahdi_bridge,
857 .exception = dahdi_exception,
858 .indicate = dahdi_indicate,
859 .fixup = dahdi_fixup,
860 .setoption = dahdi_setoption,
861 .func_channel_read = dahdi_func_read,
864 #ifdef HAVE_PRI
865 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
866 #else
867 #define GET_CHANNEL(p) ((p)->channel)
868 #endif
870 struct dahdi_pvt *round_robin[32];
872 #ifdef HAVE_PRI
873 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
875 int res;
876 /* Grab the lock first */
877 do {
878 res = ast_mutex_trylock(&pri->lock);
879 if (res) {
880 DEADLOCK_AVOIDANCE(&pvt->lock);
882 } while (res);
883 /* Then break the poll */
884 pthread_kill(pri->master, SIGURG);
885 return 0;
887 #endif
889 #ifdef HAVE_SS7
890 static inline void ss7_rel(struct dahdi_ss7 *ss7)
892 ast_mutex_unlock(&ss7->lock);
895 static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
897 int res;
898 /* Grab the lock first */
899 do {
900 res = ast_mutex_trylock(&pri->lock);
901 if (res) {
902 DEADLOCK_AVOIDANCE(&pvt->lock);
904 } while (res);
905 /* Then break the poll */
906 pthread_kill(pri->master, SIGURG);
907 return 0;
909 #endif
910 #define NUM_CADENCE_MAX 25
911 static int num_cadence = 4;
912 static int user_has_defined_cadences = 0;
914 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
915 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
916 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
917 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
918 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
921 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
922 * is 1, the second pause is 2 and so on.
925 static int cidrings[NUM_CADENCE_MAX] = {
926 2, /*!< Right after first long ring */
927 4, /*!< Right after long part */
928 3, /*!< After third chirp */
929 2, /*!< Second spell */
932 /* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
933 static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
935 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
936 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
938 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
939 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
941 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
943 int res;
944 if (p->subs[0].owner == ast)
945 res = 0;
946 else if (p->subs[1].owner == ast)
947 res = 1;
948 else if (p->subs[2].owner == ast)
949 res = 2;
950 else {
951 res = -1;
952 if (!nullok)
953 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
955 return res;
958 #ifdef HAVE_PRI
959 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
960 #else
961 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
962 #endif
964 #ifdef HAVE_PRI
965 if (pri)
966 ast_mutex_unlock(&pri->lock);
967 #endif
968 for (;;) {
969 if (p->subs[a].owner) {
970 if (ast_channel_trylock(p->subs[a].owner)) {
971 DEADLOCK_AVOIDANCE(&p->lock);
972 } else {
973 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
974 ast_channel_unlock(p->subs[a].owner);
975 break;
977 } else
978 break;
980 #ifdef HAVE_PRI
981 if (pri)
982 ast_mutex_lock(&pri->lock);
983 #endif
986 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
988 #ifdef HAVE_PRI
989 struct dahdi_pri *pri = (struct dahdi_pri*) data;
990 #endif
991 #ifdef HAVE_SS7
992 struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
993 #endif
994 /* We must unlock the PRI to avoid the possibility of a deadlock */
995 #if defined(HAVE_PRI) || defined(HAVE_SS7)
996 if (data) {
997 switch (p->sig) {
998 #ifdef HAVE_PRI
999 case SIG_BRI:
1000 case SIG_BRI_PTMP:
1001 case SIG_PRI:
1002 ast_mutex_unlock(&pri->lock);
1003 break;
1004 #endif
1005 #ifdef HAVE_SS7
1006 case SIG_SS7:
1007 ast_mutex_unlock(&ss7->lock);
1008 break;
1009 #endif
1010 default:
1011 break;
1014 #endif
1015 for (;;) {
1016 if (p->owner) {
1017 if (ast_channel_trylock(p->owner)) {
1018 DEADLOCK_AVOIDANCE(&p->lock);
1019 } else {
1020 ast_queue_frame(p->owner, f);
1021 ast_channel_unlock(p->owner);
1022 break;
1024 } else
1025 break;
1027 #if defined(HAVE_PRI) || defined(HAVE_SS7)
1028 if (data) {
1029 switch (p->sig) {
1030 #ifdef HAVE_PRI
1031 case SIG_BRI:
1032 case SIG_BRI_PTMP:
1033 case SIG_PRI:
1034 ast_mutex_lock(&pri->lock);
1035 break;
1036 #endif
1037 #ifdef HAVE_SS7
1038 case SIG_SS7:
1039 ast_mutex_lock(&ss7->lock);
1040 break;
1041 #endif
1042 default:
1043 break;
1047 #endif
1050 static int restore_gains(struct dahdi_pvt *p);
1052 static void swap_subs(struct dahdi_pvt *p, int a, int b)
1054 int tchan;
1055 int tinthreeway;
1056 struct ast_channel *towner;
1058 ast_debug(1, "Swapping %d and %d\n", a, b);
1060 tchan = p->subs[a].chan;
1061 towner = p->subs[a].owner;
1062 tinthreeway = p->subs[a].inthreeway;
1064 p->subs[a].chan = p->subs[b].chan;
1065 p->subs[a].owner = p->subs[b].owner;
1066 p->subs[a].inthreeway = p->subs[b].inthreeway;
1068 p->subs[b].chan = tchan;
1069 p->subs[b].owner = towner;
1070 p->subs[b].inthreeway = tinthreeway;
1072 if (p->subs[a].owner)
1073 ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].zfd);
1074 if (p->subs[b].owner)
1075 ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].zfd);
1076 wakeup_sub(p, a, NULL);
1077 wakeup_sub(p, b, NULL);
1080 static int dahdi_open(char *fn)
1082 int fd;
1083 int isnum;
1084 int chan = 0;
1085 int bs;
1086 int x;
1087 isnum = 1;
1088 for (x = 0; x < strlen(fn); x++) {
1089 if (!isdigit(fn[x])) {
1090 isnum = 0;
1091 break;
1094 if (isnum) {
1095 chan = atoi(fn);
1096 if (chan < 1) {
1097 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
1098 return -1;
1100 fn = "/dev/dahdi/channel";
1102 fd = open(fn, O_RDWR | O_NONBLOCK);
1103 if (fd < 0) {
1104 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
1105 return -1;
1107 if (chan) {
1108 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
1109 x = errno;
1110 close(fd);
1111 errno = x;
1112 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
1113 return -1;
1116 bs = READ_SIZE;
1117 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
1118 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
1119 x = errno;
1120 close(fd);
1121 errno = x;
1122 return -1;
1124 return fd;
1127 static void dahdi_close(int fd)
1129 if (fd > 0)
1130 close(fd);
1133 static int dahdi_setlinear(int zfd, int linear)
1135 int res;
1136 res = ioctl(zfd, DAHDI_SETLINEAR, &linear);
1137 if (res)
1138 return res;
1139 return 0;
1143 static int alloc_sub(struct dahdi_pvt *p, int x)
1145 struct dahdi_bufferinfo bi;
1146 int res;
1147 if (p->subs[x].zfd >= 0) {
1148 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
1149 return -1;
1152 p->subs[x].zfd = dahdi_open("/dev/dahdi/pseudo");
1153 if (p->subs[x].zfd <= -1) {
1154 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
1155 return -1;
1158 res = ioctl(p->subs[x].zfd, DAHDI_GET_BUFINFO, &bi);
1159 if (!res) {
1160 bi.txbufpolicy = p->buf_policy;
1161 bi.rxbufpolicy = p->buf_policy;
1162 bi.numbufs = p->buf_no;
1163 res = ioctl(p->subs[x].zfd, DAHDI_SET_BUFINFO, &bi);
1164 if (res < 0) {
1165 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
1167 } else
1168 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
1170 if (ioctl(p->subs[x].zfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
1171 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].zfd, strerror(errno));
1172 dahdi_close(p->subs[x].zfd);
1173 p->subs[x].zfd = -1;
1174 return -1;
1176 ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
1177 return 0;
1180 static int unalloc_sub(struct dahdi_pvt *p, int x)
1182 if (!x) {
1183 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
1184 return -1;
1186 ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
1187 if (p->subs[x].zfd > -1) {
1188 dahdi_close(p->subs[x].zfd);
1190 p->subs[x].zfd = -1;
1191 p->subs[x].linear = 0;
1192 p->subs[x].chan = 0;
1193 p->subs[x].owner = NULL;
1194 p->subs[x].inthreeway = 0;
1195 p->polarity = POLARITY_IDLE;
1196 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
1197 return 0;
1200 static int digit_to_dtmfindex(char digit)
1202 if (isdigit(digit))
1203 return DAHDI_TONE_DTMF_BASE + (digit - '0');
1204 else if (digit >= 'A' && digit <= 'D')
1205 return DAHDI_TONE_DTMF_A + (digit - 'A');
1206 else if (digit >= 'a' && digit <= 'd')
1207 return DAHDI_TONE_DTMF_A + (digit - 'a');
1208 else if (digit == '*')
1209 return DAHDI_TONE_DTMF_s;
1210 else if (digit == '#')
1211 return DAHDI_TONE_DTMF_p;
1212 else
1213 return -1;
1216 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1218 struct dahdi_pvt *pvt;
1219 int idx;
1220 int dtmf = -1;
1222 pvt = chan->tech_pvt;
1224 ast_mutex_lock(&pvt->lock);
1226 idx = dahdi_get_index(chan, pvt, 0);
1228 if ((idx != SUB_REAL) || !pvt->owner)
1229 goto out;
1231 #ifdef HAVE_PRI
1232 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
1233 && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1234 if (pvt->setup_ack) {
1235 if (!pri_grab(pvt, pvt->pri)) {
1236 pri_information(pvt->pri->pri, pvt->call, digit);
1237 pri_rel(pvt->pri);
1238 } else
1239 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1240 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1241 int res;
1242 ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1243 res = strlen(pvt->dialdest);
1244 pvt->dialdest[res++] = digit;
1245 pvt->dialdest[res] = '\0';
1247 goto out;
1249 #endif
1250 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1251 goto out;
1253 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_SENDTONE, &dtmf)) {
1254 int res;
1255 struct dahdi_dialoperation zo = {
1256 .op = DAHDI_DIAL_OP_APPEND,
1259 zo.dialstr[0] = 'T';
1260 zo.dialstr[1] = digit;
1261 zo.dialstr[2] = '\0';
1262 if ((res = ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_DIAL, &zo)))
1263 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1264 else
1265 pvt->dialing = 1;
1266 } else {
1267 ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
1268 pvt->dialing = 1;
1269 pvt->begindigit = digit;
1272 out:
1273 ast_mutex_unlock(&pvt->lock);
1275 return 0;
1278 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1280 struct dahdi_pvt *pvt;
1281 int res = 0;
1282 int idx;
1283 int x;
1285 pvt = chan->tech_pvt;
1287 ast_mutex_lock(&pvt->lock);
1289 idx = dahdi_get_index(chan, pvt, 0);
1291 if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
1292 goto out;
1294 #ifdef HAVE_PRI
1295 /* This means that the digit was already sent via PRI signalling */
1296 if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
1297 && !pvt->begindigit)
1298 goto out;
1299 #endif
1301 if (pvt->begindigit) {
1302 x = -1;
1303 ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
1304 res = ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_SENDTONE, &x);
1305 pvt->dialing = 0;
1306 pvt->begindigit = 0;
1309 out:
1310 ast_mutex_unlock(&pvt->lock);
1312 return res;
1315 static char *events[] = {
1316 "No event",
1317 "On hook",
1318 "Ring/Answered",
1319 "Wink/Flash",
1320 "Alarm",
1321 "No more alarm",
1322 "HDLC Abort",
1323 "HDLC Overrun",
1324 "HDLC Bad FCS",
1325 "Dial Complete",
1326 "Ringer On",
1327 "Ringer Off",
1328 "Hook Transition Complete",
1329 "Bits Changed",
1330 "Pulse Start",
1331 "Timer Expired",
1332 "Timer Ping",
1333 "Polarity Reversal",
1334 "Ring Begin",
1337 static struct {
1338 int alarm;
1339 char *name;
1340 } alarms[] = {
1341 { DAHDI_ALARM_RED, "Red Alarm" },
1342 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1343 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1344 { DAHDI_ALARM_RECOVER, "Recovering" },
1345 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1346 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1347 { DAHDI_ALARM_NONE, "None" },
1350 static char *alarm2str(int alm)
1352 int x;
1353 for (x = 0; x < ARRAY_LEN(alarms); x++) {
1354 if (alarms[x].alarm & alm)
1355 return alarms[x].name;
1357 return alm ? "Unknown Alarm" : "No Alarm";
1360 static char *event2str(int event)
1362 static char buf[256];
1363 if ((event < (ARRAY_LEN(events))) && (event > -1))
1364 return events[event];
1365 sprintf(buf, "Event %d", event); /* safe */
1366 return buf;
1369 #ifdef HAVE_PRI
1370 static char *dialplan2str(int dialplan)
1372 if (dialplan == -1 || dialplan == -2) {
1373 return("Dynamically set dialplan in ISDN");
1375 return (pri_plan2str(dialplan));
1377 #endif
1379 static char *dahdi_sig2str(int sig)
1381 static char buf[256];
1382 switch (sig) {
1383 case SIG_EM:
1384 return "E & M Immediate";
1385 case SIG_EMWINK:
1386 return "E & M Wink";
1387 case SIG_EM_E1:
1388 return "E & M E1";
1389 case SIG_FEATD:
1390 return "Feature Group D (DTMF)";
1391 case SIG_FEATDMF:
1392 return "Feature Group D (MF)";
1393 case SIG_FEATDMF_TA:
1394 return "Feature Groud D (MF) Tandem Access";
1395 case SIG_FEATB:
1396 return "Feature Group B (MF)";
1397 case SIG_E911:
1398 return "E911 (MF)";
1399 case SIG_FGC_CAMA:
1400 return "FGC/CAMA (Dialpulse)";
1401 case SIG_FGC_CAMAMF:
1402 return "FGC/CAMA (MF)";
1403 case SIG_FXSLS:
1404 return "FXS Loopstart";
1405 case SIG_FXSGS:
1406 return "FXS Groundstart";
1407 case SIG_FXSKS:
1408 return "FXS Kewlstart";
1409 case SIG_FXOLS:
1410 return "FXO Loopstart";
1411 case SIG_FXOGS:
1412 return "FXO Groundstart";
1413 case SIG_FXOKS:
1414 return "FXO Kewlstart";
1415 case SIG_PRI:
1416 return "ISDN PRI";
1417 case SIG_BRI:
1418 return "ISDN BRI Point to Point";
1419 case SIG_BRI_PTMP:
1420 return "ISDN BRI Point to MultiPoint";
1421 case SIG_SS7:
1422 return "SS7";
1423 case SIG_SF:
1424 return "SF (Tone) Immediate";
1425 case SIG_SFWINK:
1426 return "SF (Tone) Wink";
1427 case SIG_SF_FEATD:
1428 return "SF (Tone) with Feature Group D (DTMF)";
1429 case SIG_SF_FEATDMF:
1430 return "SF (Tone) with Feature Group D (MF)";
1431 case SIG_SF_FEATB:
1432 return "SF (Tone) with Feature Group B (MF)";
1433 case SIG_GR303FXOKS:
1434 return "GR-303 with FXOKS";
1435 case SIG_GR303FXSKS:
1436 return "GR-303 with FXSKS";
1437 case 0:
1438 return "Pseudo";
1439 default:
1440 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1441 return buf;
1445 #define sig2str dahdi_sig2str
1447 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
1449 /* If the conference already exists, and we're already in it
1450 don't bother doing anything */
1451 struct dahdi_confinfo zi;
1453 memset(&zi, 0, sizeof(zi));
1454 zi.chan = 0;
1456 if (slavechannel > 0) {
1457 /* If we have only one slave, do a digital mon */
1458 zi.confmode = DAHDI_CONF_DIGITALMON;
1459 zi.confno = slavechannel;
1460 } else {
1461 if (!idx) {
1462 /* Real-side and pseudo-side both participate in conference */
1463 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1464 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1465 } else
1466 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1467 zi.confno = p->confno;
1469 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1470 return 0;
1471 if (c->zfd < 0)
1472 return 0;
1473 if (ioctl(c->zfd, DAHDI_SETCONF, &zi)) {
1474 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->zfd, zi.confmode, zi.confno, strerror(errno));
1475 return -1;
1477 if (slavechannel < 1) {
1478 p->confno = zi.confno;
1480 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1481 ast_debug(1, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
1482 return 0;
1485 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1487 /* If they're listening to our channel, they're ours */
1488 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1489 return 1;
1490 /* If they're a talker on our (allocated) conference, they're ours */
1491 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1492 return 1;
1493 return 0;
1496 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
1498 struct dahdi_confinfo zi;
1499 if (/* Can't delete if there's no zfd */
1500 (c->zfd < 0) ||
1501 /* Don't delete from the conference if it's not our conference */
1502 !isourconf(p, c)
1503 /* Don't delete if we don't think it's conferenced at all (implied) */
1504 ) return 0;
1505 memset(&zi, 0, sizeof(zi));
1506 zi.chan = 0;
1507 zi.confno = 0;
1508 zi.confmode = 0;
1509 if (ioctl(c->zfd, DAHDI_SETCONF, &zi)) {
1510 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->zfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1511 return -1;
1513 ast_debug(1, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
1514 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1515 return 0;
1518 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1520 int x;
1521 int useslavenative;
1522 struct dahdi_pvt *slave = NULL;
1523 /* Start out optimistic */
1524 useslavenative = 1;
1525 /* Update conference state in a stateless fashion */
1526 for (x = 0; x < 3; x++) {
1527 /* Any three-way calling makes slave native mode *definitely* out
1528 of the question */
1529 if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway)
1530 useslavenative = 0;
1532 /* If we don't have any 3-way calls, check to see if we have
1533 precisely one slave */
1534 if (useslavenative) {
1535 for (x = 0; x < MAX_SLAVES; x++) {
1536 if (p->slaves[x]) {
1537 if (slave) {
1538 /* Whoops already have a slave! No
1539 slave native and stop right away */
1540 slave = NULL;
1541 useslavenative = 0;
1542 break;
1543 } else {
1544 /* We have one slave so far */
1545 slave = p->slaves[x];
1550 /* If no slave, slave native definitely out */
1551 if (!slave)
1552 useslavenative = 0;
1553 else if (slave->law != p->law) {
1554 useslavenative = 0;
1555 slave = NULL;
1557 if (out)
1558 *out = slave;
1559 return useslavenative;
1562 static int reset_conf(struct dahdi_pvt *p)
1564 struct dahdi_confinfo zi;
1565 memset(&zi, 0, sizeof(zi));
1566 p->confno = -1;
1567 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1568 if (p->subs[SUB_REAL].zfd > -1) {
1569 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCONF, &zi))
1570 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1572 return 0;
1575 static int update_conf(struct dahdi_pvt *p)
1577 int needconf = 0;
1578 int x;
1579 int useslavenative;
1580 struct dahdi_pvt *slave = NULL;
1582 useslavenative = isslavenative(p, &slave);
1583 /* Start with the obvious, general stuff */
1584 for (x = 0; x < 3; x++) {
1585 /* Look for three way calls */
1586 if ((p->subs[x].zfd > -1) && p->subs[x].inthreeway) {
1587 conf_add(p, &p->subs[x], x, 0);
1588 needconf++;
1589 } else {
1590 conf_del(p, &p->subs[x], x);
1593 /* If we have a slave, add him to our conference now. or DAX
1594 if this is slave native */
1595 for (x = 0; x < MAX_SLAVES; x++) {
1596 if (p->slaves[x]) {
1597 if (useslavenative)
1598 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1599 else {
1600 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1601 needconf++;
1605 /* If we're supposed to be in there, do so now */
1606 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1607 if (useslavenative)
1608 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1609 else {
1610 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1611 needconf++;
1614 /* If we have a master, add ourselves to his conference */
1615 if (p->master) {
1616 if (isslavenative(p->master, NULL)) {
1617 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1618 } else {
1619 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1622 if (!needconf) {
1623 /* Nobody is left (or should be left) in our conference.
1624 Kill it. */
1625 p->confno = -1;
1627 ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1628 return 0;
1631 static void dahdi_enable_ec(struct dahdi_pvt *p)
1633 int x;
1634 int res;
1635 if (!p)
1636 return;
1637 if (p->echocanon) {
1638 ast_debug(1, "Echo cancellation already on\n");
1639 return;
1641 if (p->digital) {
1642 ast_debug(1, "Echo cancellation isn't required on digital connection\n");
1643 return;
1645 if (p->echocancel.head.tap_length) {
1646 if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
1647 x = 1;
1648 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &x);
1649 if (res)
1650 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1652 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
1653 if (res) {
1654 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1655 } else {
1656 p->echocanon = 1;
1657 ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
1659 } else
1660 ast_debug(1, "No echo cancellation requested\n");
1663 static void dahdi_train_ec(struct dahdi_pvt *p)
1665 int x;
1666 int res;
1668 if (p && p->echocanon && p->echotraining) {
1669 x = p->echotraining;
1670 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOTRAIN, &x);
1671 if (res)
1672 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1673 else
1674 ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
1675 } else {
1676 ast_debug(1, "No echo training requested\n");
1680 static void dahdi_disable_ec(struct dahdi_pvt *p)
1682 int res;
1684 if (p->echocanon) {
1685 struct dahdi_echocanparams ecp = { .tap_length = 0 };
1687 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
1689 if (res)
1690 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1691 else
1692 ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
1695 p->echocanon = 0;
1698 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
1700 int j;
1701 int k;
1702 float linear_gain = pow(10.0, gain / 20.0);
1704 switch (law) {
1705 case DAHDI_LAW_ALAW:
1706 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
1707 if (gain) {
1708 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1709 if (k > 32767) k = 32767;
1710 if (k < -32767) k = -32767;
1711 g->txgain[j] = AST_LIN2A(k);
1712 } else {
1713 g->txgain[j] = j;
1716 break;
1717 case DAHDI_LAW_MULAW:
1718 for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
1719 if (gain) {
1720 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1721 if (k > 32767) k = 32767;
1722 if (k < -32767) k = -32767;
1723 g->txgain[j] = AST_LIN2MU(k);
1724 } else {
1725 g->txgain[j] = j;
1728 break;
1732 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
1734 int j;
1735 int k;
1736 float linear_gain = pow(10.0, gain / 20.0);
1738 switch (law) {
1739 case DAHDI_LAW_ALAW:
1740 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
1741 if (gain) {
1742 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1743 if (k > 32767) k = 32767;
1744 if (k < -32767) k = -32767;
1745 g->rxgain[j] = AST_LIN2A(k);
1746 } else {
1747 g->rxgain[j] = j;
1750 break;
1751 case DAHDI_LAW_MULAW:
1752 for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
1753 if (gain) {
1754 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1755 if (k > 32767) k = 32767;
1756 if (k < -32767) k = -32767;
1757 g->rxgain[j] = AST_LIN2MU(k);
1758 } else {
1759 g->rxgain[j] = j;
1762 break;
1766 static int set_actual_txgain(int fd, int chan, float gain, int law)
1768 struct dahdi_gains g;
1769 int res;
1771 memset(&g, 0, sizeof(g));
1772 g.chan = chan;
1773 res = ioctl(fd, DAHDI_GETGAINS, &g);
1774 if (res) {
1775 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
1776 return res;
1779 fill_txgain(&g, gain, law);
1781 return ioctl(fd, DAHDI_SETGAINS, &g);
1784 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1786 struct dahdi_gains g;
1787 int res;
1789 memset(&g, 0, sizeof(g));
1790 g.chan = chan;
1791 res = ioctl(fd, DAHDI_GETGAINS, &g);
1792 if (res) {
1793 ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
1794 return res;
1797 fill_rxgain(&g, gain, law);
1799 return ioctl(fd, DAHDI_SETGAINS, &g);
1802 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1804 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1807 static int bump_gains(struct dahdi_pvt *p)
1809 int res;
1811 /* Bump receive gain by value stored in cid_rxgain */
1812 res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
1813 if (res) {
1814 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1815 return -1;
1818 return 0;
1821 static int restore_gains(struct dahdi_pvt *p)
1823 int res;
1825 res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
1826 if (res) {
1827 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1828 return -1;
1831 return 0;
1834 static inline int dahdi_set_hook(int fd, int hs)
1836 int x, res;
1838 x = hs;
1839 res = ioctl(fd, DAHDI_HOOK, &x);
1841 if (res < 0) {
1842 if (errno == EINPROGRESS)
1843 return 0;
1844 ast_log(LOG_WARNING, "DAHDI hook failed: %s\n", strerror(errno));
1847 return res;
1850 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1852 int x, y, res;
1853 x = muted;
1854 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
1855 y = 1;
1856 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &y);
1857 if (res)
1858 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1860 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_CONFMUTE, &x);
1861 if (res < 0)
1862 ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1863 return res;
1866 static int save_conference(struct dahdi_pvt *p)
1868 struct dahdi_confinfo c;
1869 int res;
1870 if (p->saveconf.confmode) {
1871 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1872 return -1;
1874 p->saveconf.chan = 0;
1875 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GETCONF, &p->saveconf);
1876 if (res) {
1877 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1878 p->saveconf.confmode = 0;
1879 return -1;
1881 c.chan = 0;
1882 c.confno = 0;
1883 c.confmode = DAHDI_CONF_NORMAL;
1884 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCONF, &c);
1885 if (res) {
1886 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1887 return -1;
1889 ast_debug(1, "Disabled conferencing\n");
1890 return 0;
1894 * \brief Send MWI state change
1896 * \arg mailbox_full This is the mailbox associated with the FXO line that the
1897 * MWI state has changed on.
1898 * \arg thereornot This argument should simply be set to 1 or 0, to indicate
1899 * whether there are messages waiting or not.
1901 * \return nothing
1903 * This function does two things:
1905 * 1) It generates an internal Asterisk event notifying any other module that
1906 * cares about MWI that the state of a mailbox has changed.
1908 * 2) It runs the script specified by the mwimonitornotify option to allow
1909 * some custom handling of the state change.
1911 static void notify_message(char *mailbox_full, int thereornot)
1913 char s[sizeof(mwimonitornotify) + 80];
1914 struct ast_event *event;
1915 char *mailbox, *context;
1917 /* Strip off @default */
1918 context = mailbox = ast_strdupa(mailbox_full);
1919 strsep(&context, "@");
1920 if (ast_strlen_zero(context))
1921 context = "default";
1923 if (!(event = ast_event_new(AST_EVENT_MWI,
1924 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
1925 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
1926 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
1927 AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
1928 AST_EVENT_IE_END))) {
1929 return;
1932 ast_event_queue_and_cache(event,
1933 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
1934 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
1935 AST_EVENT_IE_END);
1937 if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
1938 snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
1939 ast_safe_system(s);
1943 static int restore_conference(struct dahdi_pvt *p)
1945 int res;
1946 if (p->saveconf.confmode) {
1947 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCONF, &p->saveconf);
1948 p->saveconf.confmode = 0;
1949 if (res) {
1950 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1951 return -1;
1954 ast_debug(1, "Restored conferencing\n");
1955 return 0;
1958 static int send_callerid(struct dahdi_pvt *p);
1960 static int send_cwcidspill(struct dahdi_pvt *p)
1962 p->callwaitcas = 0;
1963 p->cidcwexpire = 0;
1964 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1965 return -1;
1966 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1967 /* Make sure we account for the end */
1968 p->cidlen += READ_SIZE * 4;
1969 p->cidpos = 0;
1970 send_callerid(p);
1971 ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1972 return 0;
1975 static int has_voicemail(struct dahdi_pvt *p)
1977 int new_msgs;
1978 struct ast_event *event;
1979 char *mailbox, *context;
1981 mailbox = context = ast_strdupa(p->mailbox);
1982 strsep(&context, "@");
1983 if (ast_strlen_zero(context))
1984 context = "default";
1986 event = ast_event_get_cached(AST_EVENT_MWI,
1987 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
1988 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
1989 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
1990 AST_EVENT_IE_END);
1992 if (event) {
1993 new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
1994 ast_event_destroy(event);
1995 } else
1996 new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
1998 return new_msgs;
2001 static int send_callerid(struct dahdi_pvt *p)
2003 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
2004 int res;
2005 /* Take out of linear mode if necessary */
2006 if (p->subs[SUB_REAL].linear) {
2007 p->subs[SUB_REAL].linear = 0;
2008 dahdi_setlinear(p->subs[SUB_REAL].zfd, 0);
2010 while (p->cidpos < p->cidlen) {
2011 res = write(p->subs[SUB_REAL].zfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
2012 if (res < 0) {
2013 if (errno == EAGAIN)
2014 return 0;
2015 else {
2016 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
2017 return -1;
2020 if (!res)
2021 return 0;
2022 p->cidpos += res;
2024 ast_free(p->cidspill);
2025 p->cidspill = NULL;
2026 if (p->callwaitcas) {
2027 /* Wait for CID/CW to expire */
2028 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
2029 } else
2030 restore_conference(p);
2031 return 0;
2034 static int dahdi_callwait(struct ast_channel *ast)
2036 struct dahdi_pvt *p = ast->tech_pvt;
2037 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
2038 if (p->cidspill) {
2039 ast_log(LOG_WARNING, "Spill already exists?!?\n");
2040 ast_free(p->cidspill);
2042 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
2043 return -1;
2044 save_conference(p);
2045 /* Silence */
2046 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
2047 if (!p->callwaitrings && p->callwaitingcallerid) {
2048 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
2049 p->callwaitcas = 1;
2050 p->cidlen = 2400 + 680 + READ_SIZE * 4;
2051 } else {
2052 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
2053 p->callwaitcas = 0;
2054 p->cidlen = 2400 + READ_SIZE * 4;
2056 p->cidpos = 0;
2057 send_callerid(p);
2059 return 0;
2062 #ifdef HAVE_SS7
2063 static unsigned char cid_pres2ss7pres(int cid_pres)
2065 return (cid_pres >> 5) & 0x03;
2068 static unsigned char cid_pres2ss7screen(int cid_pres)
2070 return cid_pres & 0x03;
2072 #endif
2074 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
2076 struct dahdi_pvt *p = ast->tech_pvt;
2077 int x, res, idx,mysig;
2078 char *c, *n, *l;
2079 #ifdef HAVE_PRI
2080 char *s = NULL;
2081 #endif
2082 char dest[256]; /* must be same length as p->dialdest */
2083 ast_mutex_lock(&p->lock);
2084 ast_copy_string(dest, rdest, sizeof(dest));
2085 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
2086 if ((ast->_state == AST_STATE_BUSY)) {
2087 p->subs[SUB_REAL].needbusy = 1;
2088 ast_mutex_unlock(&p->lock);
2089 return 0;
2091 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
2092 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
2093 ast_mutex_unlock(&p->lock);
2094 return -1;
2096 p->dialednone = 0;
2097 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
2099 /* Special pseudo -- automatically up */
2100 ast_setstate(ast, AST_STATE_UP);
2101 ast_mutex_unlock(&p->lock);
2102 return 0;
2104 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
2105 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_FLUSH, &x);
2106 if (res)
2107 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
2108 p->outgoing = 1;
2110 set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
2112 mysig = p->sig;
2113 if (p->outsigmod > -1)
2114 mysig = p->outsigmod;
2116 switch (mysig) {
2117 case SIG_FXOLS:
2118 case SIG_FXOGS:
2119 case SIG_FXOKS:
2120 if (p->owner == ast) {
2121 /* Normal ring, on hook */
2123 /* Don't send audio while on hook, until the call is answered */
2124 p->dialing = 1;
2125 if (p->use_callerid) {
2126 /* Generate the Caller-ID spill if desired */
2127 if (p->cidspill) {
2128 ast_log(LOG_WARNING, "cidspill already exists??\n");
2129 ast_free(p->cidspill);
2131 p->callwaitcas = 0;
2132 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
2133 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
2134 p->cidpos = 0;
2135 send_callerid(p);
2138 /* Choose proper cadence */
2139 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
2140 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
2141 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
2142 p->cidrings = cidrings[p->distinctivering - 1];
2143 } else {
2144 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, NULL))
2145 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
2146 p->cidrings = p->sendcalleridafter;
2149 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
2150 c = strchr(dest, '/');
2151 if (c)
2152 c++;
2153 if (c && (strlen(c) < p->stripmsd)) {
2154 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2155 c = NULL;
2157 if (c) {
2158 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2159 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
2160 ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
2161 } else {
2162 p->dop.dialstr[0] = '\0';
2164 x = DAHDI_RING;
2165 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
2166 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
2167 ast_mutex_unlock(&p->lock);
2168 return -1;
2170 p->dialing = 1;
2171 } else {
2172 /* Call waiting call */
2173 p->callwaitrings = 0;
2174 if (ast->cid.cid_num)
2175 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
2176 else
2177 p->callwait_num[0] = '\0';
2178 if (ast->cid.cid_name)
2179 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
2180 else
2181 p->callwait_name[0] = '\0';
2182 /* Call waiting tone instead */
2183 if (dahdi_callwait(ast)) {
2184 ast_mutex_unlock(&p->lock);
2185 return -1;
2187 /* Make ring-back */
2188 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].zfd, DAHDI_TONE_RINGTONE))
2189 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
2192 n = ast->cid.cid_name;
2193 l = ast->cid.cid_num;
2194 if (l)
2195 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
2196 else
2197 p->lastcid_num[0] = '\0';
2198 if (n)
2199 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
2200 else
2201 p->lastcid_name[0] = '\0';
2202 ast_setstate(ast, AST_STATE_RINGING);
2203 idx = dahdi_get_index(ast, p, 0);
2204 if (idx > -1) {
2205 p->subs[idx].needringing = 1;
2207 break;
2208 case SIG_FXSLS:
2209 case SIG_FXSGS:
2210 case SIG_FXSKS:
2211 case SIG_EMWINK:
2212 case SIG_EM:
2213 case SIG_EM_E1:
2214 case SIG_FEATD:
2215 case SIG_FEATDMF:
2216 case SIG_E911:
2217 case SIG_FGC_CAMA:
2218 case SIG_FGC_CAMAMF:
2219 case SIG_FEATB:
2220 case SIG_SFWINK:
2221 case SIG_SF:
2222 case SIG_SF_FEATD:
2223 case SIG_SF_FEATDMF:
2224 case SIG_FEATDMF_TA:
2225 case SIG_SF_FEATB:
2226 c = strchr(dest, '/');
2227 if (c)
2228 c++;
2229 else
2230 c = "";
2231 if (strlen(c) < p->stripmsd) {
2232 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2233 ast_mutex_unlock(&p->lock);
2234 return -1;
2236 #ifdef HAVE_PRI
2237 /* Start the trunk, if not GR-303 */
2238 if (!p->pri) {
2239 #endif
2240 x = DAHDI_START;
2241 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
2242 if (res < 0) {
2243 if (errno != EINPROGRESS) {
2244 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
2245 ast_mutex_unlock(&p->lock);
2246 return -1;
2249 #ifdef HAVE_PRI
2251 #endif
2252 ast_debug(1, "Dialing '%s'\n", c);
2253 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2255 c += p->stripmsd;
2257 switch (mysig) {
2258 case SIG_FEATD:
2259 l = ast->cid.cid_num;
2260 if (l)
2261 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
2262 else
2263 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
2264 break;
2265 case SIG_FEATDMF:
2266 l = ast->cid.cid_num;
2267 if (l)
2268 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
2269 else
2270 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
2271 break;
2272 case SIG_FEATDMF_TA:
2274 const char *cic, *ozz;
2276 /* If you have to go through a Tandem Access point you need to use this */
2277 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
2278 if (!ozz)
2279 ozz = defaultozz;
2280 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
2281 if (!cic)
2282 cic = defaultcic;
2283 if (!ozz || !cic) {
2284 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2285 ast_mutex_unlock(&p->lock);
2286 return -1;
2288 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
2289 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
2290 p->whichwink = 0;
2292 break;
2293 case SIG_E911:
2294 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2295 break;
2296 case SIG_FGC_CAMA:
2297 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2298 break;
2299 case SIG_FGC_CAMAMF:
2300 case SIG_FEATB:
2301 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2302 break;
2303 default:
2304 if (p->pulse)
2305 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2306 else
2307 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2308 break;
2311 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2312 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2313 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2314 p->echorest[sizeof(p->echorest) - 1] = '\0';
2315 p->echobreak = 1;
2316 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2317 } else
2318 p->echobreak = 0;
2319 if (!res) {
2320 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop)) {
2321 int saveerr = errno;
2323 x = DAHDI_ONHOOK;
2324 ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
2325 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2326 ast_mutex_unlock(&p->lock);
2327 return -1;
2329 } else
2330 ast_debug(1, "Deferring dialing...\n");
2332 p->dialing = 1;
2333 if (ast_strlen_zero(c))
2334 p->dialednone = 1;
2335 ast_setstate(ast, AST_STATE_DIALING);
2336 break;
2337 case 0:
2338 /* Special pseudo -- automatically up*/
2339 ast_setstate(ast, AST_STATE_UP);
2340 break;
2341 case SIG_PRI:
2342 case SIG_BRI:
2343 case SIG_BRI_PTMP:
2344 case SIG_SS7:
2345 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2346 p->dialdest[0] = '\0';
2347 break;
2348 default:
2349 ast_debug(1, "not yet implemented\n");
2350 ast_mutex_unlock(&p->lock);
2351 return -1;
2353 #ifdef HAVE_SS7
2354 if (p->ss7) {
2355 char ss7_called_nai;
2356 int called_nai_strip;
2357 char ss7_calling_nai;
2358 int calling_nai_strip;
2359 const char *charge_str = NULL;
2360 const char *gen_address = NULL;
2361 const char *gen_digits = NULL;
2362 const char *gen_dig_type = NULL;
2363 const char *gen_dig_scheme = NULL;
2364 const char *gen_name = NULL;
2365 const char *jip_digits = NULL;
2366 const char *lspi_ident = NULL;
2367 const char *rlt_flag = NULL;
2368 const char *call_ref_id = NULL;
2369 const char *call_ref_pc = NULL;
2370 const char *send_far = NULL;
2372 c = strchr(dest, '/');
2373 if (c)
2374 c++;
2375 else
2376 c = dest;
2378 if (!p->hidecallerid) {
2379 l = ast->cid.cid_num;
2380 } else {
2381 l = NULL;
2384 if (ss7_grab(p, p->ss7)) {
2385 ast_log(LOG_WARNING, "Failed to grab SS7!\n");
2386 ast_mutex_unlock(&p->lock);
2387 return -1;
2389 p->digital = IS_DIGITAL(ast->transfercapability);
2390 p->ss7call = isup_new_call(p->ss7->ss7);
2392 if (!p->ss7call) {
2393 ss7_rel(p->ss7);
2394 ast_mutex_unlock(&p->lock);
2395 ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
2396 return -1;
2399 called_nai_strip = 0;
2400 ss7_called_nai = p->ss7->called_nai;
2401 if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
2402 if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
2403 called_nai_strip = strlen(p->ss7->internationalprefix);
2404 ss7_called_nai = SS7_NAI_INTERNATIONAL;
2405 } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
2406 called_nai_strip = strlen(p->ss7->nationalprefix);
2407 ss7_called_nai = SS7_NAI_NATIONAL;
2408 } else {
2409 ss7_called_nai = SS7_NAI_SUBSCRIBER;
2412 isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
2414 calling_nai_strip = 0;
2415 ss7_calling_nai = p->ss7->calling_nai;
2416 if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
2417 if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
2418 calling_nai_strip = strlen(p->ss7->internationalprefix);
2419 ss7_calling_nai = SS7_NAI_INTERNATIONAL;
2420 } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
2421 calling_nai_strip = strlen(p->ss7->nationalprefix);
2422 ss7_calling_nai = SS7_NAI_NATIONAL;
2423 } else {
2424 ss7_calling_nai = SS7_NAI_SUBSCRIBER;
2427 isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
2428 p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
2429 p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
2431 isup_set_oli(p->ss7call, ast->cid.cid_ani2);
2432 isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
2434 ast_channel_lock(ast);
2435 /* Set the charge number if it is set */
2436 charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
2437 if (charge_str)
2438 isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
2440 gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
2441 if (gen_address)
2442 isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
2444 gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
2445 gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
2446 gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
2447 if (gen_digits)
2448 isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
2450 gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
2451 if (gen_name)
2452 isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
2454 jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
2455 if (jip_digits)
2456 isup_set_jip_digits(p->ss7call, jip_digits);
2458 lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
2459 if (lspi_ident)
2460 isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
2462 rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
2463 if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
2464 isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
2467 call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
2468 call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
2469 if (call_ref_id && call_ref_pc) {
2470 isup_set_callref(p->ss7call, atoi(call_ref_id),
2471 call_ref_pc ? atoi(call_ref_pc) : 0);
2474 send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
2475 if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
2476 (isup_far(p->ss7->ss7, p->ss7call));
2478 ast_channel_unlock(ast);
2480 isup_iam(p->ss7->ss7, p->ss7call);
2481 ast_setstate(ast, AST_STATE_DIALING);
2482 ss7_rel(p->ss7);
2484 #endif /* HAVE_SS7 */
2485 #ifdef HAVE_PRI
2486 if (p->pri) {
2487 struct pri_sr *sr;
2488 #ifdef SUPPORT_USERUSER
2489 const char *useruser;
2490 #endif
2491 int pridialplan;
2492 int dp_strip;
2493 int prilocaldialplan;
2494 int ldp_strip;
2495 int exclusive;
2496 const char *rr_str;
2497 int redirect_reason;
2499 c = strchr(dest, '/');
2500 if (c)
2501 c++;
2502 else
2503 c = dest;
2505 l = NULL;
2506 n = NULL;
2508 if (!p->hidecallerid) {
2509 l = ast->cid.cid_num;
2510 if (!p->hidecalleridname) {
2511 n = ast->cid.cid_name;
2515 if (strlen(c) < p->stripmsd) {
2516 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2517 ast_mutex_unlock(&p->lock);
2518 return -1;
2520 if (mysig != SIG_FXSKS) {
2521 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2522 s = strchr(c + p->stripmsd, 'w');
2523 if (s) {
2524 if (strlen(s) > 1)
2525 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2526 else
2527 p->dop.dialstr[0] = '\0';
2528 *s = '\0';
2529 } else {
2530 p->dop.dialstr[0] = '\0';
2533 if (pri_grab(p, p->pri)) {
2534 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2535 ast_mutex_unlock(&p->lock);
2536 return -1;
2538 if (!(p->call = pri_new_call(p->pri->pri))) {
2539 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2540 pri_rel(p->pri);
2541 ast_mutex_unlock(&p->lock);
2542 return -1;
2544 if (!(sr = pri_sr_new())) {
2545 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2546 pri_rel(p->pri);
2547 ast_mutex_unlock(&p->lock);
2549 if (p->bearer || (mysig == SIG_FXSKS)) {
2550 if (p->bearer) {
2551 ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
2552 p->bearer->call = p->call;
2553 } else
2554 ast_debug(1, "I'm being setup with no bearer right now...\n");
2556 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2558 p->digital = IS_DIGITAL(ast->transfercapability);
2559 /* Add support for exclusive override */
2560 if (p->priexclusive)
2561 exclusive = 1;
2562 else {
2563 /* otherwise, traditional behavior */
2564 if (p->pri->nodetype == PRI_NETWORK)
2565 exclusive = 0;
2566 else
2567 exclusive = 1;
2570 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2571 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2572 (p->digital ? -1 :
2573 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2574 if (p->pri->facilityenable)
2575 pri_facility_enable(p->pri->pri);
2577 ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2578 dp_strip = 0;
2579 pridialplan = p->pri->dialplan - 1;
2580 if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
2581 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2582 if (pridialplan == -2) {
2583 dp_strip = strlen(p->pri->internationalprefix);
2585 pridialplan = PRI_INTERNATIONAL_ISDN;
2586 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2587 if (pridialplan == -2) {
2588 dp_strip = strlen(p->pri->nationalprefix);
2590 pridialplan = PRI_NATIONAL_ISDN;
2591 } else {
2592 pridialplan = PRI_LOCAL_ISDN;
2595 while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
2596 switch (c[p->stripmsd]) {
2597 case 'U':
2598 pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
2599 break;
2600 case 'I':
2601 pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
2602 break;
2603 case 'N':
2604 pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
2605 break;
2606 case 'L':
2607 pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
2608 break;
2609 case 'S':
2610 pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
2611 break;
2612 case 'V':
2613 pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
2614 break;
2615 case 'R':
2616 pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
2617 break;
2618 case 'u':
2619 pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
2620 break;
2621 case 'e':
2622 pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
2623 break;
2624 case 'x':
2625 pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
2626 break;
2627 case 'f':
2628 pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
2629 break;
2630 case 'n':
2631 pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
2632 break;
2633 case 'p':
2634 pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
2635 break;
2636 case 'r':
2637 pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
2638 break;
2639 default:
2640 if (isalpha(*c))
2641 ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
2643 c++;
2645 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2647 ldp_strip = 0;
2648 prilocaldialplan = p->pri->localdialplan - 1;
2649 if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
2650 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2651 if (prilocaldialplan == -2) {
2652 ldp_strip = strlen(p->pri->internationalprefix);
2654 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2655 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2656 if (prilocaldialplan == -2) {
2657 ldp_strip = strlen(p->pri->nationalprefix);
2659 prilocaldialplan = PRI_NATIONAL_ISDN;
2660 } else {
2661 prilocaldialplan = PRI_LOCAL_ISDN;
2664 if (l != NULL) {
2665 while (*l > '9' && *l != '*' && *l != '#') {
2666 switch (*l) {
2667 case 'U':
2668 prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
2669 break;
2670 case 'I':
2671 prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
2672 break;
2673 case 'N':
2674 prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
2675 break;
2676 case 'L':
2677 prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
2678 break;
2679 case 'S':
2680 prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
2681 break;
2682 case 'V':
2683 prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
2684 break;
2685 case 'R':
2686 prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
2687 break;
2688 case 'u':
2689 prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
2690 break;
2691 case 'e':
2692 prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
2693 break;
2694 case 'x':
2695 prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
2696 break;
2697 case 'f':
2698 prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
2699 break;
2700 case 'n':
2701 prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
2702 break;
2703 case 'p':
2704 prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
2705 break;
2706 case 'r':
2707 prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
2708 break;
2709 default:
2710 if (isalpha(*l))
2711 ast_log(LOG_WARNING, "Unrecognized prilocaldialplan %s modifier: %c\n", *c > 'Z' ? "NPI" : "TON", *c);
2713 l++;
2716 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2717 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2718 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2719 if (!strcasecmp(rr_str, "UNKNOWN"))
2720 redirect_reason = 0;
2721 else if (!strcasecmp(rr_str, "BUSY"))
2722 redirect_reason = 1;
2723 else if (!strcasecmp(rr_str, "NO_REPLY"))
2724 redirect_reason = 2;
2725 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2726 redirect_reason = 15;
2727 else
2728 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2729 } else
2730 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2731 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2733 #ifdef SUPPORT_USERUSER
2734 /* User-user info */
2735 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2737 if (useruser)
2738 pri_sr_set_useruser(sr, useruser);
2739 #endif
2741 if (pri_setup(p->pri->pri, p->call, sr)) {
2742 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2743 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2744 pri_rel(p->pri);
2745 ast_mutex_unlock(&p->lock);
2746 pri_sr_free(sr);
2747 return -1;
2749 pri_sr_free(sr);
2750 ast_setstate(ast, AST_STATE_DIALING);
2751 pri_rel(p->pri);
2753 #endif
2754 ast_mutex_unlock(&p->lock);
2755 return 0;
2758 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2760 struct dahdi_pvt *p = *pvt;
2761 /* Remove channel from the list */
2762 if (p->prev)
2763 p->prev->next = p->next;
2764 if (p->next)
2765 p->next->prev = p->prev;
2766 if (p->use_smdi)
2767 ast_smdi_interface_unref(p->smdi_iface);
2768 if (p->mwi_event_sub)
2769 ast_event_unsubscribe(p->mwi_event_sub);
2770 if (p->vars)
2771 ast_variables_destroy(p->vars);
2772 ast_mutex_destroy(&p->lock);
2773 ast_free(p);
2774 *pvt = NULL;
2777 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2779 int owned = 0;
2780 int i = 0;
2782 if (!now) {
2783 if (cur->owner) {
2784 owned = 1;
2787 for (i = 0; i < 3; i++) {
2788 if (cur->subs[i].owner) {
2789 owned = 1;
2792 if (!owned) {
2793 if (prev) {
2794 prev->next = cur->next;
2795 if (prev->next)
2796 prev->next->prev = prev;
2797 else
2798 ifend = prev;
2799 } else {
2800 iflist = cur->next;
2801 if (iflist)
2802 iflist->prev = NULL;
2803 else
2804 ifend = NULL;
2806 if (cur->subs[SUB_REAL].zfd > -1) {
2807 dahdi_close(cur->subs[SUB_REAL].zfd);
2809 destroy_dahdi_pvt(&cur);
2811 } else {
2812 if (prev) {
2813 prev->next = cur->next;
2814 if (prev->next)
2815 prev->next->prev = prev;
2816 else
2817 ifend = prev;
2818 } else {
2819 iflist = cur->next;
2820 if (iflist)
2821 iflist->prev = NULL;
2822 else
2823 ifend = NULL;
2825 if (cur->subs[SUB_REAL].zfd > -1) {
2826 dahdi_close(cur->subs[SUB_REAL].zfd);
2828 destroy_dahdi_pvt(&cur);
2830 return 0;
2833 #ifdef HAVE_PRI
2834 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2836 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2838 static char *dahdi_send_keypad_facility_descrip =
2839 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2840 " IE over the current channel.\n";
2842 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2844 /* Data will be our digit string */
2845 struct dahdi_pvt *p;
2846 char *digits = (char *) data;
2848 if (ast_strlen_zero(digits)) {
2849 ast_debug(1, "No digit string sent to application!\n");
2850 return -1;
2853 p = (struct dahdi_pvt *)chan->tech_pvt;
2855 if (!p) {
2856 ast_debug(1, "Unable to find technology private\n");
2857 return -1;
2860 ast_mutex_lock(&p->lock);
2862 if (!p->pri || !p->call) {
2863 ast_debug(1, "Unable to find pri or call on channel!\n");
2864 ast_mutex_unlock(&p->lock);
2865 return -1;
2868 if (!pri_grab(p, p->pri)) {
2869 pri_keypad_facility(p->pri->pri, p->call, digits);
2870 pri_rel(p->pri);
2871 } else {
2872 ast_debug(1, "Unable to grab pri to send keypad facility!\n");
2873 ast_mutex_unlock(&p->lock);
2874 return -1;
2877 ast_mutex_unlock(&p->lock);
2879 return 0;
2882 static int pri_is_up(struct dahdi_pri *pri)
2884 int x;
2885 for (x = 0; x < NUM_DCHANS; x++) {
2886 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2887 return 1;
2889 return 0;
2892 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2894 bearer->owner = &inuse;
2895 bearer->realcall = crv;
2896 crv->subs[SUB_REAL].zfd = bearer->subs[SUB_REAL].zfd;
2897 if (crv->subs[SUB_REAL].owner)
2898 ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].zfd);
2899 crv->bearer = bearer;
2900 crv->call = bearer->call;
2901 crv->pri = pri;
2902 return 0;
2905 static char *pri_order(int level)
2907 switch (level) {
2908 case 0:
2909 return "Primary";
2910 case 1:
2911 return "Secondary";
2912 case 2:
2913 return "Tertiary";
2914 case 3:
2915 return "Quaternary";
2916 default:
2917 return "<Unknown>";
2921 /* Returns fd of the active dchan */
2922 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2924 int x = -1;
2926 for (x = 0; x < NUM_DCHANS; x++) {
2927 if ((pri->dchans[x] == pri->pri))
2928 break;
2931 return pri->fds[x];
2934 static int pri_find_dchan(struct dahdi_pri *pri)
2936 int oldslot = -1;
2937 struct pri *old;
2938 int newslot = -1;
2939 int x;
2940 old = pri->pri;
2941 for (x = 0; x < NUM_DCHANS; x++) {
2942 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2943 newslot = x;
2944 if (pri->dchans[x] == old) {
2945 oldslot = x;
2948 if (newslot < 0) {
2949 newslot = 0;
2950 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2951 pri->dchannels[newslot]);
2953 if (old && (oldslot != newslot))
2954 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2955 pri->dchannels[oldslot], pri->dchannels[newslot]);
2956 pri->pri = pri->dchans[newslot];
2957 return 0;
2959 #endif
2961 static int dahdi_hangup(struct ast_channel *ast)
2963 int res;
2964 int idx,x, law;
2965 /*static int restore_gains(struct dahdi_pvt *p);*/
2966 struct dahdi_pvt *p = ast->tech_pvt;
2967 struct dahdi_pvt *tmp = NULL;
2968 struct dahdi_pvt *prev = NULL;
2969 struct dahdi_params par;
2971 ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
2972 if (!ast->tech_pvt) {
2973 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2974 return 0;
2977 ast_mutex_lock(&p->lock);
2979 idx = dahdi_get_index(ast, p, 1);
2981 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
2982 x = 1;
2983 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2986 x = 0;
2987 dahdi_confmute(p, 0);
2988 p->muting = 0;
2989 restore_gains(p);
2990 if (p->origcid_num) {
2991 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2992 ast_free(p->origcid_num);
2993 p->origcid_num = NULL;
2995 if (p->origcid_name) {
2996 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2997 ast_free(p->origcid_name);
2998 p->origcid_name = NULL;
3000 if (p->dsp)
3001 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
3002 if (p->exten)
3003 p->exten[0] = '\0';
3005 ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
3006 p->channel, idx, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
3007 p->ignoredtmf = 0;
3009 if (idx > -1) {
3010 /* Real channel, do some fixup */
3011 p->subs[idx].owner = NULL;
3012 p->subs[idx].needanswer = 0;
3013 p->subs[idx].needflash = 0;
3014 p->subs[idx].needringing = 0;
3015 p->subs[idx].needbusy = 0;
3016 p->subs[idx].needcongestion = 0;
3017 p->subs[idx].linear = 0;
3018 p->subs[idx].needcallerid = 0;
3019 p->polarity = POLARITY_IDLE;
3020 dahdi_setlinear(p->subs[idx].zfd, 0);
3021 if (idx == SUB_REAL) {
3022 if ((p->subs[SUB_CALLWAIT].zfd > -1) && (p->subs[SUB_THREEWAY].zfd > -1)) {
3023 ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
3024 if (p->subs[SUB_CALLWAIT].inthreeway) {
3025 /* We had flipped over to answer a callwait and now it's gone */
3026 ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
3027 /* Move to the call-wait, but un-own us until they flip back. */
3028 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3029 unalloc_sub(p, SUB_CALLWAIT);
3030 p->owner = NULL;
3031 } else {
3032 /* The three way hung up, but we still have a call wait */
3033 ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
3034 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3035 unalloc_sub(p, SUB_THREEWAY);
3036 if (p->subs[SUB_REAL].inthreeway) {
3037 /* This was part of a three way call. Immediately make way for
3038 another call */
3039 ast_debug(1, "Call was complete, setting owner to former third call\n");
3040 p->owner = p->subs[SUB_REAL].owner;
3041 } else {
3042 /* This call hasn't been completed yet... Set owner to NULL */
3043 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3044 p->owner = NULL;
3046 p->subs[SUB_REAL].inthreeway = 0;
3048 } else if (p->subs[SUB_CALLWAIT].zfd > -1) {
3049 /* Move to the call-wait and switch back to them. */
3050 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3051 unalloc_sub(p, SUB_CALLWAIT);
3052 p->owner = p->subs[SUB_REAL].owner;
3053 if (p->owner->_state != AST_STATE_UP)
3054 p->subs[SUB_REAL].needanswer = 1;
3055 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
3056 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3057 } else if (p->subs[SUB_THREEWAY].zfd > -1) {
3058 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3059 unalloc_sub(p, SUB_THREEWAY);
3060 if (p->subs[SUB_REAL].inthreeway) {
3061 /* This was part of a three way call. Immediately make way for
3062 another call */
3063 ast_debug(1, "Call was complete, setting owner to former third call\n");
3064 p->owner = p->subs[SUB_REAL].owner;
3065 } else {
3066 /* This call hasn't been completed yet... Set owner to NULL */
3067 ast_debug(1, "Call was incomplete, setting owner to NULL\n");
3068 p->owner = NULL;
3070 p->subs[SUB_REAL].inthreeway = 0;
3072 } else if (idx == SUB_CALLWAIT) {
3073 /* Ditch the holding callwait call, and immediately make it availabe */
3074 if (p->subs[SUB_CALLWAIT].inthreeway) {
3075 /* This is actually part of a three way, placed on hold. Place the third part
3076 on music on hold now */
3077 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3078 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
3079 S_OR(p->mohsuggest, NULL),
3080 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
3082 p->subs[SUB_THREEWAY].inthreeway = 0;
3083 /* Make it the call wait now */
3084 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
3085 unalloc_sub(p, SUB_THREEWAY);
3086 } else
3087 unalloc_sub(p, SUB_CALLWAIT);
3088 } else if (idx == SUB_THREEWAY) {
3089 if (p->subs[SUB_CALLWAIT].inthreeway) {
3090 /* The other party of the three way call is currently in a call-wait state.
3091 Start music on hold for them, and take the main guy out of the third call */
3092 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
3093 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
3094 S_OR(p->mohsuggest, NULL),
3095 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
3097 p->subs[SUB_CALLWAIT].inthreeway = 0;
3099 p->subs[SUB_REAL].inthreeway = 0;
3100 /* If this was part of a three way call index, let us make
3101 another three way call */
3102 unalloc_sub(p, SUB_THREEWAY);
3103 } else {
3104 /* This wasn't any sort of call, but how are we an index? */
3105 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
3109 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
3110 p->owner = NULL;
3111 p->ringt = 0;
3112 p->distinctivering = 0;
3113 p->confirmanswer = 0;
3114 p->cidrings = 1;
3115 p->outgoing = 0;
3116 p->digital = 0;
3117 p->faxhandled = 0;
3118 p->pulsedial = 0;
3119 p->onhooktime = time(NULL);
3120 #if defined(HAVE_PRI) || defined(HAVE_SS7)
3121 p->proceeding = 0;
3122 p->progress = 0;
3123 p->alerting = 0;
3124 p->setup_ack = 0;
3125 p->rlt = 0;
3126 #endif
3127 if (p->dsp) {
3128 ast_dsp_free(p->dsp);
3129 p->dsp = NULL;
3132 law = DAHDI_LAW_DEFAULT;
3133 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETLAW, &law);
3134 if (res < 0)
3135 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
3136 /* Perform low level hangup if no owner left */
3137 #ifdef HAVE_SS7
3138 if (p->ss7) {
3139 if (p->ss7call) {
3140 if (!ss7_grab(p, p->ss7)) {
3141 if (!p->alreadyhungup) {
3142 const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
3143 int icause = ast->hangupcause ? ast->hangupcause : -1;
3145 if (cause) {
3146 if (atoi(cause))
3147 icause = atoi(cause);
3149 isup_rel(p->ss7->ss7, p->ss7call, icause);
3150 ss7_rel(p->ss7);
3151 p->alreadyhungup = 1;
3152 } else
3153 ast_log(LOG_WARNING, "Trying to hangup twice!\n");
3154 } else {
3155 ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
3156 res = -1;
3160 #endif
3161 #ifdef HAVE_PRI
3162 if (p->pri) {
3163 #ifdef SUPPORT_USERUSER
3164 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
3165 #endif
3167 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
3168 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
3169 if (!pri_grab(p, p->pri)) {
3170 if (p->alreadyhungup) {
3171 ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
3173 #ifdef SUPPORT_USERUSER
3174 pri_call_set_useruser(p->call, useruser);
3175 #endif
3177 pri_hangup(p->pri->pri, p->call, -1);
3178 p->call = NULL;
3179 if (p->bearer)
3180 p->bearer->call = NULL;
3181 } else {
3182 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
3183 int icause = ast->hangupcause ? ast->hangupcause : -1;
3184 ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
3186 #ifdef SUPPORT_USERUSER
3187 pri_call_set_useruser(p->call, useruser);
3188 #endif
3190 p->alreadyhungup = 1;
3191 if (p->bearer)
3192 p->bearer->alreadyhungup = 1;
3193 if (cause) {
3194 if (atoi(cause))
3195 icause = atoi(cause);
3197 pri_hangup(p->pri->pri, p->call, icause);
3199 if (res < 0)
3200 ast_log(LOG_WARNING, "pri_disconnect failed\n");
3201 pri_rel(p->pri);
3202 } else {
3203 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
3204 res = -1;
3206 } else {
3207 if (p->bearer)
3208 ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
3209 p->call = NULL;
3210 res = 0;
3213 #endif
3214 if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
3215 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
3216 if (res < 0) {
3217 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
3219 switch (p->sig) {
3220 case SIG_FXOGS:
3221 case SIG_FXOLS:
3222 case SIG_FXOKS:
3223 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &par);
3224 if (!res) {
3225 #if 0
3226 ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
3227 #endif
3228 /* If they're off hook, try playing congestion */
3229 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
3230 tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
3231 else
3232 tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
3234 break;
3235 case SIG_FXSGS:
3236 case SIG_FXSLS:
3237 case SIG_FXSKS:
3238 /* Make sure we're not made available for at least two seconds assuming
3239 we were actually used for an inbound or outbound call. */
3240 if (ast->_state != AST_STATE_RESERVED) {
3241 time(&p->guardtime);
3242 p->guardtime += 2;
3244 break;
3245 default:
3246 tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
3248 if (p->cidspill)
3249 ast_free(p->cidspill);
3250 if (p->sig)
3251 dahdi_disable_ec(p);
3252 x = 0;
3253 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
3254 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
3255 p->didtdd = 0;
3256 p->cidspill = NULL;
3257 p->callwaitcas = 0;
3258 p->callwaiting = p->permcallwaiting;
3259 p->hidecallerid = p->permhidecallerid;
3260 p->dialing = 0;
3261 p->rdnis[0] = '\0';
3262 update_conf(p);
3263 reset_conf(p);
3264 /* Restore data mode */
3265 if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
3266 x = 0;
3267 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
3269 #ifdef HAVE_PRI
3270 if (p->bearer) {
3271 ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
3272 /* Free up the bearer channel as well, and
3273 don't use its file descriptor anymore */
3274 update_conf(p->bearer);
3275 reset_conf(p->bearer);
3276 p->bearer->owner = NULL;
3277 p->bearer->realcall = NULL;
3278 p->bearer = NULL;
3279 p->subs[SUB_REAL].zfd = -1;
3280 p->pri = NULL;
3282 #endif
3283 restart_monitor();
3286 p->callwaitingrepeat = 0;
3287 p->cidcwexpire = 0;
3288 p->oprmode = 0;
3289 ast->tech_pvt = NULL;
3290 ast_mutex_unlock(&p->lock);
3291 ast_module_unref(ast_module_info->self);
3292 ast_verb(3, "Hungup '%s'\n", ast->name);
3294 ast_mutex_lock(&iflock);
3295 tmp = iflist;
3296 prev = NULL;
3297 if (p->destroy) {
3298 while (tmp) {
3299 if (tmp == p) {
3300 destroy_channel(prev, tmp, 0);
3301 break;
3302 } else {
3303 prev = tmp;
3304 tmp = tmp->next;
3308 ast_mutex_unlock(&iflock);
3309 return 0;
3312 static int dahdi_answer(struct ast_channel *ast)
3314 struct dahdi_pvt *p = ast->tech_pvt;
3315 int res = 0;
3316 int idx;
3317 int oldstate = ast->_state;
3318 ast_setstate(ast, AST_STATE_UP);
3319 ast_mutex_lock(&p->lock);
3320 idx = dahdi_get_index(ast, p, 0);
3321 if (idx < 0)
3322 idx = SUB_REAL;
3323 /* nothing to do if a radio channel */
3324 if ((p->radio || (p->oprmode < 0))) {
3325 ast_mutex_unlock(&p->lock);
3326 return 0;
3328 switch (p->sig) {
3329 case SIG_FXSLS:
3330 case SIG_FXSGS:
3331 case SIG_FXSKS:
3332 p->ringt = 0;
3333 /* Fall through */
3334 case SIG_EM:
3335 case SIG_EM_E1:
3336 case SIG_EMWINK:
3337 case SIG_FEATD:
3338 case SIG_FEATDMF:
3339 case SIG_FEATDMF_TA:
3340 case SIG_E911:
3341 case SIG_FGC_CAMA:
3342 case SIG_FGC_CAMAMF:
3343 case SIG_FEATB:
3344 case SIG_SF:
3345 case SIG_SFWINK:
3346 case SIG_SF_FEATD:
3347 case SIG_SF_FEATDMF:
3348 case SIG_SF_FEATB:
3349 case SIG_FXOLS:
3350 case SIG_FXOGS:
3351 case SIG_FXOKS:
3352 /* Pick up the line */
3353 ast_debug(1, "Took %s off hook\n", ast->name);
3354 if (p->hanguponpolarityswitch) {
3355 p->polaritydelaytv = ast_tvnow();
3357 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
3358 tone_zone_play_tone(p->subs[idx].zfd, -1);
3359 p->dialing = 0;
3360 if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
3361 if (oldstate == AST_STATE_RINGING) {
3362 ast_debug(1, "Finally swapping real and threeway\n");
3363 tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, -1);
3364 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3365 p->owner = p->subs[SUB_REAL].owner;
3368 if (p->sig & __DAHDI_SIG_FXS) {
3369 dahdi_enable_ec(p);
3370 dahdi_train_ec(p);
3372 break;
3373 #ifdef HAVE_PRI
3374 case SIG_BRI:
3375 case SIG_BRI_PTMP:
3376 case SIG_PRI:
3377 /* Send a pri acknowledge */
3378 if (!pri_grab(p, p->pri)) {
3379 p->proceeding = 1;
3380 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
3381 pri_rel(p->pri);
3382 } else {
3383 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
3384 res = -1;
3386 break;
3387 #endif
3388 #ifdef HAVE_SS7
3389 case SIG_SS7:
3390 if (!ss7_grab(p, p->ss7)) {
3391 p->proceeding = 1;
3392 res = isup_anm(p->ss7->ss7, p->ss7call);
3393 ss7_rel(p->ss7);
3394 } else {
3395 ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
3396 res = -1;
3398 break;
3399 #endif
3400 case 0:
3401 ast_mutex_unlock(&p->lock);
3402 return 0;
3403 default:
3404 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
3405 res = -1;
3407 ast_mutex_unlock(&p->lock);
3408 return res;
3411 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
3413 char *cp;
3414 signed char *scp;
3415 int x;
3416 int idx;
3417 struct dahdi_pvt *p = chan->tech_pvt, *pp;
3418 struct oprmode *oprmode;
3421 /* all supported options require data */
3422 if (!data || (datalen < 1)) {
3423 errno = EINVAL;
3424 return -1;
3427 switch (option) {
3428 case AST_OPTION_TXGAIN:
3429 scp = (signed char *) data;
3430 idx = dahdi_get_index(chan, p, 0);
3431 if (idx < 0) {
3432 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
3433 return -1;
3435 ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
3436 return set_actual_txgain(p->subs[idx].zfd, 0, p->txgain + (float) *scp, p->law);
3437 case AST_OPTION_RXGAIN:
3438 scp = (signed char *) data;
3439 idx = dahdi_get_index(chan, p, 0);
3440 if (idx < 0) {
3441 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
3442 return -1;
3444 ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
3445 return set_actual_rxgain(p->subs[idx].zfd, 0, p->rxgain + (float) *scp, p->law);
3446 case AST_OPTION_TONE_VERIFY:
3447 if (!p->dsp)
3448 break;
3449 cp = (char *) data;
3450 switch (*cp) {
3451 case 1:
3452 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
3453 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
3454 break;
3455 case 2:
3456 ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
3457 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
3458 break;
3459 default:
3460 ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
3461 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
3462 break;
3464 break;
3465 case AST_OPTION_TDD:
3466 /* turn on or off TDD */
3467 cp = (char *) data;
3468 p->mate = 0;
3469 if (!*cp) { /* turn it off */
3470 ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
3471 if (p->tdd)
3472 tdd_free(p->tdd);
3473 p->tdd = 0;
3474 break;
3476 ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
3477 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
3478 dahdi_disable_ec(p);
3479 /* otherwise, turn it on */
3480 if (!p->didtdd) { /* if havent done it yet */
3481 unsigned char mybuf[41000], *buf;
3482 int size, res, fd, len;
3483 struct pollfd fds[1];
3485 buf = mybuf;
3486 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
3487 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
3488 len = 40000;
3489 idx = dahdi_get_index(chan, p, 0);
3490 if (idx < 0) {
3491 ast_log(LOG_WARNING, "No index in TDD?\n");
3492 return -1;
3494 fd = p->subs[idx].zfd;
3495 while (len) {
3496 if (ast_check_hangup(chan))
3497 return -1;
3498 size = len;
3499 if (size > READ_SIZE)
3500 size = READ_SIZE;
3501 fds[0].fd = fd;
3502 fds[0].events = POLLPRI | POLLOUT;
3503 fds[0].revents = 0;
3504 res = poll(fds, 1, -1);
3505 if (!res) {
3506 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
3507 continue;
3509 /* if got exception */
3510 if (fds[0].revents & POLLPRI)
3511 return -1;
3512 if (!(fds[0].revents & POLLOUT)) {
3513 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
3514 continue;
3516 res = write(fd, buf, size);
3517 if (res != size) {
3518 if (res == -1) return -1;
3519 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
3520 break;
3522 len -= size;
3523 buf += size;
3525 p->didtdd = 1; /* set to have done it now */
3527 if (*cp == 2) { /* Mate mode */
3528 if (p->tdd)
3529 tdd_free(p->tdd);
3530 p->tdd = 0;
3531 p->mate = 1;
3532 break;
3534 if (!p->tdd) { /* if we dont have one yet */
3535 p->tdd = tdd_new(); /* allocate one */
3537 break;
3538 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
3539 if (!p->dsp)
3540 break;
3541 cp = (char *) data;
3542 ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3543 *cp ? "ON" : "OFF", (int) *cp, chan->name);
3544 ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
3545 break;
3546 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
3547 cp = (char *) data;
3548 if (!*cp) {
3549 ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
3550 x = 0;
3551 dahdi_disable_ec(p);
3552 } else {
3553 ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
3554 x = 1;
3556 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &x) == -1)
3557 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
3558 break;
3559 case AST_OPTION_OPRMODE: /* Operator services mode */
3560 oprmode = (struct oprmode *) data;
3561 pp = oprmode->peer->tech_pvt;
3562 p->oprmode = pp->oprmode = 0;
3563 /* setup peers */
3564 p->oprpeer = pp;
3565 pp->oprpeer = p;
3566 /* setup modes, if any */
3567 if (oprmode->mode)
3569 pp->oprmode = oprmode->mode;
3570 p->oprmode = -oprmode->mode;
3572 ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
3573 oprmode->mode, chan->name,oprmode->peer->name);
3574 break;
3575 case AST_OPTION_ECHOCAN:
3576 cp = (char *) data;
3577 if (*cp) {
3578 ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
3579 dahdi_enable_ec(p);
3580 } else {
3581 ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
3582 dahdi_disable_ec(p);
3584 break;
3586 errno = 0;
3588 return 0;
3591 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
3593 struct dahdi_pvt *p = chan->tech_pvt;
3595 if (!strcasecmp(data, "rxgain")) {
3596 ast_mutex_lock(&p->lock);
3597 snprintf(buf, len, "%f", p->rxgain);
3598 ast_mutex_unlock(&p->lock);
3599 } else if (!strcasecmp(data, "txgain")) {
3600 ast_mutex_lock(&p->lock);
3601 snprintf(buf, len, "%f", p->txgain);
3602 ast_mutex_unlock(&p->lock);
3603 } else {
3604 ast_copy_string(buf, "", len);
3606 return 0;
3610 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3612 /* Unlink a specific slave or all slaves/masters from a given master */
3613 int x;
3614 int hasslaves;
3615 if (!master)
3616 return;
3617 if (needlock) {
3618 ast_mutex_lock(&master->lock);
3619 if (slave) {
3620 while (ast_mutex_trylock(&slave->lock)) {
3621 DEADLOCK_AVOIDANCE(&master->lock);
3625 hasslaves = 0;
3626 for (x = 0; x < MAX_SLAVES; x++) {
3627 if (master->slaves[x]) {
3628 if (!slave || (master->slaves[x] == slave)) {
3629 /* Take slave out of the conference */
3630 ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3631 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3632 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3633 master->slaves[x]->master = NULL;
3634 master->slaves[x] = NULL;
3635 } else
3636 hasslaves = 1;
3638 if (!hasslaves)
3639 master->inconference = 0;
3641 if (!slave) {
3642 if (master->master) {
3643 /* Take master out of the conference */
3644 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3645 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3646 hasslaves = 0;
3647 for (x = 0; x < MAX_SLAVES; x++) {
3648 if (master->master->slaves[x] == master)
3649 master->master->slaves[x] = NULL;
3650 else if (master->master->slaves[x])
3651 hasslaves = 1;
3653 if (!hasslaves)
3654 master->master->inconference = 0;
3656 master->master = NULL;
3658 update_conf(master);
3659 if (needlock) {
3660 if (slave)
3661 ast_mutex_unlock(&slave->lock);
3662 ast_mutex_unlock(&master->lock);
3666 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3667 int x;
3668 if (!slave || !master) {
3669 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3670 return;
3672 for (x = 0; x < MAX_SLAVES; x++) {
3673 if (!master->slaves[x]) {
3674 master->slaves[x] = slave;
3675 break;
3678 if (x >= MAX_SLAVES) {
3679 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3680 master->slaves[MAX_SLAVES - 1] = slave;
3682 if (slave->master)
3683 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3684 slave->master = master;
3686 ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3689 static void disable_dtmf_detect(struct dahdi_pvt *p)
3691 int val;
3693 p->ignoredtmf = 1;
3695 val = 0;
3696 ioctl(p->subs[SUB_REAL].zfd, DAHDI_TONEDETECT, &val);
3698 if (!p->hardwaredtmf && p->dsp) {
3699 p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
3700 ast_dsp_set_features(p->dsp, p->dsp_features);
3704 static void enable_dtmf_detect(struct dahdi_pvt *p)
3706 int val;
3708 if (p->channel == CHAN_PSEUDO)
3709 return;
3711 p->ignoredtmf = 0;
3713 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3714 ioctl(p->subs[SUB_REAL].zfd, DAHDI_TONEDETECT, &val);
3716 if (!p->hardwaredtmf && p->dsp) {
3717 p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
3718 ast_dsp_set_features(p->dsp, p->dsp_features);
3722 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
3724 struct ast_channel *who;
3725 struct dahdi_pvt *p0, *p1, *op0, *op1;
3726 struct dahdi_pvt *master = NULL, *slave = NULL;
3727 struct ast_frame *f;
3728 int inconf = 0;
3729 int nothingok = 1;
3730 int ofd0, ofd1;
3731 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3732 int os0 = -1, os1 = -1;
3733 int priority = 0;
3734 struct ast_channel *oc0, *oc1;
3735 enum ast_bridge_result res;
3737 #ifdef PRI_2BCT
3738 int triedtopribridge = 0;
3739 q931_call *q931c0 = NULL, *q931c1 = NULL;
3740 #endif
3742 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3743 There is code below to handle it properly until DTMF is actually seen,
3744 but due to currently unresolved issues it's ignored...
3747 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3748 return AST_BRIDGE_FAILED_NOWARN;
3750 ast_channel_lock(c0);
3751 while (ast_channel_trylock(c1)) {
3752 CHANNEL_DEADLOCK_AVOIDANCE(c0);
3755 p0 = c0->tech_pvt;
3756 p1 = c1->tech_pvt;
3757 /* cant do pseudo-channels here */
3758 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3759 ast_channel_unlock(c0);
3760 ast_channel_unlock(c1);
3761 return AST_BRIDGE_FAILED_NOWARN;
3764 oi0 = dahdi_get_index(c0, p0, 0);
3765 oi1 = dahdi_get_index(c1, p1, 0);
3766 if ((oi0 < 0) || (oi1 < 0)) {
3767 ast_channel_unlock(c0);
3768 ast_channel_unlock(c1);
3769 return AST_BRIDGE_FAILED;
3772 op0 = p0 = c0->tech_pvt;
3773 op1 = p1 = c1->tech_pvt;
3774 ofd0 = c0->fds[0];
3775 ofd1 = c1->fds[0];
3776 oc0 = p0->owner;
3777 oc1 = p1->owner;
3779 if (ast_mutex_trylock(&p0->lock)) {
3780 /* Don't block, due to potential for deadlock */
3781 ast_channel_unlock(c0);
3782 ast_channel_unlock(c1);
3783 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3784 return AST_BRIDGE_RETRY;
3786 if (ast_mutex_trylock(&p1->lock)) {
3787 /* Don't block, due to potential for deadlock */
3788 ast_mutex_unlock(&p0->lock);
3789 ast_channel_unlock(c0);
3790 ast_channel_unlock(c1);
3791 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3792 return AST_BRIDGE_RETRY;
3795 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3796 if (p0->owner && p1->owner) {
3797 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3798 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3799 master = p0;
3800 slave = p1;
3801 inconf = 1;
3802 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3803 master = p1;
3804 slave = p0;
3805 inconf = 1;
3806 } else {
3807 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3808 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3809 p0->channel,
3810 oi0, (p0->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
3811 p0->subs[SUB_REAL].inthreeway, p0->channel,
3812 oi0, (p1->subs[SUB_CALLWAIT].zfd > -1) ? 1 : 0,
3813 p1->subs[SUB_REAL].inthreeway);
3815 nothingok = 0;
3817 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3818 if (p1->subs[SUB_THREEWAY].inthreeway) {
3819 master = p1;
3820 slave = p0;
3821 nothingok = 0;
3823 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3824 if (p0->subs[SUB_THREEWAY].inthreeway) {
3825 master = p0;
3826 slave = p1;
3827 nothingok = 0;
3829 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3830 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3831 don't put us in anything */
3832 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3833 master = p1;
3834 slave = p0;
3835 nothingok = 0;
3837 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3838 /* Same as previous */
3839 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3840 master = p0;
3841 slave = p1;
3842 nothingok = 0;
3845 ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
3846 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3847 if (master && slave) {
3848 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3849 in an active threeway call with a channel that is ringing, we should
3850 indicate ringing. */
3851 if ((oi1 == SUB_THREEWAY) &&
3852 p1->subs[SUB_THREEWAY].inthreeway &&
3853 p1->subs[SUB_REAL].owner &&
3854 p1->subs[SUB_REAL].inthreeway &&
3855 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3856 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3857 tone_zone_play_tone(p0->subs[oi0].zfd, DAHDI_TONE_RINGTONE);
3858 os1 = p1->subs[SUB_REAL].owner->_state;
3859 } else {
3860 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3861 tone_zone_play_tone(p0->subs[oi0].zfd, -1);
3863 if ((oi0 == SUB_THREEWAY) &&
3864 p0->subs[SUB_THREEWAY].inthreeway &&
3865 p0->subs[SUB_REAL].owner &&
3866 p0->subs[SUB_REAL].inthreeway &&
3867 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3868 ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3869 tone_zone_play_tone(p1->subs[oi1].zfd, DAHDI_TONE_RINGTONE);
3870 os0 = p0->subs[SUB_REAL].owner->_state;
3871 } else {
3872 ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3873 tone_zone_play_tone(p1->subs[oi0].zfd, -1);
3875 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3876 if (!p0->echocanbridged || !p1->echocanbridged) {
3877 /* Disable echo cancellation if appropriate */
3878 dahdi_disable_ec(p0);
3879 dahdi_disable_ec(p1);
3882 dahdi_link(slave, master);
3883 master->inconference = inconf;
3884 } else if (!nothingok)
3885 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3887 update_conf(p0);
3888 update_conf(p1);
3889 t0 = p0->subs[SUB_REAL].inthreeway;
3890 t1 = p1->subs[SUB_REAL].inthreeway;
3892 ast_mutex_unlock(&p0->lock);
3893 ast_mutex_unlock(&p1->lock);
3895 ast_channel_unlock(c0);
3896 ast_channel_unlock(c1);
3898 /* Native bridge failed */
3899 if ((!master || !slave) && !nothingok) {
3900 dahdi_enable_ec(p0);
3901 dahdi_enable_ec(p1);
3902 return AST_BRIDGE_FAILED;
3905 ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
3907 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3908 disable_dtmf_detect(op0);
3910 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3911 disable_dtmf_detect(op1);
3913 for (;;) {
3914 struct ast_channel *c0_priority[2] = {c0, c1};
3915 struct ast_channel *c1_priority[2] = {c1, c0};
3917 /* Here's our main loop... Start by locking things, looking for private parts,
3918 and then balking if anything is wrong */
3920 ast_channel_lock(c0);
3921 while (ast_channel_trylock(c1)) {
3922 CHANNEL_DEADLOCK_AVOIDANCE(c0);
3925 p0 = c0->tech_pvt;
3926 p1 = c1->tech_pvt;
3928 if (op0 == p0)
3929 i0 = dahdi_get_index(c0, p0, 1);
3930 if (op1 == p1)
3931 i1 = dahdi_get_index(c1, p1, 1);
3933 ast_channel_unlock(c0);
3934 ast_channel_unlock(c1);
3936 if (!timeoutms ||
3937 (op0 != p0) ||
3938 (op1 != p1) ||
3939 (ofd0 != c0->fds[0]) ||
3940 (ofd1 != c1->fds[0]) ||
3941 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3942 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3943 (oc0 != p0->owner) ||
3944 (oc1 != p1->owner) ||
3945 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3946 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3947 (oi0 != i0) ||
3948 (oi1 != i1)) {
3949 ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3950 op0->channel, oi0, op1->channel, oi1);
3951 res = AST_BRIDGE_RETRY;
3952 goto return_from_bridge;
3955 #ifdef PRI_2BCT
3956 q931c0 = p0->call;
3957 q931c1 = p1->call;
3958 if (p0->transfer && p1->transfer
3959 && q931c0 && q931c1
3960 && !triedtopribridge) {
3961 pri_channel_bridge(q931c0, q931c1);
3962 triedtopribridge = 1;
3964 #endif
3966 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3967 if (!who) {
3968 ast_debug(1, "Ooh, empty read...\n");
3969 continue;
3971 f = ast_read(who);
3972 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3973 *fo = f;
3974 *rc = who;
3975 res = AST_BRIDGE_COMPLETE;
3976 goto return_from_bridge;
3978 if (f->frametype == AST_FRAME_DTMF) {
3979 if ((who == c0) && p0->pulsedial) {
3980 ast_write(c1, f);
3981 } else if ((who == c1) && p1->pulsedial) {
3982 ast_write(c0, f);
3983 } else {
3984 *fo = f;
3985 *rc = who;
3986 res = AST_BRIDGE_COMPLETE;
3987 goto return_from_bridge;
3990 ast_frfree(f);
3992 /* Swap who gets priority */
3993 priority = !priority;
3996 return_from_bridge:
3997 if (op0 == p0)
3998 dahdi_enable_ec(p0);
4000 if (op1 == p1)
4001 dahdi_enable_ec(p1);
4003 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
4004 enable_dtmf_detect(op0);
4006 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
4007 enable_dtmf_detect(op1);
4009 dahdi_unlink(slave, master, 1);
4011 return res;
4014 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
4016 struct dahdi_pvt *p = newchan->tech_pvt;
4017 int x;
4018 ast_mutex_lock(&p->lock);
4019 ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
4020 if (p->owner == oldchan) {
4021 p->owner = newchan;
4023 for (x = 0; x < 3; x++)
4024 if (p->subs[x].owner == oldchan) {
4025 if (!x)
4026 dahdi_unlink(NULL, p, 0);
4027 p->subs[x].owner = newchan;
4029 if (newchan->_state == AST_STATE_RINGING)
4030 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
4031 update_conf(p);
4032 ast_mutex_unlock(&p->lock);
4033 return 0;
4036 static int dahdi_ring_phone(struct dahdi_pvt *p)
4038 int x;
4039 int res;
4040 /* Make sure our transmit state is on hook */
4041 x = 0;
4042 x = DAHDI_ONHOOK;
4043 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
4044 do {
4045 x = DAHDI_RING;
4046 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
4047 if (res) {
4048 switch (errno) {
4049 case EBUSY:
4050 case EINTR:
4051 /* Wait just in case */
4052 usleep(10000);
4053 continue;
4054 case EINPROGRESS:
4055 res = 0;
4056 break;
4057 default:
4058 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
4059 res = 0;
4062 } while (res);
4063 return res;
4066 static void *ss_thread(void *data);
4068 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
4070 static int attempt_transfer(struct dahdi_pvt *p)
4072 /* In order to transfer, we need at least one of the channels to
4073 actually be in a call bridge. We can't conference two applications
4074 together (but then, why would we want to?) */
4075 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4076 /* The three-way person we're about to transfer to could still be in MOH, so
4077 stop if now if appropriate */
4078 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
4079 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
4080 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
4081 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
4083 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
4084 tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, DAHDI_TONE_RINGTONE);
4086 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
4087 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
4088 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
4089 return -1;
4091 /* Orphan the channel after releasing the lock */
4092 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4093 unalloc_sub(p, SUB_THREEWAY);
4094 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4095 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4096 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
4097 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
4099 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
4100 tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
4102 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
4103 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
4104 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
4105 return -1;
4107 /* Three-way is now the REAL */
4108 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4109 ast_channel_unlock(p->subs[SUB_REAL].owner);
4110 unalloc_sub(p, SUB_THREEWAY);
4111 /* Tell the caller not to hangup */
4112 return 1;
4113 } else {
4114 ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
4115 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
4116 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4117 return -1;
4119 return 0;
4122 static int check_for_conference(struct dahdi_pvt *p)
4124 struct dahdi_confinfo ci;
4125 /* Fine if we already have a master, etc */
4126 if (p->master || (p->confno > -1))
4127 return 0;
4128 memset(&ci, 0, sizeof(ci));
4129 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_GETCONF, &ci)) {
4130 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
4131 return 0;
4133 /* If we have no master and don't have a confno, then
4134 if we're in a conference, it's probably a MeetMe room or
4135 some such, so don't let us 3-way out! */
4136 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
4137 ast_verb(3, "Avoiding 3-way call when in an external conference\n");
4138 return 1;
4140 return 0;
4143 /*! Checks channel for alarms
4144 * \param p a channel to check for alarms.
4145 * \returns the alarms on the span to which the channel belongs, or alarms on
4146 * the channel if no span alarms.
4148 static int get_alarms(struct dahdi_pvt *p)
4150 int res;
4151 struct dahdi_spaninfo zi;
4152 struct dahdi_params params;
4154 memset(&zi, 0, sizeof(zi));
4155 zi.spanno = p->span;
4157 if ((res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SPANSTAT, &zi)) >= 0) {
4158 if (zi.alarms != DAHDI_ALARM_NONE)
4159 return zi.alarms;
4160 } else {
4161 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
4162 return 0;
4165 /* No alarms on the span. Check for channel alarms. */
4166 if ((res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &params)) >= 0)
4167 return params.chan_alarms;
4169 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
4171 return DAHDI_ALARM_NONE;
4174 static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_frame **dest)
4176 struct dahdi_pvt *p = ast->tech_pvt;
4177 struct ast_frame *f = *dest;
4179 ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
4181 if (p->confirmanswer) {
4182 ast_debug(1, "Confirm answer on %s!\n", ast->name);
4183 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
4184 of a DTMF digit */
4185 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4186 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
4187 *dest = &p->subs[idx].f;
4188 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
4189 p->confirmanswer = 0;
4190 } else if (p->callwaitcas) {
4191 if ((f->subclass == 'A') || (f->subclass == 'D')) {
4192 ast_debug(1, "Got some DTMF, but it's for the CAS\n");
4193 if (p->cidspill)
4194 ast_free(p->cidspill);
4195 send_cwcidspill(p);
4197 p->callwaitcas = 0;
4198 p->subs[idx].f.frametype = AST_FRAME_NULL;
4199 p->subs[idx].f.subclass = 0;
4200 *dest = &p->subs[idx].f;
4201 } else if (f->subclass == 'f') {
4202 /* Fax tone -- Handle and return NULL */
4203 if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
4204 p->faxhandled++;
4205 if (strcmp(ast->exten, "fax")) {
4206 const char *target_context = S_OR(ast->macrocontext, ast->context);
4208 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
4209 ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
4210 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
4211 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
4212 if (ast_async_goto(ast, target_context, "fax", 1))
4213 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
4214 } else
4215 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
4216 } else
4217 ast_debug(1, "Already in a fax extension, not redirecting\n");
4218 } else
4219 ast_debug(1, "Fax already handled\n");
4220 dahdi_confmute(p, 0);
4221 p->subs[idx].f.frametype = AST_FRAME_NULL;
4222 p->subs[idx].f.subclass = 0;
4223 *dest = &p->subs[idx].f;
4227 static void handle_alarms(struct dahdi_pvt *p, int alms)
4229 const char *alarm_str = alarm2str(alms);
4231 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
4232 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
4233 "Alarm: %s\r\n"
4234 "Channel: %d\r\n",
4235 alarm_str, p->channel);
4238 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
4240 int res, x;
4241 int idx, mysig;
4242 char *c;
4243 struct dahdi_pvt *p = ast->tech_pvt;
4244 pthread_t threadid;
4245 struct ast_channel *chan;
4246 struct ast_frame *f;
4248 idx = dahdi_get_index(ast, p, 0);
4249 mysig = p->sig;
4250 if (p->outsigmod > -1)
4251 mysig = p->outsigmod;
4252 p->subs[idx].f.frametype = AST_FRAME_NULL;
4253 p->subs[idx].f.subclass = 0;
4254 p->subs[idx].f.datalen = 0;
4255 p->subs[idx].f.samples = 0;
4256 p->subs[idx].f.mallocd = 0;
4257 p->subs[idx].f.offset = 0;
4258 p->subs[idx].f.src = "dahdi_handle_event";
4259 p->subs[idx].f.data.ptr = NULL;
4260 f = &p->subs[idx].f;
4262 if (idx < 0)
4263 return &p->subs[idx].f;
4264 if (p->fake_event) {
4265 res = p->fake_event;
4266 p->fake_event = 0;
4267 } else
4268 res = dahdi_get_event(p->subs[idx].zfd);
4270 ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
4272 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
4273 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
4274 ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
4275 #ifdef HAVE_PRI
4276 if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
4277 /* absorb event */
4278 } else {
4279 #endif
4280 p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
4281 p->subs[idx].f.subclass = res & 0xff;
4282 #ifdef HAVE_PRI
4284 #endif
4285 dahdi_handle_dtmfup(ast, idx, &f);
4286 return f;
4289 if (res & DAHDI_EVENT_DTMFDOWN) {
4290 ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
4291 /* Mute conference */
4292 dahdi_confmute(p, 1);
4293 p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
4294 p->subs[idx].f.subclass = res & 0xff;
4295 return &p->subs[idx].f;
4298 switch (res) {
4299 case DAHDI_EVENT_EC_DISABLED:
4300 ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
4301 p->echocanon = 0;
4302 break;
4303 case DAHDI_EVENT_BITSCHANGED:
4304 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
4305 case DAHDI_EVENT_PULSE_START:
4306 /* Stop tone if there's a pulse start and the PBX isn't started */
4307 if (!ast->pbx)
4308 tone_zone_play_tone(p->subs[idx].zfd, -1);
4309 break;
4310 case DAHDI_EVENT_DIALCOMPLETE:
4311 if (p->inalarm) break;
4312 if ((p->radio || (p->oprmode < 0))) break;
4313 if (ioctl(p->subs[idx].zfd,DAHDI_DIALING,&x) == -1) {
4314 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
4315 return NULL;
4317 if (!x) { /* if not still dialing in driver */
4318 dahdi_enable_ec(p);
4319 if (p->echobreak) {
4320 dahdi_train_ec(p);
4321 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
4322 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4323 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
4324 p->echobreak = 0;
4325 } else {
4326 p->dialing = 0;
4327 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
4328 /* if thru with dialing after offhook */
4329 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
4330 ast_setstate(ast, AST_STATE_UP);
4331 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4332 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
4333 break;
4334 } else { /* if to state wait for offhook to dial rest */
4335 /* we now wait for off hook */
4336 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
4339 if (ast->_state == AST_STATE_DIALING) {
4340 if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
4341 ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
4342 } else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
4343 ast_setstate(ast, AST_STATE_RINGING);
4344 } else if (!p->answeronpolarityswitch) {
4345 ast_setstate(ast, AST_STATE_UP);
4346 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4347 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
4348 /* If aops=0 and hops=1, this is necessary */
4349 p->polarity = POLARITY_REV;
4350 } else {
4351 /* Start clean, so we can catch the change to REV polarity when party answers */
4352 p->polarity = POLARITY_IDLE;
4357 break;
4358 case DAHDI_EVENT_ALARM:
4359 #ifdef HAVE_PRI
4360 if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
4361 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
4362 /* T309 is not enabled : hangup calls when alarm occurs */
4363 if (p->call) {
4364 if (p->pri && p->pri->pri) {
4365 if (!pri_grab(p, p->pri)) {
4366 pri_hangup(p->pri->pri, p->call, -1);
4367 pri_destroycall(p->pri->pri, p->call);
4368 p->call = NULL;
4369 pri_rel(p->pri);
4370 } else
4371 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
4372 } else
4373 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
4375 if (p->owner)
4376 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
4379 if (p->bearer)
4380 p->bearer->inalarm = 1;
4381 else
4382 #endif
4383 p->inalarm = 1;
4384 res = get_alarms(p);
4385 handle_alarms(p, res);
4386 #ifdef HAVE_PRI
4387 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
4388 /* fall through intentionally */
4389 } else {
4390 break;
4392 #endif
4393 #ifdef HAVE_SS7
4394 if (p->sig == SIG_SS7)
4395 break;
4396 #endif
4397 case DAHDI_EVENT_ONHOOK:
4398 if (p->radio) {
4399 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4400 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
4401 break;
4403 if (p->oprmode < 0)
4405 if (p->oprmode != -1) break;
4406 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4408 /* Make sure it starts ringing */
4409 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_RINGOFF);
4410 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_RING);
4411 save_conference(p->oprpeer);
4412 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
4414 break;
4416 switch (p->sig) {
4417 case SIG_FXOLS:
4418 case SIG_FXOGS:
4419 case SIG_FXOKS:
4420 p->onhooktime = time(NULL);
4421 p->msgstate = -1;
4422 /* Check for some special conditions regarding call waiting */
4423 if (idx == SUB_REAL) {
4424 /* The normal line was hung up */
4425 if (p->subs[SUB_CALLWAIT].owner) {
4426 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
4427 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
4428 ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
4429 unalloc_sub(p, SUB_CALLWAIT);
4430 #if 0
4431 p->subs[idx].needanswer = 0;
4432 p->subs[idx].needringing = 0;
4433 #endif
4434 p->callwaitingrepeat = 0;
4435 p->cidcwexpire = 0;
4436 p->owner = NULL;
4437 /* Don't start streaming audio yet if the incoming call isn't up yet */
4438 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
4439 p->dialing = 1;
4440 dahdi_ring_phone(p);
4441 } else if (p->subs[SUB_THREEWAY].owner) {
4442 unsigned int mssinceflash;
4443 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4444 the private structure -- not especially easy or clean */
4445 while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
4446 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4447 DLA_UNLOCK(&p->lock);
4448 CHANNEL_DEADLOCK_AVOIDANCE(ast);
4449 /* We can grab ast and p in that order, without worry. We should make sure
4450 nothing seriously bad has happened though like some sort of bizarre double
4451 masquerade! */
4452 DLA_LOCK(&p->lock);
4453 if (p->owner != ast) {
4454 ast_log(LOG_WARNING, "This isn't good...\n");
4455 return NULL;
4458 if (!p->subs[SUB_THREEWAY].owner) {
4459 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
4460 return NULL;
4462 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
4463 ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
4464 if (mssinceflash < MIN_MS_SINCE_FLASH) {
4465 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4466 hanging up. Hangup both channels now */
4467 if (p->subs[SUB_THREEWAY].owner)
4468 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
4469 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4470 ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
4471 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4472 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
4473 if (p->transfer) {
4474 /* In any case this isn't a threeway call anymore */
4475 p->subs[SUB_REAL].inthreeway = 0;
4476 p->subs[SUB_THREEWAY].inthreeway = 0;
4477 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4478 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
4479 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4480 /* Swap subs and dis-own channel */
4481 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4482 p->owner = NULL;
4483 /* Ring the phone */
4484 dahdi_ring_phone(p);
4485 } else {
4486 if ((res = attempt_transfer(p)) < 0) {
4487 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4488 if (p->subs[SUB_THREEWAY].owner)
4489 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4490 } else if (res) {
4491 /* Don't actually hang up at this point */
4492 if (p->subs[SUB_THREEWAY].owner)
4493 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4494 break;
4497 } else {
4498 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4499 if (p->subs[SUB_THREEWAY].owner)
4500 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4502 } else {
4503 ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
4504 /* Swap subs and dis-own channel */
4505 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4506 p->owner = NULL;
4507 /* Ring the phone */
4508 dahdi_ring_phone(p);
4511 } else {
4512 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
4514 /* Fall through */
4515 default:
4516 dahdi_disable_ec(p);
4517 return NULL;
4519 break;
4520 case DAHDI_EVENT_RINGOFFHOOK:
4521 if (p->inalarm) break;
4522 if (p->oprmode < 0)
4524 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4526 /* Make sure it stops ringing */
4527 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_RINGOFF);
4528 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].zfd, -1);
4529 restore_conference(p->oprpeer);
4531 break;
4533 if (p->radio)
4535 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4536 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
4537 break;
4539 /* for E911, its supposed to wait for offhook then dial
4540 the second half of the dial string */
4541 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
4542 c = strchr(p->dialdest, '/');
4543 if (c)
4544 c++;
4545 else
4546 c = p->dialdest;
4547 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
4548 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
4549 if (strlen(p->dop.dialstr) > 4) {
4550 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
4551 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
4552 p->echorest[sizeof(p->echorest) - 1] = '\0';
4553 p->echobreak = 1;
4554 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
4555 } else
4556 p->echobreak = 0;
4557 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop)) {
4558 int saveerr = errno;
4560 x = DAHDI_ONHOOK;
4561 ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
4562 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4563 return NULL;
4565 p->dialing = 1;
4566 return &p->subs[idx].f;
4568 switch (p->sig) {
4569 case SIG_FXOLS:
4570 case SIG_FXOGS:
4571 case SIG_FXOKS:
4572 switch (ast->_state) {
4573 case AST_STATE_RINGING:
4574 dahdi_enable_ec(p);
4575 dahdi_train_ec(p);
4576 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4577 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
4578 /* Make sure it stops ringing */
4579 dahdi_set_hook(p->subs[idx].zfd, DAHDI_OFFHOOK);
4580 ast_debug(1, "channel %d answered\n", p->channel);
4581 if (p->cidspill) {
4582 /* Cancel any running CallerID spill */
4583 ast_free(p->cidspill);
4584 p->cidspill = NULL;
4586 p->dialing = 0;
4587 p->callwaitcas = 0;
4588 if (p->confirmanswer) {
4589 /* Ignore answer if "confirm answer" is enabled */
4590 p->subs[idx].f.frametype = AST_FRAME_NULL;
4591 p->subs[idx].f.subclass = 0;
4592 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4593 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4594 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
4595 if (res < 0) {
4596 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4597 p->dop.dialstr[0] = '\0';
4598 return NULL;
4599 } else {
4600 ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4601 p->subs[idx].f.frametype = AST_FRAME_NULL;
4602 p->subs[idx].f.subclass = 0;
4603 p->dialing = 1;
4605 p->dop.dialstr[0] = '\0';
4606 ast_setstate(ast, AST_STATE_DIALING);
4607 } else
4608 ast_setstate(ast, AST_STATE_UP);
4609 return &p->subs[idx].f;
4610 case AST_STATE_DOWN:
4611 ast_setstate(ast, AST_STATE_RING);
4612 ast->rings = 1;
4613 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4614 p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
4615 ast_debug(1, "channel %d picked up\n", p->channel);
4616 return &p->subs[idx].f;
4617 case AST_STATE_UP:
4618 /* Make sure it stops ringing */
4619 dahdi_set_hook(p->subs[idx].zfd, DAHDI_OFFHOOK);
4620 /* Okay -- probably call waiting*/
4621 if (ast_bridged_channel(p->owner))
4622 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4623 p->subs[idx].needunhold = 1;
4624 break;
4625 case AST_STATE_RESERVED:
4626 /* Start up dialtone */
4627 if (has_voicemail(p))
4628 res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_STUTTER);
4629 else
4630 res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_DIALTONE);
4631 break;
4632 default:
4633 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4635 break;
4636 case SIG_FXSLS:
4637 case SIG_FXSGS:
4638 case SIG_FXSKS:
4639 if (ast->_state == AST_STATE_RING) {
4640 p->ringt = p->ringt_base;
4643 /* If we get a ring then we cannot be in
4644 * reversed polarity. So we reset to idle */
4645 ast_debug(1, "Setting IDLE polarity due "
4646 "to ring. Old polarity was %d\n",
4647 p->polarity);
4648 p->polarity = POLARITY_IDLE;
4650 /* Fall through */
4651 case SIG_EM:
4652 case SIG_EM_E1:
4653 case SIG_EMWINK:
4654 case SIG_FEATD:
4655 case SIG_FEATDMF:
4656 case SIG_FEATDMF_TA:
4657 case SIG_E911:
4658 case SIG_FGC_CAMA:
4659 case SIG_FGC_CAMAMF:
4660 case SIG_FEATB:
4661 case SIG_SF:
4662 case SIG_SFWINK:
4663 case SIG_SF_FEATD:
4664 case SIG_SF_FEATDMF:
4665 case SIG_SF_FEATB:
4666 if (ast->_state == AST_STATE_PRERING)
4667 ast_setstate(ast, AST_STATE_RING);
4668 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4669 ast_debug(1, "Ring detected\n");
4670 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4671 p->subs[idx].f.subclass = AST_CONTROL_RING;
4672 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4673 ast_debug(1, "Line answered\n");
4674 if (p->confirmanswer) {
4675 p->subs[idx].f.frametype = AST_FRAME_NULL;
4676 p->subs[idx].f.subclass = 0;
4677 } else {
4678 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
4679 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
4680 ast_setstate(ast, AST_STATE_UP);
4682 } else if (ast->_state != AST_STATE_RING)
4683 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4684 break;
4685 default:
4686 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4688 break;
4689 case DAHDI_EVENT_RINGBEGIN:
4690 switch (p->sig) {
4691 case SIG_FXSLS:
4692 case SIG_FXSGS:
4693 case SIG_FXSKS:
4694 if (ast->_state == AST_STATE_RING) {
4695 p->ringt = p->ringt_base;
4697 break;
4699 break;
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[idx].f.frametype = AST_FRAME_CONTROL;
4711 p->subs[idx].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 idx, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
4755 p->callwaitcas = 0;
4757 if (idx != SUB_REAL) {
4758 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, 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[idx].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 idx;
5077 struct ast_frame *f;
5080 idx = dahdi_get_index(ast, p, 1);
5082 p->subs[idx].f.frametype = AST_FRAME_NULL;
5083 p->subs[idx].f.datalen = 0;
5084 p->subs[idx].f.samples = 0;
5085 p->subs[idx].f.mallocd = 0;
5086 p->subs[idx].f.offset = 0;
5087 p->subs[idx].f.subclass = 0;
5088 p->subs[idx].f.delivery = ast_tv(0,0);
5089 p->subs[idx].f.src = "dahdi_exception";
5090 p->subs[idx].f.data.ptr = NULL;
5093 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
5094 /* If nobody owns us, absorb the event appropriately, otherwise
5095 we loop indefinitely. This occurs when, during call waiting, the
5096 other end hangs up our channel so that it no longer exists, but we
5097 have neither FLASH'd nor ONHOOK'd to signify our desire to
5098 change to the other channel. */
5099 if (p->fake_event) {
5100 res = p->fake_event;
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[idx].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[idx].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 idx;
5192 void *readbuf;
5193 struct ast_frame *f;
5195 while (ast_mutex_trylock(&p->lock)) {
5196 CHANNEL_DEADLOCK_AVOIDANCE(ast);
5199 idx = dahdi_get_index(ast, p, 0);
5201 /* Hang up if we don't really exist */
5202 if (idx < 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[idx].f.frametype = AST_FRAME_NULL;
5211 p->subs[idx].f.datalen = 0;
5212 p->subs[idx].f.samples = 0;
5213 p->subs[idx].f.mallocd = 0;
5214 p->subs[idx].f.offset = 0;
5215 p->subs[idx].f.subclass = 0;
5216 p->subs[idx].f.delivery = ast_tv(0,0);
5217 p->subs[idx].f.src = "dahdi_read";
5218 p->subs[idx].f.data.ptr = NULL;
5220 /* make sure it sends initial key state as first frame */
5221 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
5223 struct dahdi_params ps;
5225 ps.channo = p->channel;
5226 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps) < 0) {
5227 ast_mutex_unlock(&p->lock);
5228 return NULL;
5230 p->firstradio = 1;
5231 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5232 if (ps.rxisoffhook)
5234 p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
5236 else
5238 p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
5240 ast_mutex_unlock(&p->lock);
5241 return &p->subs[idx].f;
5243 if (p->ringt == 1) {
5244 ast_mutex_unlock(&p->lock);
5245 return NULL;
5247 else if (p->ringt > 0)
5248 p->ringt--;
5250 if (p->subs[idx].needringing) {
5251 /* Send ringing frame if requested */
5252 p->subs[idx].needringing = 0;
5253 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5254 p->subs[idx].f.subclass = AST_CONTROL_RINGING;
5255 ast_setstate(ast, AST_STATE_RINGING);
5256 ast_mutex_unlock(&p->lock);
5257 return &p->subs[idx].f;
5260 if (p->subs[idx].needbusy) {
5261 /* Send busy frame if requested */
5262 p->subs[idx].needbusy = 0;
5263 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5264 p->subs[idx].f.subclass = AST_CONTROL_BUSY;
5265 ast_mutex_unlock(&p->lock);
5266 return &p->subs[idx].f;
5269 if (p->subs[idx].needcongestion) {
5270 /* Send congestion frame if requested */
5271 p->subs[idx].needcongestion = 0;
5272 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5273 p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
5274 ast_mutex_unlock(&p->lock);
5275 return &p->subs[idx].f;
5278 if (p->subs[idx].needcallerid) {
5279 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
5280 S_OR(p->lastcid_name, NULL),
5281 S_OR(p->lastcid_num, NULL)
5283 p->subs[idx].needcallerid = 0;
5286 if (p->subs[idx].needanswer) {
5287 /* Send answer frame if requested */
5288 p->subs[idx].needanswer = 0;
5289 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5290 p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
5291 ast_mutex_unlock(&p->lock);
5292 return &p->subs[idx].f;
5295 if (p->subs[idx].needflash) {
5296 /* Send answer frame if requested */
5297 p->subs[idx].needflash = 0;
5298 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5299 p->subs[idx].f.subclass = AST_CONTROL_FLASH;
5300 ast_mutex_unlock(&p->lock);
5301 return &p->subs[idx].f;
5304 if (p->subs[idx].needhold) {
5305 /* Send answer frame if requested */
5306 p->subs[idx].needhold = 0;
5307 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5308 p->subs[idx].f.subclass = AST_CONTROL_HOLD;
5309 ast_mutex_unlock(&p->lock);
5310 ast_debug(1, "Sending hold on '%s'\n", ast->name);
5311 return &p->subs[idx].f;
5314 if (p->subs[idx].needunhold) {
5315 /* Send answer frame if requested */
5316 p->subs[idx].needunhold = 0;
5317 p->subs[idx].f.frametype = AST_FRAME_CONTROL;
5318 p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
5319 ast_mutex_unlock(&p->lock);
5320 ast_debug(1, "Sending unhold on '%s'\n", ast->name);
5321 return &p->subs[idx].f;
5324 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
5325 if (!p->subs[idx].linear) {
5326 p->subs[idx].linear = 1;
5327 res = dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].linear);
5328 if (res)
5329 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
5331 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
5332 (ast->rawreadformat == AST_FORMAT_ALAW)) {
5333 if (p->subs[idx].linear) {
5334 p->subs[idx].linear = 0;
5335 res = dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].linear);
5336 if (res)
5337 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
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[idx].buffer) + AST_FRIENDLY_OFFSET;
5345 CHECK_BLOCKING(ast);
5346 res = read(p->subs[idx].zfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
5347 ast_clear_flag(ast, AST_FLAG_BLOCKING);
5348 /* Check for hangup */
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[idx].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[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
5365 ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
5366 f = __dahdi_exception(ast);
5367 ast_mutex_unlock(&p->lock);
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[idx].f.subclass = 0;
5381 p->subs[idx].f.frametype = AST_FRAME_TEXT;
5382 p->subs[idx].f.mallocd = 0;
5383 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
5384 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
5385 p->subs[idx].f.datalen = 1;
5386 *((char *) p->subs[idx].f.data.ptr) = c;
5387 ast_mutex_unlock(&p->lock);
5388 return &p->subs[idx].f;
5391 /* Ensure the CW timer decrements only on a single subchannel */
5392 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
5393 p->callwaitingrepeat--;
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[idx].linear) {
5408 p->subs[idx].f.datalen = READ_SIZE * 2;
5409 } else
5410 p->subs[idx].f.datalen = READ_SIZE;
5412 /* Handle CallerID Transmission */
5413 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
5414 send_callerid(p);
5417 p->subs[idx].f.frametype = AST_FRAME_VOICE;
5418 p->subs[idx].f.subclass = ast->rawreadformat;
5419 p->subs[idx].f.samples = READ_SIZE;
5420 p->subs[idx].f.mallocd = 0;
5421 p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
5422 p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
5423 #if 0
5424 ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
5425 #endif
5426 if (p->dialing || /* Transmitting something */
5427 (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
5428 ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
5430 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
5431 don't send anything */
5432 p->subs[idx].f.frametype = AST_FRAME_NULL;
5433 p->subs[idx].f.subclass = 0;
5434 p->subs[idx].f.samples = 0;
5435 p->subs[idx].f.mallocd = 0;
5436 p->subs[idx].f.offset = 0;
5437 p->subs[idx].f.data.ptr = NULL;
5438 p->subs[idx].f.datalen= 0;
5440 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !idx) {
5441 /* Perform busy detection. etc on the dahdi line */
5442 int mute;
5444 f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
5446 /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
5447 mute = ast_dsp_was_muted(p->dsp);
5448 if (p->muting != mute) {
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[idx].f;
5477 if (f && (f->frametype == AST_FRAME_DTMF))
5478 dahdi_handle_dtmfup(ast, idx, &f);
5480 /* If we have a fake_event, trigger exception to handle it */
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 idx, int linear)
5490 int sent=0;
5491 int size;
5492 int res;
5493 int fd;
5494 fd = p->subs[idx].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 idx;
5515 idx = dahdi_get_index(ast, p, 0);
5516 if (idx < 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[idx].linear) {
5567 p->subs[idx].linear = 1;
5568 res = dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].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, idx, 1);
5573 } else {
5574 /* x-law already */
5575 if (p->subs[idx].linear) {
5576 p->subs[idx].linear = 0;
5577 res = dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].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, idx, 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 idx;
5595 int func = DAHDI_FLASH;
5596 ast_mutex_lock(&p->lock);
5597 idx = dahdi_get_index(chan, p, 0);
5598 ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
5599 if (idx == SUB_REAL) {
5600 switch (condition) {
5601 case AST_CONTROL_BUSY:
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[idx].zfd, DAHDI_TONE_BUSY);
5620 } else
5621 #endif
5622 res = tone_zone_play_tone(p->subs[idx].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[idx].zfd, DAHDI_TONE_RINGTONE);
5657 if (chan->_state != AST_STATE_UP) {
5658 if ((chan->_state != AST_STATE_RING) ||
5659 ((p->sig != SIG_FXSKS) &&
5660 (p->sig != SIG_FXSLS) &&
5661 (p->sig != SIG_FXSGS)))
5662 ast_setstate(chan, AST_STATE_RINGING);
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[idx].zfd, DAHDI_TONE_CONGESTION);
5752 } else
5753 #endif
5754 res = tone_zone_play_tone(p->subs[idx].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[idx].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[idx].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[idx].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 idx, 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 struct dahdi_params ps;
5826 if (i->subs[idx].owner) {
5827 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
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 ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
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[idx].zfd);
5869 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5870 /* Start out assuming ulaw since it's smaller :) */
5871 tmp->rawreadformat = deflaw;
5872 tmp->readformat = deflaw;
5873 tmp->rawwriteformat = deflaw;
5874 tmp->writeformat = deflaw;
5875 i->subs[idx].linear = 0;
5876 dahdi_setlinear(i->subs[idx].zfd, i->subs[idx].linear);
5877 features = 0;
5878 if (idx == SUB_REAL) {
5879 if (i->busydetect && CANBUSYDETECT(i))
5880 features |= DSP_FEATURE_BUSY_DETECT;
5881 if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
5882 features |= DSP_FEATURE_CALL_PROGRESS;
5883 if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
5884 (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
5885 features |= DSP_FEATURE_FAX_DETECT;
5887 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5888 if (ioctl(i->subs[idx].zfd, DAHDI_TONEDETECT, &x)) {
5889 i->hardwaredtmf = 0;
5890 features |= DSP_FEATURE_DIGIT_DETECT;
5891 } else if (NEED_MFDETECT(i)) {
5892 i->hardwaredtmf = 1;
5893 features |= DSP_FEATURE_DIGIT_DETECT;
5896 if (features) {
5897 if (i->dsp) {
5898 ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
5899 } else {
5900 if (i->channel != CHAN_PSEUDO)
5901 i->dsp = ast_dsp_new();
5902 else
5903 i->dsp = NULL;
5904 if (i->dsp) {
5905 i->dsp_features = features;
5906 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5907 /* We cannot do progress detection until receives PROGRESS message */
5908 if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
5909 /* Remember requested DSP features, don't treat
5910 talking as ANSWER */
5911 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5912 features = 0;
5914 #endif
5915 ast_dsp_set_features(i->dsp, features);
5916 ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5917 if (!ast_strlen_zero(progzone))
5918 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5919 if (i->busydetect && CANBUSYDETECT(i)) {
5920 ast_dsp_set_busy_count(i->dsp, i->busycount);
5921 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5927 if (state == AST_STATE_RING)
5928 tmp->rings = 1;
5929 tmp->tech_pvt = i;
5930 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5931 /* Only FXO signalled stuff can be picked up */
5932 tmp->callgroup = i->callgroup;
5933 tmp->pickupgroup = i->pickupgroup;
5935 if (!ast_strlen_zero(i->parkinglot))
5936 ast_string_field_set(tmp, parkinglot, i->parkinglot);
5937 if (!ast_strlen_zero(i->language))
5938 ast_string_field_set(tmp, language, i->language);
5939 if (!i->owner)
5940 i->owner = tmp;
5941 if (!ast_strlen_zero(i->accountcode))
5942 ast_string_field_set(tmp, accountcode, i->accountcode);
5943 if (i->amaflags)
5944 tmp->amaflags = i->amaflags;
5945 i->subs[idx].owner = tmp;
5946 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5947 ast_string_field_set(tmp, call_forward, i->call_forward);
5948 /* If we've been told "no ADSI" then enforce it */
5949 if (!i->adsi)
5950 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5951 if (!ast_strlen_zero(i->exten))
5952 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5953 if (!ast_strlen_zero(i->rdnis))
5954 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5955 if (!ast_strlen_zero(i->dnid))
5956 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5958 /* Don't use ast_set_callerid() here because it will
5959 * generate a needless NewCallerID event */
5960 #ifdef PRI_ANI
5961 if (!ast_strlen_zero(i->cid_ani))
5962 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5963 else
5964 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5965 #else
5966 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5967 #endif
5968 tmp->cid.cid_pres = i->callingpres;
5969 tmp->cid.cid_ton = i->cid_ton;
5970 tmp->cid.cid_ani2 = i->cid_ani2;
5971 #if defined(HAVE_PRI) || defined(HAVE_SS7)
5972 tmp->transfercapability = transfercapability;
5973 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5974 if (transfercapability & AST_TRANS_CAP_DIGITAL)
5975 i->digital = 1;
5976 /* Assume calls are not idle calls unless we're told differently */
5977 i->isidlecall = 0;
5978 i->alreadyhungup = 0;
5979 #endif
5980 /* clear the fake event in case we posted one before we had ast_channel */
5981 i->fake_event = 0;
5982 /* Assure there is no confmute on this channel */
5983 dahdi_confmute(i, 0);
5984 i->muting = 0;
5985 /* Configure the new channel jb */
5986 ast_jb_configure(tmp, &global_jbconf);
5988 ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
5990 for (v = i->vars ; v ; v = v->next)
5991 pbx_builtin_setvar_helper(tmp, v->name, v->value);
5993 if (startpbx) {
5994 if (ast_pbx_start(tmp)) {
5995 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5996 ast_hangup(tmp);
5997 i->owner = NULL;
5998 return NULL;
6002 ast_module_ref(ast_module_info->self);
6003 return tmp;
6007 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
6009 char c;
6011 *str = 0; /* start with empty output buffer */
6012 for (;;)
6014 /* Wait for the first digit (up to specified ms). */
6015 c = ast_waitfordigit(chan, ms);
6016 /* if timeout, hangup or error, return as such */
6017 if (c < 1)
6018 return c;
6019 *str++ = c;
6020 *str = 0;
6021 if (strchr(term, c))
6022 return 1;
6026 static int dahdi_wink(struct dahdi_pvt *p, int idx)
6028 int j;
6029 dahdi_set_hook(p->subs[idx].zfd, DAHDI_WINK);
6030 for (;;)
6032 /* set bits of interest */
6033 j = DAHDI_IOMUX_SIGEVENT;
6034 /* wait for some happening */
6035 if (ioctl(p->subs[idx].zfd,DAHDI_IOMUX,&j) == -1) return(-1);
6036 /* exit loop if we have it */
6037 if (j & DAHDI_IOMUX_SIGEVENT) break;
6039 /* get the event info */
6040 if (ioctl(p->subs[idx].zfd,DAHDI_GETEVENT,&j) == -1) return(-1);
6041 return 0;
6044 /*! \brief enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
6045 * \param dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
6046 * \param on 1 to enable, 0 to disable
6048 * chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical
6049 * DAHDI channel). Use this to enable or disable it.
6051 * \bug the use of the word "channel" for those dahdichans is really confusing.
6053 static void dahdi_dnd(struct dahdi_pvt *dahdichan, int on)
6055 /* Do not disturb */
6056 dahdichan->dnd = on;
6057 ast_verb(3, "%s DND on channel %d\n",
6058 on? "Enabled" : "Disabled",
6059 dahdichan->channel);
6060 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6061 "Channel: DAHDI/%d\r\n"
6062 "Status: %s\r\n", dahdichan->channel,
6063 on? "enabled" : "disabled");
6066 static void *ss_thread(void *data)
6068 struct ast_channel *chan = data;
6069 struct dahdi_pvt *p = chan->tech_pvt;
6070 char exten[AST_MAX_EXTENSION] = "";
6071 char exten2[AST_MAX_EXTENSION] = "";
6072 unsigned char buf[256];
6073 char dtmfcid[300];
6074 char dtmfbuf[300];
6075 struct callerid_state *cs = NULL;
6076 char *name = NULL, *number = NULL;
6077 int distMatches;
6078 int curRingData[3];
6079 int receivedRingT;
6080 int counter1;
6081 int counter;
6082 int samples = 0;
6083 struct ast_smdi_md_message *smdi_msg = NULL;
6084 int flags;
6085 int i;
6086 int timeout;
6087 int getforward = 0;
6088 char *s1, *s2;
6089 int len = 0;
6090 int res;
6091 int idx;
6093 /* in the bizarre case where the channel has become a zombie before we
6094 even get started here, abort safely
6096 if (!p) {
6097 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
6098 ast_hangup(chan);
6099 return NULL;
6102 ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
6103 idx = dahdi_get_index(chan, p, 1);
6104 if (idx < 0) {
6105 ast_log(LOG_WARNING, "Huh?\n");
6106 ast_hangup(chan);
6107 return NULL;
6109 if (p->dsp)
6110 ast_dsp_digitreset(p->dsp);
6111 switch (p->sig) {
6112 #ifdef HAVE_PRI
6113 case SIG_PRI:
6114 case SIG_BRI:
6115 case SIG_BRI_PTMP:
6116 /* Now loop looking for an extension */
6117 ast_copy_string(exten, p->exten, sizeof(exten));
6118 len = strlen(exten);
6119 res = 0;
6120 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
6121 if (len && !ast_ignore_pattern(chan->context, exten))
6122 tone_zone_play_tone(p->subs[idx].zfd, -1);
6123 else
6124 tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALTONE);
6125 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
6126 timeout = matchdigittimeout;
6127 else
6128 timeout = gendigittimeout;
6129 res = ast_waitfordigit(chan, timeout);
6130 if (res < 0) {
6131 ast_debug(1, "waitfordigit returned < 0...\n");
6132 ast_hangup(chan);
6133 return NULL;
6134 } else if (res) {
6135 exten[len++] = res;
6136 exten[len] = '\0';
6137 } else
6138 break;
6140 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
6141 if (ast_strlen_zero(exten)) {
6142 ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
6143 exten[0] = 's';
6144 exten[1] = '\0';
6146 tone_zone_play_tone(p->subs[idx].zfd, -1);
6147 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
6148 /* Start the real PBX */
6149 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6150 if (p->dsp) ast_dsp_digitreset(p->dsp);
6151 dahdi_enable_ec(p);
6152 ast_setstate(chan, AST_STATE_RING);
6153 res = ast_pbx_run(chan);
6154 if (res) {
6155 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
6157 } else {
6158 ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
6159 chan->hangupcause = AST_CAUSE_UNALLOCATED;
6160 ast_hangup(chan);
6161 p->exten[0] = '\0';
6162 /* Since we send release complete here, we won't get one */
6163 p->call = NULL;
6165 return NULL;
6166 break;
6167 #endif
6168 case SIG_FEATD:
6169 case SIG_FEATDMF:
6170 case SIG_FEATDMF_TA:
6171 case SIG_E911:
6172 case SIG_FGC_CAMAMF:
6173 case SIG_FEATB:
6174 case SIG_EMWINK:
6175 case SIG_SF_FEATD:
6176 case SIG_SF_FEATDMF:
6177 case SIG_SF_FEATB:
6178 case SIG_SFWINK:
6179 if (dahdi_wink(p, idx))
6180 return NULL;
6181 /* Fall through */
6182 case SIG_EM:
6183 case SIG_EM_E1:
6184 case SIG_SF:
6185 case SIG_FGC_CAMA:
6186 res = tone_zone_play_tone(p->subs[idx].zfd, -1);
6187 if (p->dsp)
6188 ast_dsp_digitreset(p->dsp);
6189 /* set digit mode appropriately */
6190 if (p->dsp) {
6191 if (NEED_MFDETECT(p))
6192 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
6193 else
6194 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6196 memset(dtmfbuf, 0, sizeof(dtmfbuf));
6197 /* Wait for the first digit only if immediate=no */
6198 if (!p->immediate)
6199 /* Wait for the first digit (up to 5 seconds). */
6200 res = ast_waitfordigit(chan, 5000);
6201 else
6202 res = 0;
6203 if (res > 0) {
6204 /* save first char */
6205 dtmfbuf[0] = res;
6206 switch (p->sig) {
6207 case SIG_FEATD:
6208 case SIG_SF_FEATD:
6209 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
6210 if (res > 0)
6211 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
6212 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6213 break;
6214 case SIG_FEATDMF_TA:
6215 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6216 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6217 if (dahdi_wink(p, idx)) return NULL;
6218 dtmfbuf[0] = 0;
6219 /* Wait for the first digit (up to 5 seconds). */
6220 res = ast_waitfordigit(chan, 5000);
6221 if (res <= 0) break;
6222 dtmfbuf[0] = res;
6223 /* fall through intentionally */
6224 case SIG_FEATDMF:
6225 case SIG_E911:
6226 case SIG_FGC_CAMAMF:
6227 case SIG_SF_FEATDMF:
6228 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6229 /* if international caca, do it again to get real ANO */
6230 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
6232 if (dahdi_wink(p, idx)) return NULL;
6233 dtmfbuf[0] = 0;
6234 /* Wait for the first digit (up to 5 seconds). */
6235 res = ast_waitfordigit(chan, 5000);
6236 if (res <= 0) break;
6237 dtmfbuf[0] = res;
6238 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6240 if (res > 0) {
6241 /* if E911, take off hook */
6242 if (p->sig == SIG_E911)
6243 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
6244 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
6246 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6247 break;
6248 case SIG_FEATB:
6249 case SIG_SF_FEATB:
6250 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
6251 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6252 break;
6253 case SIG_EMWINK:
6254 /* if we received a '*', we are actually receiving Feature Group D
6255 dial syntax, so use that mode; otherwise, fall through to normal
6256 mode
6258 if (res == '*') {
6259 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
6260 if (res > 0)
6261 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
6262 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
6263 break;
6265 default:
6266 /* If we got the first digit, get the rest */
6267 len = 1;
6268 dtmfbuf[len] = '\0';
6269 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
6270 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
6271 timeout = matchdigittimeout;
6272 } else {
6273 timeout = gendigittimeout;
6275 res = ast_waitfordigit(chan, timeout);
6276 if (res < 0) {
6277 ast_debug(1, "waitfordigit returned < 0...\n");
6278 ast_hangup(chan);
6279 return NULL;
6280 } else if (res) {
6281 dtmfbuf[len++] = res;
6282 dtmfbuf[len] = '\0';
6283 } else {
6284 break;
6287 break;
6290 if (res == -1) {
6291 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
6292 ast_hangup(chan);
6293 return NULL;
6294 } else if (res < 0) {
6295 ast_debug(1, "Got hung up before digits finished\n");
6296 ast_hangup(chan);
6297 return NULL;
6300 if (p->sig == SIG_FGC_CAMA) {
6301 char anibuf[100];
6303 if (ast_safe_sleep(chan,1000) == -1) {
6304 ast_hangup(chan);
6305 return NULL;
6307 dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
6308 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
6309 res = my_getsigstr(chan, anibuf, "#", 10000);
6310 if ((res > 0) && (strlen(anibuf) > 2)) {
6311 if (anibuf[strlen(anibuf) - 1] == '#')
6312 anibuf[strlen(anibuf) - 1] = 0;
6313 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
6315 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6318 ast_copy_string(exten, dtmfbuf, sizeof(exten));
6319 if (ast_strlen_zero(exten))
6320 ast_copy_string(exten, "s", sizeof(exten));
6321 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
6322 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
6323 if (exten[0] == '*') {
6324 char *stringp=NULL;
6325 ast_copy_string(exten2, exten, sizeof(exten2));
6326 /* Parse out extension and callerid */
6327 stringp=exten2 +1;
6328 s1 = strsep(&stringp, "*");
6329 s2 = strsep(&stringp, "*");
6330 if (s2) {
6331 if (!ast_strlen_zero(p->cid_num))
6332 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6333 else
6334 ast_set_callerid(chan, s1, NULL, s1);
6335 ast_copy_string(exten, s2, sizeof(exten));
6336 } else
6337 ast_copy_string(exten, s1, sizeof(exten));
6338 } else if (p->sig == SIG_FEATD)
6339 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
6341 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
6342 if (exten[0] == '*') {
6343 char *stringp=NULL;
6344 ast_copy_string(exten2, exten, sizeof(exten2));
6345 /* Parse out extension and callerid */
6346 stringp=exten2 +1;
6347 s1 = strsep(&stringp, "#");
6348 s2 = strsep(&stringp, "#");
6349 if (s2) {
6350 if (!ast_strlen_zero(p->cid_num))
6351 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6352 else
6353 if (*(s1 + 2))
6354 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
6355 ast_copy_string(exten, s2 + 1, sizeof(exten));
6356 } else
6357 ast_copy_string(exten, s1 + 2, sizeof(exten));
6358 } else
6359 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
6361 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
6362 if (exten[0] == '*') {
6363 char *stringp=NULL;
6364 ast_copy_string(exten2, exten, sizeof(exten2));
6365 /* Parse out extension and callerid */
6366 stringp=exten2 +1;
6367 s1 = strsep(&stringp, "#");
6368 s2 = strsep(&stringp, "#");
6369 if (s2 && (*(s2 + 1) == '0')) {
6370 if (*(s2 + 2))
6371 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
6373 if (s1) ast_copy_string(exten, s1, sizeof(exten));
6374 else ast_copy_string(exten, "911", sizeof(exten));
6375 } else
6376 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
6378 if (p->sig == SIG_FEATB) {
6379 if (exten[0] == '*') {
6380 char *stringp=NULL;
6381 ast_copy_string(exten2, exten, sizeof(exten2));
6382 /* Parse out extension and callerid */
6383 stringp=exten2 +1;
6384 s1 = strsep(&stringp, "#");
6385 ast_copy_string(exten, exten2 + 1, sizeof(exten));
6386 } else
6387 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
6389 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
6390 dahdi_wink(p, idx);
6391 /* some switches require a minimum guard time between
6392 the last FGD wink and something that answers
6393 immediately. This ensures it */
6394 if (ast_safe_sleep(chan,100)) return NULL;
6396 dahdi_enable_ec(p);
6397 if (NEED_MFDETECT(p)) {
6398 if (p->dsp) {
6399 if (!p->hardwaredtmf)
6400 ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
6401 else {
6402 ast_dsp_free(p->dsp);
6403 p->dsp = NULL;
6408 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
6409 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6410 if (p->dsp) ast_dsp_digitreset(p->dsp);
6411 res = ast_pbx_run(chan);
6412 if (res) {
6413 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6414 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
6416 return NULL;
6417 } else {
6418 ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
6419 sleep(2);
6420 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_INFO);
6421 if (res < 0)
6422 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
6423 else
6424 sleep(1);
6425 res = ast_streamfile(chan, "ss-noservice", chan->language);
6426 if (res >= 0)
6427 ast_waitstream(chan, "");
6428 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
6429 ast_hangup(chan);
6430 return NULL;
6432 break;
6433 case SIG_FXOLS:
6434 case SIG_FXOGS:
6435 case SIG_FXOKS:
6436 /* Read the first digit */
6437 timeout = firstdigittimeout;
6438 /* If starting a threeway call, never timeout on the first digit so someone
6439 can use flash-hook as a "hold" feature */
6440 if (p->subs[SUB_THREEWAY].owner)
6441 timeout = 999999;
6442 while (len < AST_MAX_EXTENSION-1) {
6443 /* Read digit unless it's supposed to be immediate, in which case the
6444 only answer is 's' */
6445 if (p->immediate)
6446 res = 's';
6447 else
6448 res = ast_waitfordigit(chan, timeout);
6449 timeout = 0;
6450 if (res < 0) {
6451 ast_debug(1, "waitfordigit returned < 0...\n");
6452 res = tone_zone_play_tone(p->subs[idx].zfd, -1);
6453 ast_hangup(chan);
6454 return NULL;
6455 } else if (res) {
6456 ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
6457 exten[len++]=res;
6458 exten[len] = '\0';
6460 if (!ast_ignore_pattern(chan->context, exten))
6461 tone_zone_play_tone(p->subs[idx].zfd, -1);
6462 else
6463 tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALTONE);
6464 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
6465 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
6466 if (getforward) {
6467 /* Record this as the forwarding extension */
6468 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
6469 ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
6470 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6471 if (res)
6472 break;
6473 usleep(500000);
6474 res = tone_zone_play_tone(p->subs[idx].zfd, -1);
6475 sleep(1);
6476 memset(exten, 0, sizeof(exten));
6477 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALTONE);
6478 len = 0;
6479 getforward = 0;
6480 } else {
6481 res = tone_zone_play_tone(p->subs[idx].zfd, -1);
6482 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6483 if (!ast_strlen_zero(p->cid_num)) {
6484 if (!p->hidecallerid)
6485 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6486 else
6487 ast_set_callerid(chan, NULL, NULL, p->cid_num);
6489 if (!ast_strlen_zero(p->cid_name)) {
6490 if (!p->hidecallerid)
6491 ast_set_callerid(chan, NULL, p->cid_name, NULL);
6493 ast_setstate(chan, AST_STATE_RING);
6494 dahdi_enable_ec(p);
6495 res = ast_pbx_run(chan);
6496 if (res) {
6497 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6498 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
6500 return NULL;
6502 } else {
6503 /* It's a match, but they just typed a digit, and there is an ambiguous match,
6504 so just set the timeout to matchdigittimeout and wait some more */
6505 timeout = matchdigittimeout;
6507 } else if (res == 0) {
6508 ast_debug(1, "not enough digits (and no ambiguous match)...\n");
6509 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
6510 dahdi_wait_event(p->subs[idx].zfd);
6511 ast_hangup(chan);
6512 return NULL;
6513 } else if (p->callwaiting && !strcmp(exten, "*70")) {
6514 ast_verb(3, "Disabling call waiting on %s\n", chan->name);
6515 /* Disable call waiting if enabled */
6516 p->callwaiting = 0;
6517 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6518 if (res) {
6519 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6520 chan->name, strerror(errno));
6522 len = 0;
6523 ioctl(p->subs[idx].zfd,DAHDI_CONFDIAG,&len);
6524 memset(exten, 0, sizeof(exten));
6525 timeout = firstdigittimeout;
6527 } else if (!strcmp(exten,ast_pickup_ext())) {
6528 /* Scan all channels and see if there are any
6529 * ringing channels that have call groups
6530 * that equal this channels pickup group
6532 if (idx == SUB_REAL) {
6533 /* Switch us from Third call to Call Wait */
6534 if (p->subs[SUB_THREEWAY].owner) {
6535 /* If you make a threeway call and the *8# a call, it should actually
6536 look like a callwait */
6537 alloc_sub(p, SUB_CALLWAIT);
6538 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6539 unalloc_sub(p, SUB_THREEWAY);
6541 dahdi_enable_ec(p);
6542 if (ast_pickup_call(chan)) {
6543 ast_debug(1, "No call pickup possible...\n");
6544 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
6545 dahdi_wait_event(p->subs[idx].zfd);
6547 ast_hangup(chan);
6548 return NULL;
6549 } else {
6550 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
6551 ast_hangup(chan);
6552 return NULL;
6555 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
6556 ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
6557 /* Disable Caller*ID if enabled */
6558 p->hidecallerid = 1;
6559 if (chan->cid.cid_num)
6560 ast_free(chan->cid.cid_num);
6561 chan->cid.cid_num = NULL;
6562 if (chan->cid.cid_name)
6563 ast_free(chan->cid.cid_name);
6564 chan->cid.cid_name = NULL;
6565 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6566 if (res) {
6567 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6568 chan->name, strerror(errno));
6570 len = 0;
6571 memset(exten, 0, sizeof(exten));
6572 timeout = firstdigittimeout;
6573 } else if (p->callreturn && !strcmp(exten, "*69")) {
6574 res = 0;
6575 if (!ast_strlen_zero(p->lastcid_num)) {
6576 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
6578 if (!res)
6579 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6580 break;
6581 } else if (!strcmp(exten, "*78")) {
6582 dahdi_dnd(p, 1);
6583 /* Do not disturb */
6584 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6585 getforward = 0;
6586 memset(exten, 0, sizeof(exten));
6587 len = 0;
6588 } else if (!strcmp(exten, "*79")) {
6589 dahdi_dnd(p, 0);
6590 /* Do not disturb */
6591 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6592 getforward = 0;
6593 memset(exten, 0, sizeof(exten));
6594 len = 0;
6595 } else if (p->cancallforward && !strcmp(exten, "*72")) {
6596 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6597 getforward = 1;
6598 memset(exten, 0, sizeof(exten));
6599 len = 0;
6600 } else if (p->cancallforward && !strcmp(exten, "*73")) {
6601 ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
6602 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6603 memset(p->call_forward, 0, sizeof(p->call_forward));
6604 getforward = 0;
6605 memset(exten, 0, sizeof(exten));
6606 len = 0;
6607 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
6608 p->subs[SUB_THREEWAY].owner &&
6609 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6610 /* This is a three way call, the main call being a real channel,
6611 and we're parking the first call. */
6612 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
6613 ast_verb(3, "Parking call to '%s'\n", chan->name);
6614 break;
6615 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
6616 ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
6617 res = ast_db_put("blacklist", p->lastcid_num, "1");
6618 if (!res) {
6619 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6620 memset(exten, 0, sizeof(exten));
6621 len = 0;
6623 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6624 ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
6625 /* Enable Caller*ID if enabled */
6626 p->hidecallerid = 0;
6627 if (chan->cid.cid_num)
6628 ast_free(chan->cid.cid_num);
6629 chan->cid.cid_num = NULL;
6630 if (chan->cid.cid_name)
6631 ast_free(chan->cid.cid_name);
6632 chan->cid.cid_name = NULL;
6633 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6634 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_DIALRECALL);
6635 if (res) {
6636 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6637 chan->name, strerror(errno));
6639 len = 0;
6640 memset(exten, 0, sizeof(exten));
6641 timeout = firstdigittimeout;
6642 } else if (!strcmp(exten, "*0")) {
6643 struct ast_channel *nbridge =
6644 p->subs[SUB_THREEWAY].owner;
6645 struct dahdi_pvt *pbridge = NULL;
6646 /* set up the private struct of the bridged one, if any */
6647 if (nbridge && ast_bridged_channel(nbridge))
6648 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6649 if (nbridge && pbridge &&
6650 (nbridge->tech == &dahdi_tech) &&
6651 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
6652 ISTRUNK(pbridge)) {
6653 int func = DAHDI_FLASH;
6654 /* Clear out the dial buffer */
6655 p->dop.dialstr[0] = '\0';
6656 /* flash hookswitch */
6657 if ((ioctl(pbridge->subs[SUB_REAL].zfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6658 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6659 nbridge->name, strerror(errno));
6661 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6662 unalloc_sub(p, SUB_THREEWAY);
6663 p->owner = p->subs[SUB_REAL].owner;
6664 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6665 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6666 ast_hangup(chan);
6667 return NULL;
6668 } else {
6669 tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
6670 dahdi_wait_event(p->subs[idx].zfd);
6671 tone_zone_play_tone(p->subs[idx].zfd, -1);
6672 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6673 unalloc_sub(p, SUB_THREEWAY);
6674 p->owner = p->subs[SUB_REAL].owner;
6675 ast_hangup(chan);
6676 return NULL;
6678 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6679 ((exten[0] != '*') || (strlen(exten) > 2))) {
6680 ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
6681 break;
6683 if (!timeout)
6684 timeout = gendigittimeout;
6685 if (len && !ast_ignore_pattern(chan->context, exten))
6686 tone_zone_play_tone(p->subs[idx].zfd, -1);
6688 break;
6689 case SIG_FXSLS:
6690 case SIG_FXSGS:
6691 case SIG_FXSKS:
6692 #ifdef HAVE_PRI
6693 if (p->pri) {
6694 /* This is a GR-303 trunk actually. Wait for the first ring... */
6695 struct ast_frame *f;
6696 int res;
6697 time_t start;
6699 time(&start);
6700 ast_setstate(chan, AST_STATE_RING);
6701 while (time(NULL) < start + 3) {
6702 res = ast_waitfor(chan, 1000);
6703 if (res) {
6704 f = ast_read(chan);
6705 if (!f) {
6706 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6707 ast_hangup(chan);
6708 return NULL;
6709 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6710 res = 1;
6711 } else
6712 res = 0;
6713 ast_frfree(f);
6714 if (res) {
6715 ast_debug(1, "Got ring!\n");
6716 res = 0;
6717 break;
6722 #endif
6723 /* check for SMDI messages */
6724 if (p->use_smdi && p->smdi_iface) {
6725 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6727 if (smdi_msg != NULL) {
6728 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6730 if (smdi_msg->type == 'B')
6731 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6732 else if (smdi_msg->type == 'N')
6733 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6735 ast_debug(1, "Recieved SMDI message on %s\n", chan->name);
6736 } else {
6737 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6741 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6742 number = smdi_msg->calling_st;
6744 /* If we want caller id, we're in a prering state due to a polarity reversal
6745 * and we're set to use a polarity reversal to trigger the start of caller id,
6746 * grab the caller id and wait for ringing to start... */
6747 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
6748 /* If set to use DTMF CID signalling, listen for DTMF */
6749 if (p->cid_signalling == CID_SIG_DTMF) {
6750 int k = 0;
6751 cs = NULL;
6752 ast_debug(1, "Receiving DTMF cid on "
6753 "channel %s\n", chan->name);
6754 dahdi_setlinear(p->subs[idx].zfd, 0);
6755 res = 2000;
6756 for (;;) {
6757 struct ast_frame *f;
6758 res = ast_waitfor(chan, res);
6759 if (res <= 0) {
6760 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6761 "Exiting simple switch\n");
6762 ast_hangup(chan);
6763 return NULL;
6765 f = ast_read(chan);
6766 if (!f)
6767 break;
6768 if (f->frametype == AST_FRAME_DTMF) {
6769 dtmfbuf[k++] = f->subclass;
6770 ast_debug(1, "CID got digit '%c'\n", f->subclass);
6771 res = 2000;
6773 ast_frfree(f);
6774 if (chan->_state == AST_STATE_RING ||
6775 chan->_state == AST_STATE_RINGING)
6776 break; /* Got ring */
6778 dtmfbuf[k] = '\0';
6779 dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].linear);
6780 /* Got cid and ring. */
6781 ast_debug(1, "CID got string '%s'\n", dtmfbuf);
6782 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6783 ast_debug(1, "CID is '%s', flags %d\n",
6784 dtmfcid, flags);
6785 /* If first byte is NULL, we have no cid */
6786 if (!ast_strlen_zero(dtmfcid))
6787 number = dtmfcid;
6788 else
6789 number = NULL;
6790 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6791 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6792 cs = callerid_new(p->cid_signalling);
6793 if (cs) {
6794 samples = 0;
6795 #if 1
6796 bump_gains(p);
6797 #endif
6798 /* Take out of linear mode for Caller*ID processing */
6799 dahdi_setlinear(p->subs[idx].zfd, 0);
6801 /* First we wait and listen for the Caller*ID */
6802 for (;;) {
6803 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6804 if ((res = ioctl(p->subs[idx].zfd, DAHDI_IOMUX, &i))) {
6805 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6806 callerid_free(cs);
6807 ast_hangup(chan);
6808 return NULL;
6810 if (i & DAHDI_IOMUX_SIGEVENT) {
6811 res = dahdi_get_event(p->subs[idx].zfd);
6812 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6814 if (p->cid_signalling == CID_SIG_V23_JP) {
6815 if (res == DAHDI_EVENT_RINGBEGIN) {
6816 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
6817 usleep(1);
6819 } else {
6820 res = 0;
6821 break;
6823 } else if (i & DAHDI_IOMUX_READ) {
6824 res = read(p->subs[idx].zfd, buf, sizeof(buf));
6825 if (res < 0) {
6826 if (errno != ELAST) {
6827 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6828 callerid_free(cs);
6829 ast_hangup(chan);
6830 return NULL;
6832 break;
6834 samples += res;
6836 if (p->cid_signalling == CID_SIG_V23_JP) {
6837 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6838 } else {
6839 res = callerid_feed(cs, buf, res, AST_LAW(p));
6842 if (res < 0) {
6843 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6844 break;
6845 } else if (res)
6846 break;
6847 else if (samples > (8000 * 10))
6848 break;
6851 if (res == 1) {
6852 callerid_get(cs, &name, &number, &flags);
6853 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6856 if (p->cid_signalling == CID_SIG_V23_JP) {
6857 res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
6858 usleep(1);
6859 res = 4000;
6860 } else {
6862 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6863 res = 2000;
6866 for (;;) {
6867 struct ast_frame *f;
6868 res = ast_waitfor(chan, res);
6869 if (res <= 0) {
6870 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6871 "Exiting simple switch\n");
6872 ast_hangup(chan);
6873 return NULL;
6875 if (!(f = ast_read(chan))) {
6876 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6877 ast_hangup(chan);
6878 return NULL;
6880 ast_frfree(f);
6881 if (chan->_state == AST_STATE_RING ||
6882 chan->_state == AST_STATE_RINGING)
6883 break; /* Got ring */
6886 /* We must have a ring by now, so, if configured, lets try to listen for
6887 * distinctive ringing */
6888 if (p->usedistinctiveringdetection == 1) {
6889 len = 0;
6890 distMatches = 0;
6891 /* Clear the current ring data array so we dont have old data in it. */
6892 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
6893 curRingData[receivedRingT] = 0;
6894 receivedRingT = 0;
6895 counter = 0;
6896 counter1 = 0;
6897 /* Check to see if context is what it should be, if not set to be. */
6898 if (strcmp(p->context,p->defcontext) != 0) {
6899 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6900 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6903 for (;;) {
6904 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6905 if ((res = ioctl(p->subs[idx].zfd, DAHDI_IOMUX, &i))) {
6906 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6907 callerid_free(cs);
6908 ast_hangup(chan);
6909 return NULL;
6911 if (i & DAHDI_IOMUX_SIGEVENT) {
6912 res = dahdi_get_event(p->subs[idx].zfd);
6913 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6914 res = 0;
6915 /* Let us detect distinctive ring */
6917 curRingData[receivedRingT] = p->ringt;
6919 if (p->ringt < p->ringt_base/2)
6920 break;
6921 /* Increment the ringT counter so we can match it against
6922 values in chan_dahdi.conf for distinctive ring */
6923 if (++receivedRingT == ARRAY_LEN(curRingData))
6924 break;
6925 } else if (i & DAHDI_IOMUX_READ) {
6926 res = read(p->subs[idx].zfd, buf, sizeof(buf));
6927 if (res < 0) {
6928 if (errno != ELAST) {
6929 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6930 callerid_free(cs);
6931 ast_hangup(chan);
6932 return NULL;
6934 break;
6936 if (p->ringt)
6937 p->ringt--;
6938 if (p->ringt == 1) {
6939 res = -1;
6940 break;
6944 /* this only shows up if you have n of the dring patterns filled in */
6945 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6946 for (counter = 0; counter < 3; counter++) {
6947 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6948 channel */
6949 distMatches = 0;
6950 for (counter1 = 0; counter1 < 3; counter1++) {
6951 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
6952 if (p->drings.ringnum[counter].ring[counter1] == -1) {
6953 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
6954 curRingData[counter1]);
6955 distMatches++;
6957 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
6958 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
6959 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
6960 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
6961 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
6962 distMatches++;
6966 if (distMatches == 3) {
6967 /* The ring matches, set the context to whatever is for distinctive ring.. */
6968 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6969 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6970 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
6971 break;
6975 /* Restore linear mode (if appropriate) for Caller*ID processing */
6976 dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].linear);
6977 #if 1
6978 restore_gains(p);
6979 #endif
6980 } else
6981 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6982 } else {
6983 ast_log(LOG_WARNING, "Channel %s in prering "
6984 "state, but I have nothing to do. "
6985 "Terminating simple switch, should be "
6986 "restarted by the actual ring.\n",
6987 chan->name);
6988 ast_hangup(chan);
6989 return NULL;
6991 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6992 if (p->cid_signalling == CID_SIG_DTMF) {
6993 int k = 0;
6994 cs = NULL;
6995 dahdi_setlinear(p->subs[idx].zfd, 0);
6996 res = 2000;
6997 for (;;) {
6998 struct ast_frame *f;
6999 res = ast_waitfor(chan, res);
7000 if (res <= 0) {
7001 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
7002 "Exiting simple switch\n");
7003 ast_hangup(chan);
7004 return NULL;
7006 f = ast_read(chan);
7007 if (f->frametype == AST_FRAME_DTMF) {
7008 dtmfbuf[k++] = f->subclass;
7009 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
7010 res = 2000;
7012 ast_frfree(f);
7014 if (p->ringt_base == p->ringt)
7015 break;
7018 dtmfbuf[k] = '\0';
7019 dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].linear);
7020 /* Got cid and ring. */
7021 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
7022 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
7023 dtmfcid, flags);
7024 /* If first byte is NULL, we have no cid */
7025 if (!ast_strlen_zero(dtmfcid))
7026 number = dtmfcid;
7027 else
7028 number = NULL;
7029 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
7030 } else {
7031 /* FSK Bell202 callerID */
7032 cs = callerid_new(p->cid_signalling);
7033 if (cs) {
7034 #if 1
7035 bump_gains(p);
7036 #endif
7037 samples = 0;
7038 len = 0;
7039 distMatches = 0;
7040 /* Clear the current ring data array so we dont have old data in it. */
7041 for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
7042 curRingData[receivedRingT] = 0;
7043 receivedRingT = 0;
7044 counter = 0;
7045 counter1 = 0;
7046 /* Check to see if context is what it should be, if not set to be. */
7047 if (strcmp(p->context,p->defcontext) != 0) {
7048 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
7049 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
7052 /* Take out of linear mode for Caller*ID processing */
7053 dahdi_setlinear(p->subs[idx].zfd, 0);
7054 for (;;) {
7055 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7056 if ((res = ioctl(p->subs[idx].zfd, DAHDI_IOMUX, &i))) {
7057 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7058 callerid_free(cs);
7059 ast_hangup(chan);
7060 return NULL;
7062 if (i & DAHDI_IOMUX_SIGEVENT) {
7063 res = dahdi_get_event(p->subs[idx].zfd);
7064 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
7065 /* If we get a PR event, they hung up while processing calerid */
7066 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
7067 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
7068 p->polarity = POLARITY_IDLE;
7069 callerid_free(cs);
7070 ast_hangup(chan);
7071 return NULL;
7073 res = 0;
7074 /* Let us detect callerid when the telco uses distinctive ring */
7076 curRingData[receivedRingT] = p->ringt;
7078 if (p->ringt < p->ringt_base/2)
7079 break;
7080 /* Increment the ringT counter so we can match it against
7081 values in chan_dahdi.conf for distinctive ring */
7082 if (++receivedRingT == ARRAY_LEN(curRingData))
7083 break;
7084 } else if (i & DAHDI_IOMUX_READ) {
7085 res = read(p->subs[idx].zfd, buf, sizeof(buf));
7086 if (res < 0) {
7087 if (errno != ELAST) {
7088 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7089 callerid_free(cs);
7090 ast_hangup(chan);
7091 return NULL;
7093 break;
7095 if (p->ringt)
7096 p->ringt--;
7097 if (p->ringt == 1) {
7098 res = -1;
7099 break;
7101 samples += res;
7102 res = callerid_feed(cs, buf, res, AST_LAW(p));
7103 if (res < 0) {
7104 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
7105 break;
7106 } else if (res)
7107 break;
7108 else if (samples > (8000 * 10))
7109 break;
7112 if (res == 1) {
7113 callerid_get(cs, &name, &number, &flags);
7114 ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
7116 if (distinctiveringaftercid == 1) {
7117 /* Clear the current ring data array so we dont have old data in it. */
7118 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
7119 curRingData[receivedRingT] = 0;
7121 receivedRingT = 0;
7122 ast_verb(3, "Detecting post-CID distinctive ring\n");
7123 for (;;) {
7124 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7125 if ((res = ioctl(p->subs[idx].zfd, DAHDI_IOMUX, &i))) {
7126 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7127 callerid_free(cs);
7128 ast_hangup(chan);
7129 return NULL;
7131 if (i & DAHDI_IOMUX_SIGEVENT) {
7132 res = dahdi_get_event(p->subs[idx].zfd);
7133 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
7134 res = 0;
7135 /* Let us detect callerid when the telco uses distinctive ring */
7137 curRingData[receivedRingT] = p->ringt;
7139 if (p->ringt < p->ringt_base/2)
7140 break;
7141 /* Increment the ringT counter so we can match it against
7142 values in chan_dahdi.conf for distinctive ring */
7143 if (++receivedRingT == ARRAY_LEN(curRingData))
7144 break;
7145 } else if (i & DAHDI_IOMUX_READ) {
7146 res = read(p->subs[idx].zfd, buf, sizeof(buf));
7147 if (res < 0) {
7148 if (errno != ELAST) {
7149 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7150 callerid_free(cs);
7151 ast_hangup(chan);
7152 return NULL;
7154 break;
7156 if (p->ringt)
7157 p->ringt--;
7158 if (p->ringt == 1) {
7159 res = -1;
7160 break;
7165 if (p->usedistinctiveringdetection == 1) {
7166 /* this only shows up if you have n of the dring patterns filled in */
7167 ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
7169 for (counter = 0; counter < 3; counter++) {
7170 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
7171 channel */
7172 /* this only shows up if you have n of the dring patterns filled in */
7173 ast_verb(3, "Checking %d,%d,%d\n",
7174 p->drings.ringnum[counter].ring[0],
7175 p->drings.ringnum[counter].ring[1],
7176 p->drings.ringnum[counter].ring[2]);
7177 distMatches = 0;
7178 for (counter1 = 0; counter1 < 3; counter1++) {
7179 ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
7180 if (p->drings.ringnum[counter].ring[counter1] == -1) {
7181 ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
7182 curRingData[counter1]);
7183 distMatches++;
7185 else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
7186 curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
7187 ast_verb(3, "Ring pattern matched in range: %d to %d\n",
7188 (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
7189 (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
7190 distMatches++;
7193 if (distMatches == 3) {
7194 /* The ring matches, set the context to whatever is for distinctive ring.. */
7195 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
7196 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
7197 ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
7198 break;
7202 /* Restore linear mode (if appropriate) for Caller*ID processing */
7203 dahdi_setlinear(p->subs[idx].zfd, p->subs[idx].linear);
7204 #if 1
7205 restore_gains(p);
7206 #endif
7207 if (res < 0) {
7208 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
7210 } else
7211 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
7214 else
7215 cs = NULL;
7217 if (number)
7218 ast_shrink_phone_number(number);
7219 ast_set_callerid(chan, number, name, number);
7221 if (smdi_msg)
7222 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
7224 if (cs)
7225 callerid_free(cs);
7226 /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
7227 if (flags & CID_MSGWAITING) {
7228 ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
7229 notify_message(p->mailbox, 1);
7230 ast_hangup(chan);
7231 return NULL;
7232 } else if (flags & CID_NOMSGWAITING) {
7233 ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
7234 notify_message(p->mailbox, 0);
7235 ast_hangup(chan);
7236 return NULL;
7239 ast_setstate(chan, AST_STATE_RING);
7240 chan->rings = 1;
7241 p->ringt = p->ringt_base;
7242 res = ast_pbx_run(chan);
7243 if (res) {
7244 ast_hangup(chan);
7245 ast_log(LOG_WARNING, "PBX exited non-zero\n");
7247 return NULL;
7248 default:
7249 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
7250 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
7251 if (res < 0)
7252 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
7254 res = tone_zone_play_tone(p->subs[idx].zfd, DAHDI_TONE_CONGESTION);
7255 if (res < 0)
7256 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
7257 ast_hangup(chan);
7258 return NULL;
7261 struct mwi_thread_data {
7262 struct dahdi_pvt *pvt;
7263 unsigned char buf[READ_SIZE];
7264 size_t len;
7267 static int calc_energy(const unsigned char *buf, int len, int law)
7269 int x;
7270 int sum = 0;
7272 if (!len)
7273 return 0;
7275 for (x = 0; x < len; x++)
7276 sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
7278 return sum / len;
7281 static void *mwi_thread(void *data)
7283 struct mwi_thread_data *mtd = data;
7284 struct callerid_state *cs;
7285 pthread_attr_t attr;
7286 pthread_t threadid;
7287 int samples = 0;
7288 char *name, *number;
7289 int flags;
7290 int i, res;
7291 unsigned int spill_done = 0;
7292 int spill_result = -1;
7294 if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
7295 mtd->pvt->mwimonitoractive = 0;
7297 return NULL;
7300 callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
7302 bump_gains(mtd->pvt);
7304 for (;;) {
7305 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7306 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_IOMUX, &i))) {
7307 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7308 goto quit;
7311 if (i & DAHDI_IOMUX_SIGEVENT) {
7312 struct ast_channel *chan;
7314 /* If we get an event, screen out events that we do not act on.
7315 * Otherwise, cancel and go to the simple switch to let it deal with it.
7317 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].zfd);
7319 switch (res) {
7320 case DAHDI_EVENT_NEONMWI_ACTIVE:
7321 case DAHDI_EVENT_NEONMWI_INACTIVE:
7322 case DAHDI_EVENT_NONE:
7323 case DAHDI_EVENT_BITSCHANGED:
7324 break;
7325 case DAHDI_EVENT_NOALARM:
7326 mtd->pvt->inalarm = 0;
7327 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
7328 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
7329 "Channel: %d\r\n", mtd->pvt->channel);
7330 break;
7331 case DAHDI_EVENT_ALARM:
7332 mtd->pvt->inalarm = 1;
7333 res = get_alarms(mtd->pvt);
7334 handle_alarms(mtd->pvt, res);
7335 break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
7336 default:
7337 ast_log(LOG_NOTICE, "Got event %d (%s)... Passing along to ss_thread\n", res, event2str(res));
7338 callerid_free(cs);
7340 restore_gains(mtd->pvt);
7341 mtd->pvt->ringt = mtd->pvt->ringt_base;
7343 if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
7344 pthread_attr_init(&attr);
7345 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7347 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
7348 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
7349 res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7350 if (res < 0)
7351 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
7352 ast_hangup(chan);
7353 goto quit;
7355 goto quit_no_clean;
7357 } else {
7358 ast_log(LOG_WARNING, "Could not create channel to handle call\n");
7361 } else if (i & DAHDI_IOMUX_READ) {
7362 if ((res = read(mtd->pvt->subs[SUB_REAL].zfd, mtd->buf, sizeof(mtd->buf))) < 0) {
7363 if (errno != ELAST) {
7364 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7365 goto quit;
7367 break;
7369 samples += res;
7370 if (!spill_done) {
7371 if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
7372 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
7373 break;
7374 } else if (spill_result) {
7375 spill_done = 1;
7377 } else {
7378 /* keep reading data until the energy level drops below the threshold
7379 so we don't get another 'trigger' on the remaining carrier signal
7381 if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
7382 break;
7384 if (samples > (8000 * 4)) /*Termination case - time to give up*/
7385 break;
7389 if (spill_result == 1) {
7390 callerid_get(cs, &name, &number, &flags);
7391 if (flags & CID_MSGWAITING) {
7392 ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
7393 notify_message(mtd->pvt->mailbox, 1);
7394 } else if (flags & CID_NOMSGWAITING) {
7395 ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
7396 notify_message(mtd->pvt->mailbox, 0);
7397 } else {
7398 ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
7403 quit:
7404 callerid_free(cs);
7406 restore_gains(mtd->pvt);
7408 quit_no_clean:
7409 mtd->pvt->mwimonitoractive = 0;
7411 ast_free(mtd);
7413 return NULL;
7416 /* States for sending MWI message
7417 * First three states are required for send Ring Pulse Alert Signal
7419 enum mwisend_states {
7420 MWI_SEND_SA,
7421 MWI_SEND_SA_WAIT,
7422 MWI_SEND_PAUSE,
7423 MWI_SEND_SPILL,
7424 MWI_SEND_CLEANUP,
7425 MWI_SEND_DONE
7428 static void *mwi_send_thread(void *data)
7430 struct mwi_thread_data *mtd = data;
7431 struct timeval timeout_basis, suspend, now;
7432 int x, i, res;
7433 int num_read;
7434 enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
7436 /* Determine how this spill is to be sent */
7437 if(mwisend_rpas) {
7438 mwi_send_state = MWI_SEND_SA;
7441 gettimeofday(&timeout_basis, NULL);
7443 mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
7444 if (!mtd->pvt->cidspill) {
7445 mtd->pvt->mwisendactive = 0;
7446 ast_free(mtd);
7447 return NULL;
7449 x = DAHDI_FLUSH_BOTH;
7450 res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_FLUSH, &x);
7451 x = 3000;
7452 ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_ONHOOKTRANSFER, &x);
7453 mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
7454 AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
7455 mtd->pvt->cidpos = 0;
7457 while (MWI_SEND_DONE != mwi_send_state) {
7458 num_read = 0;
7459 gettimeofday(&now, NULL);
7460 if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
7461 ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
7462 goto quit;
7465 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
7466 if ((res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_IOMUX, &i))) {
7467 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
7468 goto quit;
7471 if (i & DAHDI_IOMUX_SIGEVENT) {
7472 /* If we get an event, screen out events that we do not act on.
7473 * Otherwise, let handle_init_event determine what is needed
7475 res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].zfd);
7476 switch (res) {
7477 case DAHDI_EVENT_RINGEROFF:
7478 if(mwi_send_state == MWI_SEND_SA_WAIT) {
7479 if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_RINGOFF) ) {
7480 ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
7481 goto quit;
7483 mwi_send_state = MWI_SEND_PAUSE;
7484 gettimeofday(&suspend, NULL);
7486 break;
7487 case DAHDI_EVENT_RINGERON:
7488 case DAHDI_EVENT_HOOKCOMPLETE:
7489 break;
7490 default:
7491 /* Got to the default init event handler */
7492 if (0 < handle_init_event(mtd->pvt, res)) {
7493 /* I've spawned a thread, get out */
7494 goto quit;
7496 break;
7498 } else if (i & DAHDI_IOMUX_READ) {
7499 if ((num_read = read(mtd->pvt->subs[SUB_REAL].zfd, mtd->buf, sizeof(mtd->buf))) < 0) {
7500 if (errno != ELAST) {
7501 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
7502 goto quit;
7504 break;
7507 /* Perform mwi send action */
7508 switch ( mwi_send_state) {
7509 case MWI_SEND_SA:
7510 /* Send the Ring Pulse Signal Alert */
7511 res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, &AS_RP_cadence);
7512 if (res) {
7513 ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
7514 goto quit;
7516 dahdi_set_hook(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_RING);
7517 mwi_send_state = MWI_SEND_SA_WAIT;
7518 break;
7519 case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
7520 break;
7521 case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
7522 gettimeofday(&now, NULL);
7523 if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
7524 mwi_send_state = MWI_SEND_SPILL;
7526 break;
7527 case MWI_SEND_SPILL:
7528 /* We read some number of bytes. Write an equal amount of data */
7529 if(0 < num_read) {
7530 if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
7531 num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
7532 res = write(mtd->pvt->subs[SUB_REAL].zfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
7533 if (res > 0) {
7534 mtd->pvt->cidpos += res;
7535 if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
7536 ast_free(mtd->pvt->cidspill);
7537 mtd->pvt->cidspill = NULL;
7538 mtd->pvt->cidpos = 0;
7539 mtd->pvt->cidlen = 0;
7540 mwi_send_state = MWI_SEND_CLEANUP;
7542 } else {
7543 ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
7544 goto quit;
7547 break;
7548 case MWI_SEND_CLEANUP:
7549 /* For now, do nothing */
7550 mwi_send_state = MWI_SEND_DONE;
7551 break;
7552 default:
7553 /* Should not get here, punt*/
7554 goto quit;
7555 break;
7558 quit:
7559 if(mtd->pvt->cidspill) {
7560 ast_free(mtd->pvt->cidspill);
7561 mtd->pvt->cidspill = NULL;
7563 mtd->pvt->mwisendactive = 0;
7564 ast_free(mtd);
7566 return NULL;
7570 /* destroy a DAHDI channel, identified by its number */
7571 static int dahdi_destroy_channel_bynum(int channel)
7573 struct dahdi_pvt *tmp = NULL;
7574 struct dahdi_pvt *prev = NULL;
7576 tmp = iflist;
7577 while (tmp) {
7578 if (tmp->channel == channel) {
7579 destroy_channel(prev, tmp, 1);
7580 return RESULT_SUCCESS;
7582 prev = tmp;
7583 tmp = tmp->next;
7585 return RESULT_FAILURE;
7588 /* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
7589 static int handle_init_event(struct dahdi_pvt *i, int event)
7591 int res;
7592 int thread_spawned = 0;
7593 pthread_t threadid;
7594 struct ast_channel *chan;
7596 /* Handle an event on a given channel for the monitor thread. */
7598 switch (event) {
7599 case DAHDI_EVENT_NONE:
7600 case DAHDI_EVENT_BITSCHANGED:
7601 break;
7602 case DAHDI_EVENT_WINKFLASH:
7603 case DAHDI_EVENT_RINGOFFHOOK:
7604 if (i->inalarm) break;
7605 if (i->radio) break;
7606 /* Got a ring/answer. What kind of channel are we? */
7607 switch (i->sig) {
7608 case SIG_FXOLS:
7609 case SIG_FXOGS:
7610 case SIG_FXOKS:
7611 res = dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
7612 if (res && (errno == EBUSY))
7613 break;
7614 if (i->cidspill) {
7615 /* Cancel VMWI spill */
7616 ast_free(i->cidspill);
7617 i->cidspill = NULL;
7619 if (i->immediate) {
7620 dahdi_enable_ec(i);
7621 /* The channel is immediately up. Start right away */
7622 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
7623 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
7624 if (!chan) {
7625 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
7626 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7627 if (res < 0)
7628 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7630 } else {
7631 /* Check for callerid, digits, etc */
7632 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
7633 if (chan) {
7634 if (has_voicemail(i))
7635 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_STUTTER);
7636 else
7637 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_DIALTONE);
7638 if (res < 0)
7639 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
7640 if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
7641 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7642 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7643 if (res < 0)
7644 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7645 ast_hangup(chan);
7646 } else {
7647 thread_spawned = 1;
7649 } else
7650 ast_log(LOG_WARNING, "Unable to create channel\n");
7652 break;
7653 case SIG_FXSLS:
7654 case SIG_FXSGS:
7655 case SIG_FXSKS:
7656 i->ringt = i->ringt_base;
7657 /* Fall through */
7658 case SIG_EMWINK:
7659 case SIG_FEATD:
7660 case SIG_FEATDMF:
7661 case SIG_FEATDMF_TA:
7662 case SIG_E911:
7663 case SIG_FGC_CAMA:
7664 case SIG_FGC_CAMAMF:
7665 case SIG_FEATB:
7666 case SIG_EM:
7667 case SIG_EM_E1:
7668 case SIG_SFWINK:
7669 case SIG_SF_FEATD:
7670 case SIG_SF_FEATDMF:
7671 case SIG_SF_FEATB:
7672 case SIG_SF:
7673 /* Check for callerid, digits, etc */
7674 if (i->cid_start == CID_START_POLARITY_IN) {
7675 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
7676 } else {
7677 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
7680 if (!chan) {
7681 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
7682 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
7683 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7684 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7685 if (res < 0) {
7686 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7688 ast_hangup(chan);
7689 } else {
7690 thread_spawned = 1;
7692 break;
7693 default:
7694 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
7695 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
7696 if (res < 0)
7697 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7698 return -1;
7700 break;
7701 case DAHDI_EVENT_NOALARM:
7702 i->inalarm = 0;
7703 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
7704 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
7705 "Channel: %d\r\n", i->channel);
7706 break;
7707 case DAHDI_EVENT_ALARM:
7708 i->inalarm = 1;
7709 res = get_alarms(i);
7710 handle_alarms(i, res);
7711 /* fall thru intentionally */
7712 case DAHDI_EVENT_ONHOOK:
7713 if (i->radio)
7714 break;
7715 /* Back on hook. Hang up. */
7716 switch (i->sig) {
7717 case SIG_FXOLS:
7718 case SIG_FXOGS:
7719 case SIG_FEATD:
7720 case SIG_FEATDMF:
7721 case SIG_FEATDMF_TA:
7722 case SIG_E911:
7723 case SIG_FGC_CAMA:
7724 case SIG_FGC_CAMAMF:
7725 case SIG_FEATB:
7726 case SIG_EM:
7727 case SIG_EM_E1:
7728 case SIG_EMWINK:
7729 case SIG_SF_FEATD:
7730 case SIG_SF_FEATDMF:
7731 case SIG_SF_FEATB:
7732 case SIG_SF:
7733 case SIG_SFWINK:
7734 case SIG_FXSLS:
7735 case SIG_FXSGS:
7736 case SIG_FXSKS:
7737 case SIG_GR303FXSKS:
7738 dahdi_disable_ec(i);
7739 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7740 dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
7741 break;
7742 case SIG_GR303FXOKS:
7743 case SIG_FXOKS:
7744 dahdi_disable_ec(i);
7745 /* Diddle the battery for the zhone */
7746 #ifdef ZHONE_HACK
7747 dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
7748 usleep(1);
7749 #endif
7750 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7751 dahdi_set_hook(i->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
7752 break;
7753 case SIG_PRI:
7754 case SIG_SS7:
7755 case SIG_BRI:
7756 case SIG_BRI_PTMP:
7757 dahdi_disable_ec(i);
7758 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7759 break;
7760 default:
7761 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
7762 res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, -1);
7763 return -1;
7765 break;
7766 case DAHDI_EVENT_POLARITY:
7767 switch (i->sig) {
7768 case SIG_FXSLS:
7769 case SIG_FXSKS:
7770 case SIG_FXSGS:
7771 /* We have already got a PR before the channel was
7772 created, but it wasn't handled. We need polarity
7773 to be REV for remote hangup detection to work.
7774 At least in Spain */
7775 if (i->hanguponpolarityswitch)
7776 i->polarity = POLARITY_REV;
7777 if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
7778 i->polarity = POLARITY_REV;
7779 ast_verb(2, "Starting post polarity "
7780 "CID detection on channel %d\n",
7781 i->channel);
7782 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
7783 if (!chan) {
7784 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
7785 } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
7786 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7787 } else {
7788 thread_spawned = 1;
7791 break;
7792 default:
7793 ast_log(LOG_WARNING, "handle_init_event detected "
7794 "polarity reversal on non-FXO (SIG_FXS) "
7795 "interface %d\n", i->channel);
7797 break;
7798 case DAHDI_EVENT_REMOVED: /* destroy channel */
7799 ast_log(LOG_NOTICE,
7800 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
7801 i->channel);
7802 dahdi_destroy_channel_bynum(i->channel);
7803 break;
7804 case DAHDI_EVENT_NEONMWI_ACTIVE:
7805 if (i->mwimonitor_neon) {
7806 notify_message(i->mailbox, 1);
7807 ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
7809 break;
7810 case DAHDI_EVENT_NEONMWI_INACTIVE:
7811 if (i->mwimonitor_neon) {
7812 notify_message(i->mailbox, 0);
7813 ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
7815 break;
7817 return thread_spawned;
7820 static void *do_monitor(void *data)
7822 int count, res, res2, spoint, pollres=0;
7823 struct dahdi_pvt *i;
7824 struct dahdi_pvt *last = NULL;
7825 time_t thispass = 0, lastpass = 0;
7826 int found;
7827 char buf[1024];
7828 struct pollfd *pfds=NULL;
7829 int lastalloc = -1;
7830 /* This thread monitors all the frame relay interfaces which are not yet in use
7831 (and thus do not have a separate thread) indefinitely */
7832 /* From here on out, we die whenever asked */
7833 #if 0
7834 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
7835 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
7836 return NULL;
7838 ast_debug(1, "Monitor starting...\n");
7839 #endif
7840 for (;;) {
7841 /* Lock the interface list */
7842 ast_mutex_lock(&iflock);
7843 if (!pfds || (lastalloc != ifcount)) {
7844 if (pfds) {
7845 ast_free(pfds);
7846 pfds = NULL;
7848 if (ifcount) {
7849 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
7850 ast_mutex_unlock(&iflock);
7851 return NULL;
7854 lastalloc = ifcount;
7856 /* Build the stuff we're going to poll on, that is the socket of every
7857 dahdi_pvt that does not have an associated owner channel */
7858 count = 0;
7859 i = iflist;
7860 while (i) {
7861 if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
7862 if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
7863 /* This needs to be watched, as it lacks an owner */
7864 pfds[count].fd = i->subs[SUB_REAL].zfd;
7865 pfds[count].events = POLLPRI;
7866 pfds[count].revents = 0;
7867 /* If we are monitoring for VMWI or sending CID, we need to
7868 read from the channel as well */
7869 if (i->cidspill || i->mwimonitor_fsk)
7870 pfds[count].events |= POLLIN;
7871 count++;
7874 i = i->next;
7876 /* Okay, now that we know what to do, release the interface lock */
7877 ast_mutex_unlock(&iflock);
7879 pthread_testcancel();
7880 /* Wait at least a second for something to happen */
7881 res = poll(pfds, count, 1000);
7882 pthread_testcancel();
7883 /* Okay, poll has finished. Let's see what happened. */
7884 if (res < 0) {
7885 if ((errno != EAGAIN) && (errno != EINTR))
7886 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
7887 continue;
7889 /* Alright, lock the interface list again, and let's look and see what has
7890 happened */
7891 ast_mutex_lock(&iflock);
7892 found = 0;
7893 spoint = 0;
7894 lastpass = thispass;
7895 thispass = time(NULL);
7896 i = iflist;
7897 while (i) {
7898 if (thispass != lastpass) {
7899 if (!found && ((i == last) || ((i == iflist) && !last))) {
7900 last = i;
7901 if (last) {
7902 if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
7903 res = has_voicemail(last);
7904 if (last->msgstate != res) {
7906 /* This channel has a new voicemail state,
7907 * initiate a thread to send an MWI message
7909 pthread_attr_t attr;
7910 pthread_t threadid;
7911 struct mwi_thread_data *mtd;
7912 res2 = ioctl(last->subs[SUB_REAL].zfd, DAHDI_VMWI, res);
7913 if (res2) {
7914 ast_log(LOG_DEBUG, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
7916 pthread_attr_init(&attr);
7917 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7918 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
7919 last->msgstate = res;
7920 mtd->pvt = last;
7921 last->mwisendactive = 1;
7922 if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
7923 ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
7924 ast_free(mtd);
7925 last->mwisendactive = 0;
7928 found ++;
7931 last = last->next;
7935 if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
7936 if (i->radio && !i->owner)
7938 res = dahdi_get_event(i->subs[SUB_REAL].zfd);
7939 if (res)
7941 ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
7942 /* Don't hold iflock while handling init events */
7943 ast_mutex_unlock(&iflock);
7944 handle_init_event(i, res);
7945 ast_mutex_lock(&iflock);
7947 i = i->next;
7948 continue;
7950 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
7951 if (pollres & POLLIN) {
7952 if (i->owner || i->subs[SUB_REAL].owner) {
7953 #ifdef HAVE_PRI
7954 if (!i->pri)
7955 #endif
7956 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].zfd);
7957 i = i->next;
7958 continue;
7960 if (!i->cidspill && !i->mwimonitor_fsk) {
7961 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].zfd);
7962 i = i->next;
7963 continue;
7965 res = read(i->subs[SUB_REAL].zfd, buf, sizeof(buf));
7966 if (res > 0) {
7967 if (i->mwimonitor_fsk) {
7968 if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
7969 pthread_attr_t attr;
7970 pthread_t threadid;
7971 struct mwi_thread_data *mtd;
7973 pthread_attr_init(&attr);
7974 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7976 ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
7977 if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
7978 mtd->pvt = i;
7979 memcpy(mtd->buf, buf, res);
7980 mtd->len = res;
7981 if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
7982 ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
7983 ast_free(mtd);
7985 i->mwimonitoractive = 1;
7989 } else {
7990 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
7993 if (pollres & POLLPRI) {
7994 if (i->owner || i->subs[SUB_REAL].owner) {
7995 #ifdef HAVE_PRI
7996 if (!i->pri)
7997 #endif
7998 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].zfd);
7999 i = i->next;
8000 continue;
8002 res = dahdi_get_event(i->subs[SUB_REAL].zfd);
8003 ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
8004 /* Don't hold iflock while handling init events */
8005 ast_mutex_unlock(&iflock);
8006 handle_init_event(i, res);
8007 ast_mutex_lock(&iflock);
8010 i=i->next;
8012 ast_mutex_unlock(&iflock);
8014 /* Never reached */
8015 return NULL;
8019 static int restart_monitor(void)
8021 /* If we're supposed to be stopped -- stay stopped */
8022 if (monitor_thread == AST_PTHREADT_STOP)
8023 return 0;
8024 ast_mutex_lock(&monlock);
8025 if (monitor_thread == pthread_self()) {
8026 ast_mutex_unlock(&monlock);
8027 ast_log(LOG_WARNING, "Cannot kill myself\n");
8028 return -1;
8030 if (monitor_thread != AST_PTHREADT_NULL) {
8031 /* Wake up the thread */
8032 pthread_kill(monitor_thread, SIGURG);
8033 } else {
8034 /* Start a new monitor */
8035 if (ast_pthread_create_detached_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
8036 ast_mutex_unlock(&monlock);
8037 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
8038 return -1;
8041 ast_mutex_unlock(&monlock);
8042 return 0;
8045 #ifdef HAVE_PRI
8046 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
8048 int x;
8049 int trunkgroup;
8050 /* Get appropriate trunk group if there is one */
8051 trunkgroup = pris[*span].mastertrunkgroup;
8052 if (trunkgroup) {
8053 /* Select a specific trunk group */
8054 for (x = 0; x < NUM_SPANS; x++) {
8055 if (pris[x].trunkgroup == trunkgroup) {
8056 *span = x;
8057 return 0;
8060 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
8061 *span = -1;
8062 } else {
8063 if (pris[*span].trunkgroup) {
8064 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
8065 *span = -1;
8066 } else if (pris[*span].mastertrunkgroup) {
8067 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
8068 *span = -1;
8069 } else {
8070 if (si->totalchans == 31) {
8071 /* E1 */
8072 pris[*span].dchannels[0] = 16 + offset;
8073 } else if (si->totalchans == 24) {
8074 /* T1 or J1 */
8075 pris[*span].dchannels[0] = 24 + offset;
8076 } else if (si->totalchans == 3) {
8077 /* BRI */
8078 pris[*span].dchannels[0] = 3 + offset;
8079 } else {
8080 ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
8081 *span = -1;
8082 return 0;
8084 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
8085 pris[*span].offset = offset;
8086 pris[*span].span = *span + 1;
8089 return 0;
8092 static int pri_create_trunkgroup(int trunkgroup, int *channels)
8094 struct dahdi_spaninfo si;
8095 struct dahdi_params p;
8096 int fd;
8097 int span;
8098 int ospan=0;
8099 int x,y;
8100 for (x = 0; x < NUM_SPANS; x++) {
8101 if (pris[x].trunkgroup == trunkgroup) {
8102 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
8103 return -1;
8106 for (y = 0; y < NUM_DCHANS; y++) {
8107 if (!channels[y])
8108 break;
8109 memset(&si, 0, sizeof(si));
8110 memset(&p, 0, sizeof(p));
8111 fd = open("/dev/dahdi/channel", O_RDWR);
8112 if (fd < 0) {
8113 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
8114 return -1;
8116 x = channels[y];
8117 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
8118 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
8119 dahdi_close(fd);
8120 return -1;
8122 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
8123 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
8124 return -1;
8126 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
8127 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
8128 dahdi_close(fd);
8129 return -1;
8131 span = p.spanno - 1;
8132 if (pris[span].trunkgroup) {
8133 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
8134 dahdi_close(fd);
8135 return -1;
8137 if (pris[span].pvts[0]) {
8138 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
8139 dahdi_close(fd);
8140 return -1;
8142 if (!y) {
8143 pris[span].trunkgroup = trunkgroup;
8144 pris[span].offset = channels[y] - p.chanpos;
8145 ospan = span;
8147 pris[ospan].dchannels[y] = channels[y];
8148 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
8149 pris[span].span = span + 1;
8150 dahdi_close(fd);
8152 return 0;
8155 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
8157 if (pris[span].mastertrunkgroup) {
8158 ast_log(LOG_WARNING, "Span %d is already part of trunk group %d, cannot add to trunk group %d\n", span + 1, pris[span].mastertrunkgroup, trunkgroup);
8159 return -1;
8161 pris[span].mastertrunkgroup = trunkgroup;
8162 pris[span].prilogicalspan = logicalspan;
8163 return 0;
8166 #endif
8168 #ifdef HAVE_SS7
8170 static unsigned int parse_pointcode(const char *pcstring)
8172 unsigned int code1, code2, code3;
8173 int numvals;
8175 numvals = sscanf(pcstring, "%d-%d-%d", &code1, &code2, &code3);
8176 if (numvals == 1)
8177 return code1;
8178 if (numvals == 3)
8179 return (code1 << 16) | (code2 << 8) | code3;
8181 return 0;
8184 static struct dahdi_ss7 * ss7_resolve_linkset(int linkset)
8186 if ((linkset < 0) || (linkset >= NUM_SPANS))
8187 return NULL;
8188 else
8189 return &linksets[linkset - 1];
8191 #endif /* HAVE_SS7 */
8193 /* converts a DAHDI sigtype to signalling as can be configured from
8194 * chan_dahdi.conf.
8195 * While both have basically the same values, this will later be the
8196 * place to add filters and sanity checks
8198 static int sigtype_to_signalling(int sigtype)
8200 return sigtype;
8203 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
8205 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
8206 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
8207 char fn[80];
8208 struct dahdi_bufferinfo bi;
8210 int res;
8211 int span = 0;
8212 int here = 0;
8213 int x;
8214 struct dahdi_pvt **wlist;
8215 struct dahdi_pvt **wend;
8216 struct dahdi_params p;
8218 wlist = &iflist;
8219 wend = &ifend;
8221 #ifdef HAVE_PRI
8222 if (pri) {
8223 wlist = &pri->crvs;
8224 wend = &pri->crvend;
8226 #endif
8228 tmp2 = *wlist;
8229 prev = NULL;
8231 while (tmp2) {
8232 if (!tmp2->destroy) {
8233 if (tmp2->channel == channel) {
8234 tmp = tmp2;
8235 here = 1;
8236 break;
8238 if (tmp2->channel > channel) {
8239 break;
8242 prev = tmp2;
8243 tmp2 = tmp2->next;
8246 if (!here && !reloading) {
8247 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
8248 destroy_dahdi_pvt(&tmp);
8249 return NULL;
8251 ast_mutex_init(&tmp->lock);
8252 ifcount++;
8253 for (x = 0; x < 3; x++)
8254 tmp->subs[x].zfd = -1;
8255 tmp->channel = channel;
8258 if (tmp) {
8259 int chan_sig = conf->chan.sig;
8260 if (!here) {
8261 if ((channel != CHAN_PSEUDO) && !pri) {
8262 snprintf(fn, sizeof(fn), "%d", channel);
8263 /* Open non-blocking */
8264 if (!here)
8265 tmp->subs[SUB_REAL].zfd = dahdi_open(fn);
8266 /* Allocate a dahdi structure */
8267 if (tmp->subs[SUB_REAL].zfd < 0) {
8268 ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
8269 destroy_dahdi_pvt(&tmp);
8270 return NULL;
8272 memset(&p, 0, sizeof(p));
8273 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &p);
8274 if (res < 0) {
8275 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
8276 destroy_dahdi_pvt(&tmp);
8277 return NULL;
8279 if (conf->is_sig_auto)
8280 chan_sig = sigtype_to_signalling(p.sigtype);
8281 if (p.sigtype != (chan_sig & 0x3ffff)) {
8282 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
8283 destroy_dahdi_pvt(&tmp);
8284 return NULL;
8286 tmp->law = p.curlaw;
8287 tmp->span = p.spanno;
8288 span = p.spanno - 1;
8289 } else {
8290 if (channel == CHAN_PSEUDO)
8291 chan_sig = 0;
8292 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
8293 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
8294 return NULL;
8297 #ifdef HAVE_SS7
8298 if (chan_sig == SIG_SS7) {
8299 struct dahdi_ss7 *ss7;
8300 int clear = 0;
8301 if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &clear)) {
8302 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
8303 destroy_dahdi_pvt(&tmp);
8304 return NULL;
8307 ss7 = ss7_resolve_linkset(cur_linkset);
8308 if (!ss7) {
8309 ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
8310 destroy_dahdi_pvt(&tmp);
8311 return NULL;
8313 if (cur_cicbeginswith < 0) {
8314 ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
8315 destroy_dahdi_pvt(&tmp);
8316 return NULL;
8319 tmp->cic = cur_cicbeginswith++;
8321 /* DB: Add CIC's DPC information */
8322 tmp->dpc = cur_defaultdpc;
8324 tmp->ss7 = ss7;
8325 tmp->ss7call = NULL;
8326 ss7->pvts[ss7->numchans++] = tmp;
8328 ast_copy_string(linksets[span].internationalprefix, conf->ss7.internationalprefix, sizeof(linksets[span].internationalprefix));
8329 ast_copy_string(linksets[span].nationalprefix, conf->ss7.nationalprefix, sizeof(linksets[span].nationalprefix));
8330 ast_copy_string(linksets[span].subscriberprefix, conf->ss7.subscriberprefix, sizeof(linksets[span].subscriberprefix));
8331 ast_copy_string(linksets[span].unknownprefix, conf->ss7.unknownprefix, sizeof(linksets[span].unknownprefix));
8333 linksets[span].called_nai = conf->ss7.called_nai;
8334 linksets[span].calling_nai = conf->ss7.calling_nai;
8336 #endif
8337 #ifdef HAVE_PRI
8338 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
8339 int offset;
8340 int myswitchtype;
8341 int matchesdchan;
8342 int x,y;
8343 offset = 0;
8344 if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
8345 && ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &offset)) {
8346 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
8347 destroy_dahdi_pvt(&tmp);
8348 return NULL;
8350 if (span >= NUM_SPANS) {
8351 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
8352 destroy_dahdi_pvt(&tmp);
8353 return NULL;
8354 } else {
8355 struct dahdi_spaninfo si;
8356 si.spanno = 0;
8357 if (ioctl(tmp->subs[SUB_REAL].zfd,DAHDI_SPANSTAT,&si) == -1) {
8358 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
8359 destroy_dahdi_pvt(&tmp);
8360 return NULL;
8362 /* Store the logical span first based upon the real span */
8363 tmp->logicalspan = pris[span].prilogicalspan;
8364 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
8365 if (span < 0) {
8366 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
8367 destroy_dahdi_pvt(&tmp);
8368 return NULL;
8370 if ((chan_sig == SIG_PRI) ||
8371 (chan_sig == SIG_BRI) ||
8372 (chan_sig == SIG_BRI_PTMP))
8373 myswitchtype = conf->pri.switchtype;
8374 else
8375 myswitchtype = PRI_SWITCH_GR303_TMC;
8376 /* Make sure this isn't a d-channel */
8377 matchesdchan=0;
8378 for (x = 0; x < NUM_SPANS; x++) {
8379 for (y = 0; y < NUM_DCHANS; y++) {
8380 if (pris[x].dchannels[y] == tmp->channel) {
8381 matchesdchan = 1;
8382 break;
8386 offset = p.chanpos;
8387 if (!matchesdchan) {
8388 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
8389 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
8390 destroy_dahdi_pvt(&tmp);
8391 return NULL;
8393 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
8394 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
8395 destroy_dahdi_pvt(&tmp);
8396 return NULL;
8398 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
8399 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
8400 destroy_dahdi_pvt(&tmp);
8401 return NULL;
8403 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
8404 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
8405 destroy_dahdi_pvt(&tmp);
8406 return NULL;
8408 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
8409 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
8410 destroy_dahdi_pvt(&tmp);
8411 return NULL;
8413 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
8414 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
8415 destroy_dahdi_pvt(&tmp);
8416 return NULL;
8418 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
8419 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
8420 destroy_dahdi_pvt(&tmp);
8421 return NULL;
8423 if (pris[span].numchans >= MAX_CHANNELS) {
8424 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
8425 pris[span].trunkgroup);
8426 destroy_dahdi_pvt(&tmp);
8427 return NULL;
8430 pris[span].sig = chan_sig;
8431 pris[span].nodetype = conf->pri.nodetype;
8432 pris[span].switchtype = myswitchtype;
8433 pris[span].nsf = conf->pri.nsf;
8434 pris[span].dialplan = conf->pri.dialplan;
8435 pris[span].localdialplan = conf->pri.localdialplan;
8436 pris[span].pvts[pris[span].numchans++] = tmp;
8437 pris[span].minunused = conf->pri.minunused;
8438 pris[span].minidle = conf->pri.minidle;
8439 pris[span].overlapdial = conf->pri.overlapdial;
8440 #ifdef HAVE_PRI_INBANDDISCONNECT
8441 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
8442 #endif
8443 pris[span].facilityenable = conf->pri.facilityenable;
8444 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
8445 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
8446 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
8447 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
8448 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
8449 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
8450 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
8451 pris[span].resetinterval = conf->pri.resetinterval;
8453 tmp->pri = &pris[span];
8454 tmp->prioffset = offset;
8455 tmp->call = NULL;
8456 } else {
8457 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
8458 destroy_dahdi_pvt(&tmp);
8459 return NULL;
8462 } else {
8463 tmp->prioffset = 0;
8465 #endif
8466 } else {
8467 chan_sig = tmp->sig;
8468 memset(&p, 0, sizeof(p));
8469 if (tmp->subs[SUB_REAL].zfd > -1)
8470 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &p);
8472 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
8473 switch (chan_sig) {
8474 case SIG_FXSKS:
8475 case SIG_FXSLS:
8476 case SIG_EM:
8477 case SIG_EM_E1:
8478 case SIG_EMWINK:
8479 case SIG_FEATD:
8480 case SIG_FEATDMF:
8481 case SIG_FEATDMF_TA:
8482 case SIG_FEATB:
8483 case SIG_E911:
8484 case SIG_SF:
8485 case SIG_SFWINK:
8486 case SIG_FGC_CAMA:
8487 case SIG_FGC_CAMAMF:
8488 case SIG_SF_FEATD:
8489 case SIG_SF_FEATDMF:
8490 case SIG_SF_FEATB:
8491 p.starttime = 250;
8492 break;
8495 if (tmp->radio) {
8496 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
8497 p.channo = channel;
8498 p.rxwinktime = 1;
8499 p.rxflashtime = 1;
8500 p.starttime = 1;
8501 p.debouncetime = 5;
8503 if (!tmp->radio) {
8504 p.channo = channel;
8505 /* Override timing settings based on config file */
8506 if (conf->timing.prewinktime >= 0)
8507 p.prewinktime = conf->timing.prewinktime;
8508 if (conf->timing.preflashtime >= 0)
8509 p.preflashtime = conf->timing.preflashtime;
8510 if (conf->timing.winktime >= 0)
8511 p.winktime = conf->timing.winktime;
8512 if (conf->timing.flashtime >= 0)
8513 p.flashtime = conf->timing.flashtime;
8514 if (conf->timing.starttime >= 0)
8515 p.starttime = conf->timing.starttime;
8516 if (conf->timing.rxwinktime >= 0)
8517 p.rxwinktime = conf->timing.rxwinktime;
8518 if (conf->timing.rxflashtime >= 0)
8519 p.rxflashtime = conf->timing.rxflashtime;
8520 if (conf->timing.debouncetime >= 0)
8521 p.debouncetime = conf->timing.debouncetime;
8524 /* dont set parms on a pseudo-channel (or CRV) */
8525 if (tmp->subs[SUB_REAL].zfd >= 0)
8527 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_PARAMS, &p);
8528 if (res < 0) {
8529 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
8530 destroy_dahdi_pvt(&tmp);
8531 return NULL;
8534 #if 1
8535 if (!here && (tmp->subs[SUB_REAL].zfd > -1)) {
8536 memset(&bi, 0, sizeof(bi));
8537 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_BUFINFO, &bi);
8538 if (!res) {
8539 bi.txbufpolicy = conf->chan.buf_policy;
8540 bi.rxbufpolicy = conf->chan.buf_policy;
8541 bi.numbufs = conf->chan.buf_no;
8542 res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_BUFINFO, &bi);
8543 if (res < 0) {
8544 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
8546 } else
8547 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
8549 #endif
8550 tmp->immediate = conf->chan.immediate;
8551 tmp->transfertobusy = conf->chan.transfertobusy;
8552 if (chan_sig & __DAHDI_SIG_FXS) {
8553 tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
8554 tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
8556 tmp->sig = chan_sig;
8557 tmp->outsigmod = conf->chan.outsigmod;
8558 tmp->ringt_base = ringt_base;
8559 tmp->firstradio = 0;
8560 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
8561 tmp->permcallwaiting = conf->chan.callwaiting;
8562 else
8563 tmp->permcallwaiting = 0;
8564 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
8565 tmp->destroy = 0;
8566 tmp->drings = conf->chan.drings;
8568 /* 10 is a nice default. */
8569 if (tmp->drings.ringnum[0].range == 0)
8570 tmp->drings.ringnum[0].range = 10;
8571 if (tmp->drings.ringnum[1].range == 0)
8572 tmp->drings.ringnum[1].range = 10;
8573 if (tmp->drings.ringnum[2].range == 0)
8574 tmp->drings.ringnum[2].range = 10;
8576 tmp->usedistinctiveringdetection = usedistinctiveringdetection;
8577 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
8578 tmp->threewaycalling = conf->chan.threewaycalling;
8579 tmp->adsi = conf->chan.adsi;
8580 tmp->use_smdi = conf->chan.use_smdi;
8581 tmp->permhidecallerid = conf->chan.hidecallerid;
8582 tmp->callreturn = conf->chan.callreturn;
8583 tmp->echocancel = conf->chan.echocancel;
8584 tmp->echotraining = conf->chan.echotraining;
8585 tmp->pulse = conf->chan.pulse;
8586 if (tmp->echocancel.head.tap_length) {
8587 tmp->echocanbridged = conf->chan.echocanbridged;
8588 } else {
8589 if (conf->chan.echocanbridged)
8590 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
8591 tmp->echocanbridged = 0;
8593 tmp->busydetect = conf->chan.busydetect;
8594 tmp->busycount = conf->chan.busycount;
8595 tmp->busy_tonelength = conf->chan.busy_tonelength;
8596 tmp->busy_quietlength = conf->chan.busy_quietlength;
8597 tmp->callprogress = conf->chan.callprogress;
8598 tmp->cancallforward = conf->chan.cancallforward;
8599 tmp->dtmfrelax = conf->chan.dtmfrelax;
8600 tmp->callwaiting = tmp->permcallwaiting;
8601 tmp->hidecallerid = tmp->permhidecallerid;
8602 tmp->channel = channel;
8603 tmp->stripmsd = conf->chan.stripmsd;
8604 tmp->use_callerid = conf->chan.use_callerid;
8605 tmp->cid_signalling = conf->chan.cid_signalling;
8606 tmp->cid_start = conf->chan.cid_start;
8607 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
8608 tmp->restrictcid = conf->chan.restrictcid;
8609 tmp->use_callingpres = conf->chan.use_callingpres;
8610 tmp->priindication_oob = conf->chan.priindication_oob;
8611 tmp->priexclusive = conf->chan.priexclusive;
8612 if (tmp->usedistinctiveringdetection) {
8613 if (!tmp->use_callerid) {
8614 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
8615 tmp->use_callerid = 1;
8619 if (tmp->cid_signalling == CID_SIG_SMDI) {
8620 if (!tmp->use_smdi) {
8621 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
8622 tmp->use_smdi = 1;
8625 if (tmp->use_smdi) {
8626 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
8627 if (!(tmp->smdi_iface)) {
8628 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
8629 tmp->use_smdi = 0;
8633 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
8634 tmp->amaflags = conf->chan.amaflags;
8635 if (!here) {
8636 tmp->confno = -1;
8637 tmp->propconfno = -1;
8639 tmp->canpark = conf->chan.canpark;
8640 tmp->transfer = conf->chan.transfer;
8641 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
8642 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
8643 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
8644 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
8645 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
8646 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
8647 ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
8648 tmp->cid_ton = 0;
8649 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
8650 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
8651 if (!ast_strlen_zero(tmp->mailbox)) {
8652 char *mailbox, *context;
8653 mailbox = context = ast_strdupa(tmp->mailbox);
8654 strsep(&context, "@");
8655 if (ast_strlen_zero(context))
8656 context = "default";
8657 tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
8658 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
8659 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
8660 AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
8661 AST_EVENT_IE_END);
8663 tmp->msgstate = -1;
8664 tmp->group = conf->chan.group;
8665 tmp->callgroup = conf->chan.callgroup;
8666 tmp->pickupgroup= conf->chan.pickupgroup;
8667 if (conf->chan.vars) {
8668 tmp->vars = conf->chan.vars;
8670 tmp->cid_rxgain = conf->chan.cid_rxgain;
8671 tmp->rxgain = conf->chan.rxgain;
8672 tmp->txgain = conf->chan.txgain;
8673 tmp->tonezone = conf->chan.tonezone;
8674 tmp->onhooktime = time(NULL);
8675 if (tmp->subs[SUB_REAL].zfd > -1) {
8676 set_actual_gain(tmp->subs[SUB_REAL].zfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
8677 if (tmp->dsp)
8678 ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
8679 update_conf(tmp);
8680 if (!here) {
8681 if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
8682 /* Hang it up to be sure it's good */
8683 dahdi_set_hook(tmp->subs[SUB_REAL].zfd, DAHDI_ONHOOK);
8685 ioctl(tmp->subs[SUB_REAL].zfd,DAHDI_SETTONEZONE,&tmp->tonezone);
8686 #ifdef HAVE_PRI
8687 /* the dchannel is down so put the channel in alarm */
8688 if (tmp->pri && !pri_is_up(tmp->pri))
8689 tmp->inalarm = 1;
8690 #endif
8691 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
8692 tmp->inalarm = 1;
8693 handle_alarms(tmp, res);
8697 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
8698 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
8699 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
8700 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
8701 if (!here) {
8702 tmp->locallyblocked = tmp->remotelyblocked = 0;
8703 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
8704 tmp->inservice = 0;
8705 else /* We default to in service on protocols that don't have a reset */
8706 tmp->inservice = 1;
8709 if (tmp && !here) {
8710 /* nothing on the iflist */
8711 if (!*wlist) {
8712 *wlist = tmp;
8713 tmp->prev = NULL;
8714 tmp->next = NULL;
8715 *wend = tmp;
8716 } else {
8717 /* at least one member on the iflist */
8718 struct dahdi_pvt *working = *wlist;
8720 /* check if we maybe have to put it on the begining */
8721 if (working->channel > tmp->channel) {
8722 tmp->next = *wlist;
8723 tmp->prev = NULL;
8724 (*wlist)->prev = tmp;
8725 *wlist = tmp;
8726 } else {
8727 /* go through all the members and put the member in the right place */
8728 while (working) {
8729 /* in the middle */
8730 if (working->next) {
8731 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
8732 tmp->next = working->next;
8733 tmp->prev = working;
8734 working->next->prev = tmp;
8735 working->next = tmp;
8736 break;
8738 } else {
8739 /* the last */
8740 if (working->channel < tmp->channel) {
8741 working->next = tmp;
8742 tmp->next = NULL;
8743 tmp->prev = working;
8744 *wend = tmp;
8745 break;
8748 working = working->next;
8753 return tmp;
8756 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
8758 int res;
8759 struct dahdi_params par;
8761 /* First, check group matching */
8762 if (groupmatch) {
8763 if ((p->group & groupmatch) != groupmatch)
8764 return 0;
8765 *groupmatched = 1;
8767 /* Check to see if we have a channel match */
8768 if (channelmatch != -1) {
8769 if (p->channel != channelmatch)
8770 return 0;
8771 *channelmatched = 1;
8773 /* We're at least busy at this point */
8774 if (busy) {
8775 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
8776 *busy = 1;
8778 /* If do not disturb, definitely not */
8779 if (p->dnd)
8780 return 0;
8781 /* If guard time, definitely not */
8782 if (p->guardtime && (time(NULL) < p->guardtime))
8783 return 0;
8785 if (p->locallyblocked || p->remotelyblocked)
8786 return 0;
8788 /* If no owner definitely available */
8789 if (!p->owner) {
8790 #ifdef HAVE_PRI
8791 /* Trust PRI */
8792 if (p->pri) {
8793 if (p->resetting || p->call)
8794 return 0;
8795 else
8796 return 1;
8798 #endif
8799 #ifdef HAVE_SS7
8800 /* Trust SS7 */
8801 if (p->ss7) {
8802 if (p->ss7call)
8803 return 0;
8804 else
8805 return 1;
8807 #endif
8808 if (!(p->radio || (p->oprmode < 0)))
8810 if (!p->sig || (p->sig == SIG_FXSLS))
8811 return 1;
8812 /* Check hook state */
8813 if (p->subs[SUB_REAL].zfd > -1)
8814 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &par);
8815 else {
8816 /* Assume not off hook on CVRS */
8817 res = 0;
8818 par.rxisoffhook = 0;
8820 if (res) {
8821 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
8822 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
8823 /* When "onhook" that means no battery on the line, and thus
8824 it is out of service..., if it's on a TDM card... If it's a channel
8825 bank, there is no telling... */
8826 if (par.rxbits > -1)
8827 return 1;
8828 if (par.rxisoffhook)
8829 return 1;
8830 else
8831 return 0;
8832 } else if (par.rxisoffhook) {
8833 ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
8834 /* Not available when the other end is off hook */
8835 return 0;
8838 return 1;
8841 /* If it's not an FXO, forget about call wait */
8842 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
8843 return 0;
8845 if (!p->callwaiting) {
8846 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
8847 return 0;
8850 if (p->subs[SUB_CALLWAIT].zfd > -1) {
8851 /* If there is already a call waiting call, then we can't take a second one */
8852 return 0;
8855 if ((p->owner->_state != AST_STATE_UP) &&
8856 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
8857 /* If the current call is not up, then don't allow the call */
8858 return 0;
8860 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
8861 /* Can't take a call wait when the three way calling hasn't been merged yet. */
8862 return 0;
8864 /* We're cool */
8865 return 1;
8868 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
8870 struct dahdi_pvt *p;
8871 struct dahdi_bufferinfo bi;
8872 int res;
8874 if ((p = ast_malloc(sizeof(*p)))) {
8875 memcpy(p, src, sizeof(struct dahdi_pvt));
8876 ast_mutex_init(&p->lock);
8877 p->subs[SUB_REAL].zfd = dahdi_open("/dev/dahdi/pseudo");
8878 /* Allocate a dahdi structure */
8879 if (p->subs[SUB_REAL].zfd < 0) {
8880 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
8881 destroy_dahdi_pvt(&p);
8882 return NULL;
8884 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_BUFINFO, &bi);
8885 if (!res) {
8886 bi.txbufpolicy = src->buf_policy;
8887 bi.rxbufpolicy = src->buf_policy;
8888 bi.numbufs = src->buf_no;
8889 res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SET_BUFINFO, &bi);
8890 if (res < 0) {
8891 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
8893 } else
8894 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
8896 p->destroy = 1;
8897 p->next = iflist;
8898 p->prev = NULL;
8899 iflist = p;
8900 if (iflist->next)
8901 iflist->next->prev = p;
8902 return p;
8906 #ifdef HAVE_PRI
8907 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
8909 int x;
8910 if (backwards)
8911 x = pri->numchans;
8912 else
8913 x = 0;
8914 for (;;) {
8915 if (backwards && (x < 0))
8916 break;
8917 if (!backwards && (x >= pri->numchans))
8918 break;
8919 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
8920 ast_debug(1, "Found empty available channel %d/%d\n",
8921 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
8922 return x;
8924 if (backwards)
8925 x--;
8926 else
8927 x++;
8929 return -1;
8931 #endif
8933 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
8935 ast_group_t groupmatch = 0;
8936 int channelmatch = -1;
8937 int roundrobin = 0;
8938 int callwait = 0;
8939 int busy = 0;
8940 struct dahdi_pvt *p;
8941 struct ast_channel *tmp = NULL;
8942 char *dest=NULL;
8943 int x;
8944 char *s;
8945 char opt=0;
8946 int res=0, y=0;
8947 int backwards = 0;
8948 #ifdef HAVE_PRI
8949 int crv;
8950 int bearer = -1;
8951 int trunkgroup;
8952 struct dahdi_pri *pri=NULL;
8953 #endif
8954 struct dahdi_pvt *exitpvt, *start, *end;
8955 ast_mutex_t *lock;
8956 int channelmatched = 0;
8957 int groupmatched = 0;
8959 /* Assume we're locking the iflock */
8960 lock = &iflock;
8961 start = iflist;
8962 end = ifend;
8963 if (data) {
8964 dest = ast_strdupa((char *)data);
8965 } else {
8966 ast_log(LOG_WARNING, "Channel requested with no data\n");
8967 return NULL;
8969 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
8970 /* Retrieve the group number */
8971 char *stringp=NULL;
8972 stringp=dest + 1;
8973 s = strsep(&stringp, "/");
8974 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
8975 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
8976 return NULL;
8978 groupmatch = ((ast_group_t) 1 << x);
8979 if (toupper(dest[0]) == 'G') {
8980 if (dest[0] == 'G') {
8981 backwards = 1;
8982 p = ifend;
8983 } else
8984 p = iflist;
8985 } else {
8986 if (dest[0] == 'R') {
8987 backwards = 1;
8988 p = round_robin[x]?round_robin[x]->prev:ifend;
8989 if (!p)
8990 p = ifend;
8991 } else {
8992 p = round_robin[x]?round_robin[x]->next:iflist;
8993 if (!p)
8994 p = iflist;
8996 roundrobin = 1;
8998 } else {
8999 char *stringp=NULL;
9000 stringp=dest;
9001 s = strsep(&stringp, "/");
9002 p = iflist;
9003 if (!strcasecmp(s, "pseudo")) {
9004 /* Special case for pseudo */
9005 x = CHAN_PSEUDO;
9006 channelmatch = x;
9008 #ifdef HAVE_PRI
9009 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
9010 if ((trunkgroup < 1) || (crv < 1)) {
9011 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
9012 return NULL;
9014 res--;
9015 for (x = 0; x < NUM_SPANS; x++) {
9016 if (pris[x].trunkgroup == trunkgroup) {
9017 pri = pris + x;
9018 lock = &pri->lock;
9019 start = pri->crvs;
9020 end = pri->crvend;
9021 break;
9024 if (!pri) {
9025 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
9026 return NULL;
9028 channelmatch = crv;
9029 p = pris[x].crvs;
9031 #endif
9032 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
9033 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
9034 return NULL;
9035 } else {
9036 channelmatch = x;
9039 /* Search for an unowned channel */
9040 ast_mutex_lock(lock);
9041 exitpvt = p;
9042 while (p && !tmp) {
9043 if (roundrobin)
9044 round_robin[x] = p;
9045 #if 0
9046 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
9047 #endif
9049 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
9050 ast_debug(1, "Using channel %d\n", p->channel);
9051 if (p->inalarm)
9052 goto next;
9054 callwait = (p->owner != NULL);
9055 #ifdef HAVE_PRI
9056 if (pri && (p->subs[SUB_REAL].zfd < 0)) {
9057 if (p->sig != SIG_FXSKS) {
9058 /* Gotta find an actual channel to use for this
9059 CRV if this isn't a callwait */
9060 bearer = pri_find_empty_chan(pri, 0);
9061 if (bearer < 0) {
9062 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
9063 p = NULL;
9064 break;
9066 pri_assign_bearer(p, pri, pri->pvts[bearer]);
9067 } else {
9068 if (alloc_sub(p, 0)) {
9069 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
9070 p = NULL;
9071 break;
9072 } else
9073 ast_debug(1, "Allocated placeholder pseudo channel\n");
9075 p->pri = pri;
9078 #endif
9079 if (p->channel == CHAN_PSEUDO) {
9080 p = chandup(p);
9081 if (!p) {
9082 break;
9085 if (p->owner) {
9086 if (alloc_sub(p, SUB_CALLWAIT)) {
9087 p = NULL;
9088 break;
9091 p->outgoing = 1;
9092 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
9093 #ifdef HAVE_PRI
9094 if (p->bearer) {
9095 /* Log owner to bearer channel, too */
9096 p->bearer->owner = tmp;
9098 #endif
9099 /* Make special notes */
9100 if (res > 1) {
9101 if (opt == 'c') {
9102 /* Confirm answer */
9103 p->confirmanswer = 1;
9104 } else if (opt == 'r') {
9105 /* Distinctive ring */
9106 if (res < 3)
9107 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
9108 else
9109 p->distinctivering = y;
9110 } else if (opt == 'd') {
9111 /* If this is an ISDN call, make it digital */
9112 p->digital = 1;
9113 if (tmp)
9114 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
9115 } else {
9116 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
9119 /* Note if the call is a call waiting call */
9120 if (tmp && callwait)
9121 tmp->cdrflags |= AST_CDR_CALLWAIT;
9122 break;
9124 next:
9125 if (backwards) {
9126 p = p->prev;
9127 if (!p)
9128 p = end;
9129 } else {
9130 p = p->next;
9131 if (!p)
9132 p = start;
9134 /* stop when you roll to the one that we started from */
9135 if (p == exitpvt)
9136 break;
9138 ast_mutex_unlock(lock);
9139 restart_monitor();
9140 if (callwait)
9141 *cause = AST_CAUSE_BUSY;
9142 else if (!tmp) {
9143 if (channelmatched) {
9144 if (busy)
9145 *cause = AST_CAUSE_BUSY;
9146 } else if (groupmatched) {
9147 *cause = AST_CAUSE_CONGESTION;
9151 return tmp;
9154 #if defined(HAVE_PRI) || defined(HAVE_SS7)
9155 static int dahdi_setlaw(int zfd, int law)
9157 return ioctl(zfd, DAHDI_SETLAW, &law);
9159 #endif
9161 #ifdef HAVE_SS7
9163 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
9165 int i;
9166 int winner = -1;
9167 for (i = 0; i < linkset->numchans; i++) {
9168 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
9169 winner = i;
9170 break;
9173 return winner;
9176 static void ss7_handle_cqm(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
9178 unsigned char status[32];
9179 struct dahdi_pvt *p = NULL;
9180 int i, offset;
9182 for (i = 0; i < linkset->numchans; i++) {
9183 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
9184 p = linkset->pvts[i];
9185 offset = p->cic - startcic;
9186 status[offset] = 0;
9187 if (p->locallyblocked)
9188 status[offset] |= (1 << 0) | (1 << 4);
9189 if (p->remotelyblocked)
9190 status[offset] |= (1 << 1) | (1 << 5);
9191 if (p->ss7call) {
9192 if (p->outgoing)
9193 status[offset] |= (1 << 3);
9194 else
9195 status[offset] |= (1 << 2);
9196 } else
9197 status[offset] |= 0x3 << 2;
9201 if (p)
9202 isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
9203 else
9204 ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
9208 static inline void ss7_block_cics(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
9210 int i;
9212 for (i = 0; i < linkset->numchans; i++) {
9213 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
9214 if (state) {
9215 if (state[i])
9216 linkset->pvts[i]->remotelyblocked = block;
9217 } else
9218 linkset->pvts[i]->remotelyblocked = block;
9223 static void ss7_inservice(struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
9225 int i;
9227 for (i = 0; i < linkset->numchans; i++) {
9228 if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
9229 linkset->pvts[i]->inservice = 1;
9233 static void ss7_reset_linkset(struct dahdi_ss7 *linkset)
9235 int i, startcic = -1, endcic, dpc;
9237 if (linkset->numchans <= 0)
9238 return;
9240 startcic = linkset->pvts[0]->cic;
9241 /* DB: CIC's DPC fix */
9242 dpc = linkset->pvts[0]->dpc;
9244 for (i = 0; i < linkset->numchans; i++) {
9245 if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
9246 continue;
9247 } else {
9248 endcic = linkset->pvts[i]->cic;
9249 ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
9250 isup_grs(linkset->ss7, startcic, endcic, dpc);
9252 /* DB: CIC's DPC fix */
9253 if (linkset->pvts[i+1]) {
9254 startcic = linkset->pvts[i+1]->cic;
9255 dpc = linkset->pvts[i+1]->dpc;
9261 static void dahdi_loopback(struct dahdi_pvt *p, int enable)
9263 if (p->loopedback != enable) {
9264 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_LOOPBACK, &enable)) {
9265 ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
9266 return;
9268 p->loopedback = enable;
9272 /* XXX: This function is assumed to be called with the private channel lock and linkset lock held */
9273 static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
9275 struct ss7 *ss7 = linkset->ss7;
9276 int res;
9277 int law = 1;
9278 struct ast_channel *c;
9279 char tmp[256];
9281 if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &law) == -1)
9282 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
9284 if (linkset->type == SS7_ITU)
9285 law = DAHDI_LAW_ALAW;
9286 else
9287 law = DAHDI_LAW_MULAW;
9289 res = dahdi_setlaw(p->subs[SUB_REAL].zfd, law);
9290 if (res < 0)
9291 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
9293 if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
9294 p->proceeding = 1;
9295 isup_acm(ss7, p->ss7call);
9298 ast_mutex_unlock(&linkset->lock);
9299 c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
9301 if (!c) {
9302 ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
9303 /* Holding this lock is assumed entering the function */
9304 ast_mutex_lock(&linkset->lock);
9305 return;
9306 } else
9307 ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
9309 dahdi_enable_ec(p);
9311 /* We only reference these variables in the context of the ss7_linkset function
9312 * when receiving either and IAM or a COT message. Since they are only accessed
9313 * from this context, we should be safe to unlock around them */
9315 ast_mutex_unlock(&p->lock);
9317 if (!ast_strlen_zero(p->charge_number)) {
9318 pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
9319 /* Clear this after we set it */
9320 p->charge_number[0] = 0;
9322 if (!ast_strlen_zero(p->gen_add_number)) {
9323 pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
9324 /* Clear this after we set it */
9325 p->gen_add_number[0] = 0;
9327 if (!ast_strlen_zero(p->jip_number)) {
9328 pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
9329 /* Clear this after we set it */
9330 p->jip_number[0] = 0;
9332 if (!ast_strlen_zero(p->gen_dig_number)) {
9333 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
9334 /* Clear this after we set it */
9335 p->gen_dig_number[0] = 0;
9337 if (!ast_strlen_zero(p->orig_called_num)) {
9338 pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
9339 /* Clear this after we set it */
9340 p->orig_called_num[0] = 0;
9343 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
9344 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
9345 /* Clear this after we set it */
9346 p->gen_dig_type = 0;
9348 snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
9349 pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
9350 /* Clear this after we set it */
9351 p->gen_dig_scheme = 0;
9353 if (!ast_strlen_zero(p->lspi_ident)) {
9354 pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
9355 /* Clear this after we set it */
9356 p->lspi_ident[0] = 0;
9359 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
9360 pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
9361 /* Clear this after we set it */
9362 p->call_ref_ident = 0;
9364 snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
9365 pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
9366 /* Clear this after we set it */
9367 p->call_ref_pc = 0;
9369 snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
9370 pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
9371 /* Clear this after we set it */
9372 p->calling_party_cat = 0;
9374 if (!ast_strlen_zero(p->redirecting_num)) {
9375 pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
9376 /* Clear this after we set it */
9377 p->redirecting_num[0] = 0;
9379 if (!ast_strlen_zero(p->generic_name)) {
9380 pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
9381 /* Clear this after we set it */
9382 p->generic_name[0] = 0;
9385 ast_mutex_lock(&p->lock);
9386 ast_mutex_lock(&linkset->lock);
9389 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
9391 switch (nai) {
9392 case SS7_NAI_INTERNATIONAL:
9393 snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
9394 break;
9395 case SS7_NAI_NATIONAL:
9396 snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
9397 break;
9398 case SS7_NAI_SUBSCRIBER:
9399 snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
9400 break;
9401 case SS7_NAI_UNKNOWN:
9402 snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
9403 break;
9404 default:
9405 snprintf(buf, size, "%s", number);
9406 break;
9409 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
9411 return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
9414 static void *ss7_linkset(void *data)
9416 int res, i;
9417 struct timeval *next = NULL, tv;
9418 struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
9419 struct ss7 *ss7 = linkset->ss7;
9420 ss7_event *e = NULL;
9421 struct dahdi_pvt *p;
9422 int chanpos;
9423 struct pollfd pollers[NUM_DCHANS];
9424 int cic;
9425 unsigned int dpc;
9426 int nextms = 0;
9428 ss7_start(ss7);
9430 while(1) {
9431 ast_mutex_lock(&linkset->lock);
9432 if ((next = ss7_schedule_next(ss7))) {
9433 tv = ast_tvnow();
9434 tv.tv_sec = next->tv_sec - tv.tv_sec;
9435 tv.tv_usec = next->tv_usec - tv.tv_usec;
9436 if (tv.tv_usec < 0) {
9437 tv.tv_usec += 1000000;
9438 tv.tv_sec -= 1;
9440 if (tv.tv_sec < 0) {
9441 tv.tv_sec = 0;
9442 tv.tv_usec = 0;
9444 nextms = tv.tv_sec * 1000;
9445 nextms += tv.tv_usec / 1000;
9447 ast_mutex_unlock(&linkset->lock);
9449 for (i = 0; i < linkset->numsigchans; i++) {
9450 pollers[i].fd = linkset->fds[i];
9451 pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
9452 pollers[i].revents = 0;
9455 res = poll(pollers, linkset->numsigchans, nextms);
9456 if ((res < 0) && (errno != EINTR)) {
9457 ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
9458 } else if (!res) {
9459 ast_mutex_lock(&linkset->lock);
9460 ss7_schedule_run(ss7);
9461 ast_mutex_unlock(&linkset->lock);
9462 continue;
9465 ast_mutex_lock(&linkset->lock);
9466 for (i = 0; i < linkset->numsigchans; i++) {
9467 if (pollers[i].revents & POLLPRI) {
9468 int x;
9469 if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
9470 ast_log(LOG_ERROR, "Error in exception retrieval!\n");
9472 switch (x) {
9473 case DAHDI_EVENT_OVERRUN:
9474 ast_debug(1, "Overrun detected!\n");
9475 break;
9476 case DAHDI_EVENT_BADFCS:
9477 ast_debug(1, "Bad FCS\n");
9478 break;
9479 case DAHDI_EVENT_ABORT:
9480 ast_debug(1, "HDLC Abort\n");
9481 break;
9482 case DAHDI_EVENT_ALARM:
9483 ast_log(LOG_ERROR, "Alarm on link!\n");
9484 linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
9485 linkset->linkstate[i] &= ~LINKSTATE_UP;
9486 ss7_link_alarm(ss7, pollers[i].fd);
9487 break;
9488 case DAHDI_EVENT_NOALARM:
9489 ast_log(LOG_ERROR, "Alarm cleared on link\n");
9490 linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
9491 linkset->linkstate[i] |= LINKSTATE_STARTING;
9492 ss7_link_noalarm(ss7, pollers[i].fd);
9493 break;
9494 default:
9495 ast_log(LOG_ERROR, "Got exception %d!\n", x);
9496 break;
9500 if (pollers[i].revents & POLLIN) {
9501 ast_mutex_lock(&linkset->lock);
9502 res = ss7_read(ss7, pollers[i].fd);
9503 ast_mutex_unlock(&linkset->lock);
9506 if (pollers[i].revents & POLLOUT) {
9507 ast_mutex_lock(&linkset->lock);
9508 res = ss7_write(ss7, pollers[i].fd);
9509 ast_mutex_unlock(&linkset->lock);
9510 if (res < 0) {
9511 ast_debug(1, "Error in write %s\n", strerror(errno));
9516 while ((e = ss7_check_event(ss7))) {
9517 switch (e->e) {
9518 case SS7_EVENT_UP:
9519 if (linkset->state != LINKSET_STATE_UP) {
9520 ast_verbose("--- SS7 Up ---\n");
9521 ss7_reset_linkset(linkset);
9523 linkset->state = LINKSET_STATE_UP;
9524 break;
9525 case SS7_EVENT_DOWN:
9526 ast_verbose("--- SS7 Down ---\n");
9527 linkset->state = LINKSET_STATE_DOWN;
9528 for (i = 0; i < linkset->numchans; i++) {
9529 struct dahdi_pvt *p = linkset->pvts[i];
9530 if (p)
9531 p->inalarm = 1;
9533 break;
9534 case MTP2_LINK_UP:
9535 ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
9536 break;
9537 case MTP2_LINK_DOWN:
9538 ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
9539 break;
9540 case ISUP_EVENT_CPG:
9541 chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
9542 if (chanpos < 0) {
9543 ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
9544 break;
9546 p = linkset->pvts[chanpos];
9547 ast_mutex_lock(&p->lock);
9548 switch (e->cpg.event) {
9549 case CPG_EVENT_ALERTING:
9550 p->alerting = 1;
9551 p->subs[SUB_REAL].needringing = 1;
9552 break;
9553 case CPG_EVENT_PROGRESS:
9554 case CPG_EVENT_INBANDINFO:
9556 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9557 ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
9558 dahdi_queue_frame(p, &f, linkset);
9559 p->progress = 1;
9560 if (p->dsp && p->dsp_features) {
9561 ast_dsp_set_features(p->dsp, p->dsp_features);
9562 p->dsp_features = 0;
9565 break;
9566 default:
9567 ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
9570 ast_mutex_unlock(&p->lock);
9571 break;
9572 case ISUP_EVENT_RSC:
9573 ast_verbose("Resetting CIC %d\n", e->rsc.cic);
9574 chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
9575 if (chanpos < 0) {
9576 ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
9577 break;
9579 p = linkset->pvts[chanpos];
9580 ast_mutex_lock(&p->lock);
9581 p->inservice = 1;
9582 p->remotelyblocked = 0;
9583 dpc = p->dpc;
9584 isup_set_call_dpc(e->rsc.call, dpc);
9585 if (p->ss7call)
9586 p->ss7call = NULL;
9587 if (p->owner)
9588 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9589 ast_mutex_unlock(&p->lock);
9590 isup_rlc(ss7, e->rsc.call);
9591 break;
9592 case ISUP_EVENT_GRS:
9593 ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
9594 chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
9595 if (chanpos < 0) {
9596 ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
9597 break;
9599 p = linkset->pvts[chanpos];
9600 isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
9601 ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
9602 break;
9603 case ISUP_EVENT_CQM:
9604 ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
9605 ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
9606 break;
9607 case ISUP_EVENT_GRA:
9608 ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
9609 ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
9610 ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
9611 break;
9612 case ISUP_EVENT_IAM:
9613 ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
9614 chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
9615 if (chanpos < 0) {
9616 ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
9617 isup_rel(ss7, e->iam.call, -1);
9618 break;
9620 p = linkset->pvts[chanpos];
9621 ast_mutex_lock(&p->lock);
9622 if (p->owner) {
9623 if (p->ss7call == e->iam.call) {
9624 ast_mutex_unlock(&p->lock);
9625 ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
9626 break;
9627 } else {
9628 ast_mutex_unlock(&p->lock);
9629 ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
9630 break;
9634 dpc = p->dpc;
9635 p->ss7call = e->iam.call;
9636 isup_set_call_dpc(p->ss7call, dpc);
9638 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
9639 ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
9640 p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
9641 } else
9642 p->cid_num[0] = 0;
9644 if (p->immediate) {
9645 p->exten[0] = 's';
9646 p->exten[1] = '\0';
9647 } else if (!ast_strlen_zero(e->iam.called_party_num)) {
9648 char *st;
9649 ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
9650 st = strchr(p->exten, '#');
9651 if (st)
9652 *st = '\0';
9653 } else
9654 p->exten[0] = '\0';
9656 p->cid_ani[0] = '\0';
9657 if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
9658 ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
9659 else
9660 p->cid_name[0] = '\0';
9662 p->cid_ani2 = e->iam.oli_ani2;
9663 p->cid_ton = 0;
9664 ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
9665 ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
9666 p->gen_add_type = e->iam.gen_add_type;
9667 p->gen_add_nai = e->iam.gen_add_nai;
9668 p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
9669 p->gen_add_num_plan = e->iam.gen_add_num_plan;
9670 ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
9671 p->gen_dig_type = e->iam.gen_dig_type;
9672 p->gen_dig_scheme = e->iam.gen_dig_scheme;
9673 ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
9674 ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
9675 ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
9676 ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
9677 p->calling_party_cat = e->iam.calling_party_cat;
9679 /* Set DNID */
9680 if (!ast_strlen_zero(e->iam.called_party_num))
9681 ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
9683 if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
9685 if (e->iam.cot_check_required) {
9686 dahdi_loopback(p, 1);
9687 } else
9688 ss7_start_call(p, linkset);
9689 } else {
9690 ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
9691 isup_rel(ss7, e->iam.call, -1);
9693 ast_mutex_unlock(&p->lock);
9694 break;
9695 case ISUP_EVENT_COT:
9696 chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
9697 if (chanpos < 0) {
9698 ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
9699 isup_rel(ss7, e->cot.call, -1);
9700 break;
9702 p = linkset->pvts[chanpos];
9704 ast_mutex_lock(&p->lock);
9706 if (p->loopedback) {
9707 dahdi_loopback(p, 0);
9708 ss7_start_call(p, linkset);
9711 ast_mutex_unlock(&p->lock);
9713 break;
9714 case ISUP_EVENT_CCR:
9715 ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
9716 chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
9717 if (chanpos < 0) {
9718 ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
9719 break;
9722 p = linkset->pvts[chanpos];
9724 ast_mutex_lock(&p->lock);
9725 dahdi_loopback(p, 1);
9726 ast_mutex_unlock(&p->lock);
9728 isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
9729 break;
9730 case ISUP_EVENT_CVT:
9731 ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
9732 chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
9733 if (chanpos < 0) {
9734 ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
9735 break;
9738 p = linkset->pvts[chanpos];
9740 ast_mutex_lock(&p->lock);
9741 dahdi_loopback(p, 1);
9742 ast_mutex_unlock(&p->lock);
9744 isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
9745 break;
9746 case ISUP_EVENT_REL:
9747 chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
9748 if (chanpos < 0) {
9749 ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
9750 break;
9752 p = linkset->pvts[chanpos];
9753 ast_mutex_lock(&p->lock);
9754 if (p->owner) {
9755 p->owner->hangupcause = e->rel.cause;
9756 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9757 } else
9758 ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
9760 /* End the loopback if we have one */
9761 dahdi_loopback(p, 0);
9763 isup_rlc(ss7, e->rel.call);
9764 p->ss7call = NULL;
9766 ast_mutex_unlock(&p->lock);
9767 break;
9768 case ISUP_EVENT_ACM:
9769 chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
9770 if (chanpos < 0) {
9771 ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
9772 isup_rel(ss7, e->acm.call, -1);
9773 break;
9774 } else {
9775 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9777 p = linkset->pvts[chanpos];
9779 ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
9781 if (e->acm.call_ref_ident > 0) {
9782 p->rlt = 1; /* Setting it but not using it here*/
9785 ast_mutex_lock(&p->lock);
9786 dahdi_queue_frame(p, &f, linkset);
9787 p->proceeding = 1;
9788 /* Send alerting if subscriber is free */
9789 if (e->acm.called_party_status_ind == 1) {
9790 p->alerting = 1;
9791 p->subs[SUB_REAL].needringing = 1;
9793 ast_mutex_unlock(&p->lock);
9795 break;
9796 case ISUP_EVENT_CGB:
9797 chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
9798 if (chanpos < 0) {
9799 ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
9800 break;
9802 p = linkset->pvts[chanpos];
9803 ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
9804 isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
9805 break;
9806 case ISUP_EVENT_CGU:
9807 chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
9808 if (chanpos < 0) {
9809 ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
9810 break;
9812 p = linkset->pvts[chanpos];
9813 ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
9814 isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
9815 break;
9816 case ISUP_EVENT_UCIC:
9817 chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
9818 if (chanpos < 0) {
9819 ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
9820 break;
9822 p = linkset->pvts[chanpos];
9823 ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
9824 ast_mutex_lock(&p->lock);
9825 p->remotelyblocked = 1;
9826 p->inservice = 0;
9827 ast_mutex_unlock(&p->lock); //doesn't require a SS7 acknowledgement
9828 break;
9829 case ISUP_EVENT_BLO:
9830 chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
9831 if (chanpos < 0) {
9832 ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
9833 break;
9835 p = linkset->pvts[chanpos];
9836 ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
9837 ast_mutex_lock(&p->lock);
9838 p->remotelyblocked = 1;
9839 ast_mutex_unlock(&p->lock);
9840 isup_bla(linkset->ss7, e->blo.cic, p->dpc);
9841 break;
9842 case ISUP_EVENT_BLA:
9843 chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
9844 if (chanpos < 0) {
9845 ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
9846 break;
9848 ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
9849 p = linkset->pvts[chanpos];
9850 ast_mutex_lock(&p->lock);
9851 p->locallyblocked = 1;
9852 ast_mutex_unlock(&p->lock);
9853 break;
9854 case ISUP_EVENT_UBL:
9855 chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
9856 if (chanpos < 0) {
9857 ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
9858 break;
9860 p = linkset->pvts[chanpos];
9861 ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
9862 ast_mutex_lock(&p->lock);
9863 p->remotelyblocked = 0;
9864 ast_mutex_unlock(&p->lock);
9865 isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
9866 break;
9867 case ISUP_EVENT_UBA:
9868 chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
9869 if (chanpos < 0) {
9870 ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
9871 break;
9873 p = linkset->pvts[chanpos];
9874 ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
9875 ast_mutex_lock(&p->lock);
9876 p->locallyblocked = 0;
9877 ast_mutex_unlock(&p->lock);
9878 break;
9879 case ISUP_EVENT_CON:
9880 case ISUP_EVENT_ANM:
9881 if (e->e == ISUP_EVENT_CON)
9882 cic = e->con.cic;
9883 else
9884 cic = e->anm.cic;
9886 chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
9887 if (chanpos < 0) {
9888 ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
9889 isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
9890 break;
9891 } else {
9892 p = linkset->pvts[chanpos];
9893 ast_mutex_lock(&p->lock);
9894 p->subs[SUB_REAL].needanswer = 1;
9895 if (p->dsp && p->dsp_features) {
9896 ast_dsp_set_features(p->dsp, p->dsp_features);
9897 p->dsp_features = 0;
9899 dahdi_enable_ec(p);
9900 ast_mutex_unlock(&p->lock);
9902 break;
9903 case ISUP_EVENT_RLC:
9904 chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
9905 if (chanpos < 0) {
9906 ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
9907 break;
9908 } else {
9909 p = linkset->pvts[chanpos];
9910 ast_mutex_lock(&p->lock);
9911 if (p->alreadyhungup)
9912 p->ss7call = NULL;
9913 else
9914 ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL. Ignoring.\n");
9915 ast_mutex_unlock(&p->lock);
9917 break;
9918 case ISUP_EVENT_FAA:
9919 chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
9920 if (chanpos < 0) {
9921 ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
9922 break;
9923 } else {
9924 p = linkset->pvts[chanpos];
9925 ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
9926 ast_mutex_lock(&p->lock);
9927 if (p->alreadyhungup){
9928 p->ss7call = NULL;
9929 ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
9931 ast_mutex_unlock(&p->lock);
9933 break;
9934 default:
9935 ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
9936 break;
9939 ast_mutex_unlock(&linkset->lock);
9942 return 0;
9945 static void dahdi_ss7_message(struct ss7 *ss7, char *s)
9947 #if 0
9948 int i;
9950 for (i = 0; i < NUM_SPANS; i++)
9951 if (linksets[i].ss7 == ss7)
9952 break;
9954 ast_verbose("[%d] %s", i+1, s);
9955 #else
9956 ast_verbose("%s", s);
9957 #endif
9960 static void dahdi_ss7_error(struct ss7 *ss7, char *s)
9962 #if 0
9963 int i;
9965 for (i = 0; i < NUM_SPANS; i++)
9966 if (linksets[i].ss7 == ss7)
9967 break;
9969 #else
9970 ast_log(LOG_ERROR, "%s", s);
9971 #endif
9974 #endif /* HAVE_SS7 */
9976 #ifdef HAVE_PRI
9977 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
9979 struct dahdi_pvt *p;
9980 p = pri->crvs;
9981 while (p) {
9982 if (p->channel == crv)
9983 return p;
9984 p = p->next;
9986 return NULL;
9990 static int pri_find_principle(struct dahdi_pri *pri, int channel)
9992 int x;
9993 int span = PRI_SPAN(channel);
9994 int spanfd;
9995 struct dahdi_params param;
9996 int principle = -1;
9997 int explicit = PRI_EXPLICIT(channel);
9998 channel = PRI_CHANNEL(channel);
10000 if (!explicit) {
10001 spanfd = pri_active_dchan_fd(pri);
10002 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10003 return -1;
10004 span = pris[param.spanno - 1].prilogicalspan;
10007 for (x = 0; x < pri->numchans; x++) {
10008 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10009 principle = x;
10010 break;
10014 return principle;
10017 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
10019 int x;
10020 struct dahdi_pvt *crv;
10021 if (!c) {
10022 if (principle < 0)
10023 return -1;
10024 return principle;
10026 if ((principle > -1) &&
10027 (principle < pri->numchans) &&
10028 (pri->pvts[principle]) &&
10029 (pri->pvts[principle]->call == c))
10030 return principle;
10031 /* First, check for other bearers */
10032 for (x = 0; x < pri->numchans; x++) {
10033 if (!pri->pvts[x])
10034 continue;
10035 if (pri->pvts[x]->call == c) {
10036 /* Found our call */
10037 if (principle != x) {
10038 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10040 ast_verb(3, "Moving call from channel %d to channel %d\n",
10041 old->channel, new->channel);
10042 if (new->owner) {
10043 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10044 old->channel, new->channel, new->channel);
10045 return -1;
10047 /* Fix it all up now */
10048 new->owner = old->owner;
10049 old->owner = NULL;
10050 if (new->owner) {
10051 ast_string_field_build(new->owner, name,
10052 "DAHDI/%d:%d-%d", pri->trunkgroup,
10053 new->channel, 1);
10054 new->owner->tech_pvt = new;
10055 ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].zfd);
10056 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10057 old->subs[SUB_REAL].owner = NULL;
10058 } else
10059 ast_log(LOG_WARNING, "Whoa, there's no owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
10060 new->call = old->call;
10061 old->call = NULL;
10063 /* Copy any DSP that may be present */
10064 new->dsp = old->dsp;
10065 new->dsp_features = old->dsp_features;
10066 old->dsp = NULL;
10067 old->dsp_features = 0;
10069 return principle;
10072 /* Now check for a CRV with no bearer */
10073 crv = pri->crvs;
10074 while (crv) {
10075 if (crv->call == c) {
10076 /* This is our match... Perform some basic checks */
10077 if (crv->bearer)
10078 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10079 else if (pri->pvts[principle]->owner)
10080 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10081 else {
10082 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
10083 wakeup the potential sleeper */
10084 dahdi_close(crv->subs[SUB_REAL].zfd);
10085 pri->pvts[principle]->call = crv->call;
10086 pri_assign_bearer(crv, pri, pri->pvts[principle]);
10087 ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10088 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10089 pri->trunkgroup, crv->channel);
10090 wakeup_sub(crv, SUB_REAL, pri);
10092 return principle;
10094 crv = crv->next;
10096 ast_log(LOG_WARNING, "Call specified, but not found?\n");
10097 return -1;
10100 static void *do_idle_thread(void *vchan)
10102 struct ast_channel *chan = vchan;
10103 struct dahdi_pvt *pvt = chan->tech_pvt;
10104 struct ast_frame *f;
10105 char ex[80];
10106 /* Wait up to 30 seconds for an answer */
10107 int newms, ms = 30000;
10108 ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10109 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10110 if (ast_call(chan, ex, 0)) {
10111 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10112 ast_hangup(chan);
10113 return NULL;
10115 while ((newms = ast_waitfor(chan, ms)) > 0) {
10116 f = ast_read(chan);
10117 if (!f) {
10118 /* Got hangup */
10119 break;
10121 if (f->frametype == AST_FRAME_CONTROL) {
10122 switch (f->subclass) {
10123 case AST_CONTROL_ANSWER:
10124 /* Launch the PBX */
10125 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10126 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10127 chan->priority = 1;
10128 ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10129 ast_pbx_run(chan);
10130 /* It's already hungup, return immediately */
10131 return NULL;
10132 case AST_CONTROL_BUSY:
10133 ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10134 break;
10135 case AST_CONTROL_CONGESTION:
10136 ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10137 break;
10140 ast_frfree(f);
10141 ms = newms;
10143 /* Hangup the channel since nothing happend */
10144 ast_hangup(chan);
10145 return NULL;
10148 #ifndef PRI_RESTART
10149 #error "Upgrade your libpri"
10150 #endif
10151 static void dahdi_pri_message(struct pri *pri, char *s)
10153 int x, y;
10154 int dchan = -1, span = -1;
10155 int dchancount = 0;
10157 if (pri) {
10158 for (x = 0; x < NUM_SPANS; x++) {
10159 for (y = 0; y < NUM_DCHANS; y++) {
10160 if (pris[x].dchans[y])
10161 dchancount++;
10163 if (pris[x].dchans[y] == pri)
10164 dchan = y;
10166 if (dchan >= 0) {
10167 span = x;
10168 break;
10170 dchancount = 0;
10172 if (dchancount > 1 && (span > -1))
10173 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10174 else
10175 ast_verbose("%s", s);
10176 } else
10177 ast_verbose("%s", s);
10179 ast_mutex_lock(&pridebugfdlock);
10181 if (pridebugfd >= 0)
10182 write(pridebugfd, s, strlen(s));
10184 ast_mutex_unlock(&pridebugfdlock);
10187 static void dahdi_pri_error(struct pri *pri, char *s)
10189 int x, y;
10190 int dchan = -1, span = -1;
10191 int dchancount = 0;
10193 if (pri) {
10194 for (x = 0; x < NUM_SPANS; x++) {
10195 for (y = 0; y < NUM_DCHANS; y++) {
10196 if (pris[x].dchans[y])
10197 dchancount++;
10199 if (pris[x].dchans[y] == pri)
10200 dchan = y;
10202 if (dchan >= 0) {
10203 span = x;
10204 break;
10206 dchancount = 0;
10208 if ((dchancount > 1) && (span > -1))
10209 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10210 else
10211 ast_log(LOG_ERROR, "%s", s);
10212 } else
10213 ast_log(LOG_ERROR, "%s", s);
10215 ast_mutex_lock(&pridebugfdlock);
10217 if (pridebugfd >= 0)
10218 write(pridebugfd, s, strlen(s));
10220 ast_mutex_unlock(&pridebugfdlock);
10223 static int pri_check_restart(struct dahdi_pri *pri)
10225 do {
10226 pri->resetpos++;
10227 } while ((pri->resetpos < pri->numchans) &&
10228 (!pri->pvts[pri->resetpos] ||
10229 pri->pvts[pri->resetpos]->call ||
10230 pri->pvts[pri->resetpos]->resetting));
10231 if (pri->resetpos < pri->numchans) {
10232 /* Mark the channel as resetting and restart it */
10233 pri->pvts[pri->resetpos]->resetting = 1;
10234 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10235 } else {
10236 pri->resetting = 0;
10237 time(&pri->lastreset);
10239 return 0;
10242 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
10244 int x;
10245 int redo;
10246 ast_mutex_unlock(&pri->lock);
10247 ast_mutex_lock(&p->lock);
10248 do {
10249 redo = 0;
10250 for (x = 0; x < 3; x++) {
10251 while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10252 redo++;
10253 DEADLOCK_AVOIDANCE(&p->lock);
10255 if (p->subs[x].owner) {
10256 ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10257 ast_channel_unlock(p->subs[x].owner);
10260 } while (redo);
10261 ast_mutex_unlock(&p->lock);
10262 ast_mutex_lock(&pri->lock);
10263 return 0;
10266 static char * redirectingreason2str(int redirectingreason)
10268 switch (redirectingreason) {
10269 case 0:
10270 return "UNKNOWN";
10271 case 1:
10272 return "BUSY";
10273 case 2:
10274 return "NO_REPLY";
10275 case 0xF:
10276 return "UNCONDITIONAL";
10277 default:
10278 return "NOREDIRECT";
10282 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
10284 if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10285 snprintf(buf, size, "%s", number);
10286 return;
10288 switch (plan) {
10289 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10290 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10291 break;
10292 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10293 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10294 break;
10295 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10296 snprintf(buf, size, "%s%s", pri->localprefix, number);
10297 break;
10298 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10299 snprintf(buf, size, "%s%s", pri->privateprefix, number);
10300 break;
10301 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10302 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10303 break;
10304 default: /* other Q.931 dialplan => don't twiddle with callingnum */
10305 snprintf(buf, size, "%s", number);
10306 break;
10311 static void *pri_dchannel(void *vpri)
10313 struct dahdi_pri *pri = vpri;
10314 pri_event *e;
10315 struct pollfd fds[NUM_DCHANS];
10316 int res;
10317 int chanpos = 0;
10318 int x;
10319 int haveidles;
10320 int activeidles;
10321 int nextidle = -1;
10322 struct ast_channel *c;
10323 struct timeval tv, lowest, *next;
10324 struct timeval lastidle = ast_tvnow();
10325 int doidling=0;
10326 char *cc;
10327 char idlen[80];
10328 struct ast_channel *idle;
10329 pthread_t p;
10330 time_t t;
10331 int i, which=-1;
10332 int numdchans;
10333 int cause=0;
10334 struct dahdi_pvt *crv;
10335 pthread_t threadid;
10336 char ani2str[6];
10337 char plancallingnum[256];
10338 char plancallingani[256];
10339 char calledtonstr[10];
10341 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10342 /* Need to do idle dialing, check to be sure though */
10343 cc = strchr(pri->idleext, '@');
10344 if (cc) {
10345 *cc = '\0';
10346 cc++;
10347 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10348 #if 0
10349 /* Extensions may not be loaded yet */
10350 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10351 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10352 else
10353 #endif
10354 doidling = 1;
10355 } else
10356 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10358 for (;;) {
10359 for (i = 0; i < NUM_DCHANS; i++) {
10360 if (!pri->dchannels[i])
10361 break;
10362 fds[i].fd = pri->fds[i];
10363 fds[i].events = POLLIN | POLLPRI;
10364 fds[i].revents = 0;
10366 numdchans = i;
10367 time(&t);
10368 ast_mutex_lock(&pri->lock);
10369 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10370 if (pri->resetting && pri_is_up(pri)) {
10371 if (pri->resetpos < 0)
10372 pri_check_restart(pri);
10373 } else {
10374 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
10375 pri->resetting = 1;
10376 pri->resetpos = -1;
10380 /* Look for any idle channels if appropriate */
10381 if (doidling && pri_is_up(pri)) {
10382 nextidle = -1;
10383 haveidles = 0;
10384 activeidles = 0;
10385 for (x = pri->numchans; x >= 0; x--) {
10386 if (pri->pvts[x] && !pri->pvts[x]->owner &&
10387 !pri->pvts[x]->call) {
10388 if (haveidles < pri->minunused) {
10389 haveidles++;
10390 } else if (!pri->pvts[x]->resetting) {
10391 nextidle = x;
10392 break;
10394 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10395 activeidles++;
10397 if (nextidle > -1) {
10398 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10399 /* Don't create a new idle call more than once per second */
10400 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10401 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10402 if (idle) {
10403 pri->pvts[nextidle]->isidlecall = 1;
10404 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10405 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10406 dahdi_hangup(idle);
10408 } else
10409 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10410 lastidle = ast_tvnow();
10412 } else if ((haveidles < pri->minunused) &&
10413 (activeidles > pri->minidle)) {
10414 /* Mark something for hangup if there is something
10415 that can be hungup */
10416 for (x = pri->numchans; x >= 0; x--) {
10417 /* find a candidate channel */
10418 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10419 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10420 haveidles++;
10421 /* Stop if we have enough idle channels or
10422 can't spare any more active idle ones */
10423 if ((haveidles >= pri->minunused) ||
10424 (activeidles <= pri->minidle))
10425 break;
10430 /* Start with reasonable max */
10431 lowest = ast_tv(60, 0);
10432 for (i = 0; i < NUM_DCHANS; i++) {
10433 /* Find lowest available d-channel */
10434 if (!pri->dchannels[i])
10435 break;
10436 if ((next = pri_schedule_next(pri->dchans[i]))) {
10437 /* We need relative time here */
10438 tv = ast_tvsub(*next, ast_tvnow());
10439 if (tv.tv_sec < 0) {
10440 tv = ast_tv(0,0);
10442 if (doidling || pri->resetting) {
10443 if (tv.tv_sec > 1) {
10444 tv = ast_tv(1, 0);
10446 } else {
10447 if (tv.tv_sec > 60) {
10448 tv = ast_tv(60, 0);
10451 } else if (doidling || pri->resetting) {
10452 /* Make sure we stop at least once per second if we're
10453 monitoring idle channels */
10454 tv = ast_tv(1,0);
10455 } else {
10456 /* Don't poll for more than 60 seconds */
10457 tv = ast_tv(60, 0);
10459 if (!i || ast_tvcmp(tv, lowest) < 0) {
10460 lowest = tv;
10463 ast_mutex_unlock(&pri->lock);
10465 e = NULL;
10466 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
10468 ast_mutex_lock(&pri->lock);
10469 if (!res) {
10470 for (which = 0; which < NUM_DCHANS; which++) {
10471 if (!pri->dchans[which])
10472 break;
10473 /* Just a timeout, run the scheduler */
10474 e = pri_schedule_run(pri->dchans[which]);
10475 if (e)
10476 break;
10478 } else if (res > -1) {
10479 for (which = 0; which < NUM_DCHANS; which++) {
10480 if (!pri->dchans[which])
10481 break;
10482 if (fds[which].revents & POLLPRI) {
10483 /* Check for an event */
10484 x = 0;
10485 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
10486 if (x) {
10487 ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
10488 manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
10489 "PRIEvent: %s\r\n"
10490 "PRIEventCode: %d\r\n"
10491 "D-channel: %s\r\n"
10492 "Span: %d\r\n",
10493 event2str(x),
10495 pri_order(which),
10496 pri->span
10499 /* Keep track of alarm state */
10500 if (x == DAHDI_EVENT_ALARM) {
10501 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
10502 pri_find_dchan(pri);
10503 } else if (x == DAHDI_EVENT_NOALARM) {
10504 pri->dchanavail[which] |= DCHAN_NOTINALARM;
10505 pri_restart(pri->dchans[which]);
10508 ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
10509 } else if (fds[which].revents & POLLIN) {
10510 e = pri_check_event(pri->dchans[which]);
10512 if (e)
10513 break;
10515 } else if (errno != EINTR)
10516 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
10518 if (e) {
10519 if (pri->debug)
10520 pri_dump_event(pri->dchans[which], e);
10522 if (e->e != PRI_EVENT_DCHAN_DOWN) {
10523 if (!(pri->dchanavail[which] & DCHAN_UP)) {
10524 ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
10526 pri->dchanavail[which] |= DCHAN_UP;
10527 } else {
10528 if (pri->dchanavail[which] & DCHAN_UP) {
10529 ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
10531 pri->dchanavail[which] &= ~DCHAN_UP;
10534 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
10535 /* Must be an NFAS group that has the secondary dchan active */
10536 pri->pri = pri->dchans[which];
10538 switch (e->e) {
10539 case PRI_EVENT_DCHAN_UP:
10540 if (!pri->pri) pri_find_dchan(pri);
10542 /* Note presense of D-channel */
10543 time(&pri->lastreset);
10545 /* Restart in 5 seconds */
10546 if (pri->resetinterval > -1) {
10547 pri->lastreset -= pri->resetinterval;
10548 pri->lastreset += 5;
10550 pri->resetting = 0;
10551 /* Take the channels from inalarm condition */
10552 for (i = 0; i < pri->numchans; i++)
10553 if (pri->pvts[i]) {
10554 pri->pvts[i]->inalarm = 0;
10556 break;
10557 case PRI_EVENT_DCHAN_DOWN:
10558 pri_find_dchan(pri);
10559 if (!pri_is_up(pri)) {
10560 pri->resetting = 0;
10561 /* Hangup active channels and put them in alarm mode */
10562 for (i = 0; i < pri->numchans; i++) {
10563 struct dahdi_pvt *p = pri->pvts[i];
10564 if (p) {
10565 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
10566 /* T309 is not enabled : hangup calls when alarm occurs */
10567 if (p->call) {
10568 if (p->pri && p->pri->pri) {
10569 pri_hangup(p->pri->pri, p->call, -1);
10570 pri_destroycall(p->pri->pri, p->call);
10571 p->call = NULL;
10572 } else
10573 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
10575 if (p->realcall) {
10576 pri_hangup_all(p->realcall, pri);
10577 } else if (p->owner)
10578 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10580 p->inalarm = 1;
10584 break;
10585 case PRI_EVENT_RESTART:
10586 if (e->restart.channel > -1) {
10587 chanpos = pri_find_principle(pri, e->restart.channel);
10588 if (chanpos < 0)
10589 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
10590 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10591 else {
10592 ast_verb(3, "B-channel %d/%d restarted on span %d\n",
10593 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
10594 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10595 if (pri->pvts[chanpos]->call) {
10596 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
10597 pri->pvts[chanpos]->call = NULL;
10599 /* Force soft hangup if appropriate */
10600 if (pri->pvts[chanpos]->realcall)
10601 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10602 else if (pri->pvts[chanpos]->owner)
10603 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10604 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10606 } else {
10607 ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
10608 for (x = 0; x < pri->numchans; x++)
10609 if (pri->pvts[x]) {
10610 ast_mutex_lock(&pri->pvts[x]->lock);
10611 if (pri->pvts[x]->call) {
10612 pri_destroycall(pri->pri, pri->pvts[x]->call);
10613 pri->pvts[x]->call = NULL;
10615 if (pri->pvts[chanpos]->realcall)
10616 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10617 else if (pri->pvts[x]->owner)
10618 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10619 ast_mutex_unlock(&pri->pvts[x]->lock);
10622 break;
10623 case PRI_EVENT_KEYPAD_DIGIT:
10624 chanpos = pri_find_principle(pri, e->digit.channel);
10625 if (chanpos < 0) {
10626 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
10627 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
10628 } else {
10629 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
10630 if (chanpos > -1) {
10631 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10632 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
10633 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
10634 /* how to do that */
10635 int digitlen = strlen(e->digit.digits);
10636 char digit;
10637 int i;
10638 for (i = 0; i < digitlen; i++) {
10639 digit = e->digit.digits[i];
10641 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10642 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10646 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10649 break;
10651 case PRI_EVENT_INFO_RECEIVED:
10652 chanpos = pri_find_principle(pri, e->ring.channel);
10653 if (chanpos < 0) {
10654 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
10655 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10656 } else {
10657 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
10658 if (chanpos > -1) {
10659 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10660 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
10661 if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
10662 /* how to do that */
10663 int digitlen = strlen(e->ring.callednum);
10664 char digit;
10665 int i;
10666 for (i = 0; i < digitlen; i++) {
10667 digit = e->ring.callednum[i];
10669 struct ast_frame f = { AST_FRAME_DTMF, digit, };
10670 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10674 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10677 break;
10678 case PRI_EVENT_RING:
10679 crv = NULL;
10680 if (e->ring.channel == -1)
10681 chanpos = pri_find_empty_chan(pri, 1);
10682 else
10683 chanpos = pri_find_principle(pri, e->ring.channel);
10684 /* if no channel specified find one empty */
10685 if (chanpos < 0) {
10686 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
10687 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10688 } else {
10689 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10690 if (pri->pvts[chanpos]->owner) {
10691 if (pri->pvts[chanpos]->call == e->ring.call) {
10692 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
10693 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10694 break;
10695 } else {
10696 /* This is where we handle initial glare */
10697 ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
10698 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
10699 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10700 chanpos = -1;
10703 if (chanpos > -1)
10704 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10706 if ((chanpos < 0) && (e->ring.flexible))
10707 chanpos = pri_find_empty_chan(pri, 1);
10708 if (chanpos > -1) {
10709 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10710 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
10711 /* Should be safe to lock CRV AFAIK while bearer is still locked */
10712 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
10713 if (crv)
10714 ast_mutex_lock(&crv->lock);
10715 if (!crv || crv->owner) {
10716 pri->pvts[chanpos]->call = NULL;
10717 if (crv) {
10718 if (crv->owner)
10719 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10720 ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10721 } else
10722 ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
10723 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
10724 if (crv)
10725 ast_mutex_unlock(&crv->lock);
10726 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10727 break;
10730 pri->pvts[chanpos]->call = e->ring.call;
10731 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
10732 if (pri->pvts[chanpos]->use_callerid) {
10733 ast_shrink_phone_number(plancallingnum);
10734 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
10735 #ifdef PRI_ANI
10736 if (!ast_strlen_zero(e->ring.callingani)) {
10737 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
10738 ast_shrink_phone_number(plancallingani);
10739 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
10740 } else {
10741 pri->pvts[chanpos]->cid_ani[0] = '\0';
10743 #endif
10744 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
10745 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
10746 } else {
10747 pri->pvts[chanpos]->cid_num[0] = '\0';
10748 pri->pvts[chanpos]->cid_ani[0] = '\0';
10749 pri->pvts[chanpos]->cid_name[0] = '\0';
10750 pri->pvts[chanpos]->cid_ton = 0;
10752 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
10753 e->ring.redirectingnum, e->ring.callingplanrdnis);
10754 /* If immediate=yes go to s|1 */
10755 if (pri->pvts[chanpos]->immediate) {
10756 ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
10757 pri->pvts[chanpos]->exten[0] = 's';
10758 pri->pvts[chanpos]->exten[1] = '\0';
10760 /* Get called number */
10761 else if (!ast_strlen_zero(e->ring.callednum)) {
10762 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
10763 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10764 } else if (pri->overlapdial)
10765 pri->pvts[chanpos]->exten[0] = '\0';
10766 else {
10767 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
10768 pri->pvts[chanpos]->exten[0] = 's';
10769 pri->pvts[chanpos]->exten[1] = '\0';
10771 /* Set DNID on all incoming calls -- even immediate */
10772 if (!ast_strlen_zero(e->ring.callednum))
10773 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
10774 /* No number yet, but received "sending complete"? */
10775 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
10776 ast_verb(3, "Going to extension s|1 because of Complete received\n");
10777 pri->pvts[chanpos]->exten[0] = 's';
10778 pri->pvts[chanpos]->exten[1] = '\0';
10780 /* Make sure extension exists (or in overlap dial mode, can exist) */
10781 if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
10782 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10783 /* Setup law */
10784 int law;
10785 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
10786 /* Set to audio mode at this point */
10787 law = 1;
10788 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &law) == -1)
10789 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
10791 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
10792 law = DAHDI_LAW_ALAW;
10793 else
10794 law = DAHDI_LAW_MULAW;
10795 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].zfd, law);
10796 if (res < 0)
10797 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
10798 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10799 if (res < 0)
10800 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
10801 if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
10802 /* Just announce proceeding */
10803 pri->pvts[chanpos]->proceeding = 1;
10804 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
10805 } else {
10806 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
10807 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10808 else
10809 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
10811 /* Get the use_callingpres state */
10812 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
10814 /* Start PBX */
10815 if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
10816 /* Release the PRI lock while we create the channel */
10817 ast_mutex_unlock(&pri->lock);
10818 if (crv) {
10819 /* Set bearer and such */
10820 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
10821 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10822 pri->pvts[chanpos]->owner = &inuse;
10823 ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
10824 } else {
10825 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
10828 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10830 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
10831 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
10833 if (e->ring.ani2 >= 0) {
10834 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
10835 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10836 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
10839 #ifdef SUPPORT_USERUSER
10840 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10841 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10843 #endif
10845 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10846 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10847 if (e->ring.redirectingreason >= 0)
10848 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10850 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10851 ast_mutex_lock(&pri->lock);
10852 if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
10853 ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
10854 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
10855 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10856 } else {
10857 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10858 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10859 if (c)
10860 ast_hangup(c);
10861 else {
10862 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10863 pri->pvts[chanpos]->call = NULL;
10866 } else {
10867 ast_mutex_unlock(&pri->lock);
10868 /* Release PRI lock while we create the channel */
10869 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
10870 if (c) {
10871 char calledtonstr[10];
10873 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10875 if (e->ring.ani2 >= 0) {
10876 snprintf(ani2str, 5, "%d", e->ring.ani2);
10877 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
10878 pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
10881 #ifdef SUPPORT_USERUSER
10882 if (!ast_strlen_zero(e->ring.useruserinfo)) {
10883 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
10885 #endif
10887 if (e->ring.redirectingreason >= 0)
10888 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
10890 snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
10891 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
10893 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10894 ast_mutex_lock(&pri->lock);
10896 ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
10897 plancallingnum, pri->pvts[chanpos]->exten,
10898 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10900 dahdi_enable_ec(pri->pvts[chanpos]);
10901 } else {
10903 ast_mutex_lock(&pri->lock);
10905 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
10906 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
10907 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
10908 pri->pvts[chanpos]->call = NULL;
10911 } else {
10912 ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
10913 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
10914 pri->pvts[chanpos]->prioffset, pri->span);
10915 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
10916 pri->pvts[chanpos]->call = NULL;
10917 pri->pvts[chanpos]->exten[0] = '\0';
10919 if (crv)
10920 ast_mutex_unlock(&crv->lock);
10921 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10922 } else {
10923 if (e->ring.flexible)
10924 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
10925 else
10926 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
10928 break;
10929 case PRI_EVENT_RINGING:
10930 chanpos = pri_find_principle(pri, e->ringing.channel);
10931 if (chanpos < 0) {
10932 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
10933 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10934 } else {
10935 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
10936 if (chanpos < 0) {
10937 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
10938 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
10939 } else {
10940 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10941 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10942 dahdi_enable_ec(pri->pvts[chanpos]);
10943 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
10944 pri->pvts[chanpos]->alerting = 1;
10945 } else
10946 ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
10948 #ifdef PRI_PROGRESS_MASK
10949 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10950 #else
10951 if (e->ringing.progress == 8) {
10952 #endif
10953 /* Now we can do call progress detection */
10954 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10955 /* RINGING detection isn't required because we got ALERTING signal */
10956 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
10957 pri->pvts[chanpos]->dsp_features = 0;
10961 #ifdef SUPPORT_USERUSER
10962 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
10963 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10964 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10965 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
10966 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10968 #endif
10970 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10973 break;
10974 case PRI_EVENT_PROGRESS:
10975 /* Get chan value if e->e is not PRI_EVNT_RINGING */
10976 chanpos = pri_find_principle(pri, e->proceeding.channel);
10977 if (chanpos > -1) {
10978 #ifdef PRI_PROGRESS_MASK
10979 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
10980 #else
10981 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
10982 #endif
10983 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10985 if (e->proceeding.cause > -1) {
10986 ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
10988 /* Work around broken, out of spec USER_BUSY cause in a progress message */
10989 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
10990 if (pri->pvts[chanpos]->owner) {
10991 ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
10993 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
10994 f.subclass = AST_CONTROL_BUSY;
10999 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11000 ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11001 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11002 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11003 #ifdef PRI_PROGRESS_MASK
11004 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11005 #else
11006 if (e->proceeding.progress == 8) {
11007 #endif
11008 /* Now we can do call progress detection */
11009 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11010 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11011 pri->pvts[chanpos]->dsp_features = 0;
11014 pri->pvts[chanpos]->progress = 1;
11015 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11018 break;
11019 case PRI_EVENT_PROCEEDING:
11020 chanpos = pri_find_principle(pri, e->proceeding.channel);
11021 if (chanpos > -1) {
11022 if (!pri->pvts[chanpos]->proceeding) {
11023 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11025 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11026 ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11027 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11028 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11029 #ifdef PRI_PROGRESS_MASK
11030 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11031 #else
11032 if (e->proceeding.progress == 8) {
11033 #endif
11034 /* Now we can do call progress detection */
11035 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11036 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11037 pri->pvts[chanpos]->dsp_features = 0;
11039 /* Bring voice path up */
11040 f.subclass = AST_CONTROL_PROGRESS;
11041 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11043 pri->pvts[chanpos]->proceeding = 1;
11044 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11047 break;
11048 case PRI_EVENT_FACNAME:
11049 chanpos = pri_find_principle(pri, e->facname.channel);
11050 if (chanpos < 0) {
11051 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
11052 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11053 } else {
11054 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11055 if (chanpos < 0) {
11056 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
11057 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11058 } else {
11059 /* Re-use *69 field for PRI */
11060 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11061 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11062 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11063 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11064 dahdi_enable_ec(pri->pvts[chanpos]);
11065 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11068 break;
11069 case PRI_EVENT_ANSWER:
11070 chanpos = pri_find_principle(pri, e->answer.channel);
11071 if (chanpos < 0) {
11072 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
11073 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11074 } else {
11075 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11076 if (chanpos < 0) {
11077 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
11078 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11079 } else {
11080 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11081 /* Now we can do call progress detection */
11083 /* We changed this so it turns on the DSP no matter what... progress or no progress.
11084 * By this time, we need DTMF detection and other features that were previously disabled
11085 * -- Matt F */
11086 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11087 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11088 pri->pvts[chanpos]->dsp_features = 0;
11090 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11091 ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11092 x = DAHDI_START;
11093 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
11094 if (res < 0) {
11095 if (errno != EINPROGRESS) {
11096 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11099 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11100 pri->pvts[chanpos]->dialing = 1;
11101 /* Send any "w" waited stuff */
11102 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11103 if (res < 0) {
11104 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11105 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11106 } else
11107 ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11109 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11110 } else if (pri->pvts[chanpos]->confirmanswer) {
11111 ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11112 } else {
11113 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11114 /* Enable echo cancellation if it's not on already */
11115 dahdi_enable_ec(pri->pvts[chanpos]);
11118 #ifdef SUPPORT_USERUSER
11119 if (!ast_strlen_zero(e->answer.useruserinfo)) {
11120 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11121 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11122 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11123 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11125 #endif
11127 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11130 break;
11131 case PRI_EVENT_HANGUP:
11132 chanpos = pri_find_principle(pri, e->hangup.channel);
11133 if (chanpos < 0) {
11134 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
11135 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11136 } else {
11137 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11138 if (chanpos > -1) {
11139 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11140 if (!pri->pvts[chanpos]->alreadyhungup) {
11141 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11142 pri->pvts[chanpos]->alreadyhungup = 1;
11143 if (pri->pvts[chanpos]->realcall)
11144 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11145 else if (pri->pvts[chanpos]->owner) {
11146 /* Queue a BUSY instead of a hangup if our cause is appropriate */
11147 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11148 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11149 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11150 else {
11151 switch (e->hangup.cause) {
11152 case PRI_CAUSE_USER_BUSY:
11153 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11154 break;
11155 case PRI_CAUSE_CALL_REJECTED:
11156 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11157 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11158 case PRI_CAUSE_SWITCH_CONGESTION:
11159 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11160 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11161 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11162 break;
11163 default:
11164 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11168 ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11169 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11170 } else {
11171 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11172 pri->pvts[chanpos]->call = NULL;
11174 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11175 ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11176 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11177 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11178 pri->pvts[chanpos]->resetting = 1;
11180 if (e->hangup.aoc_units > -1)
11181 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11182 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11184 #ifdef SUPPORT_USERUSER
11185 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11186 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11187 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11188 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11189 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11191 #endif
11193 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11194 } else {
11195 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
11196 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11199 break;
11200 #ifndef PRI_EVENT_HANGUP_REQ
11201 #error please update libpri
11202 #endif
11203 case PRI_EVENT_HANGUP_REQ:
11204 chanpos = pri_find_principle(pri, e->hangup.channel);
11205 if (chanpos < 0) {
11206 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
11207 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11208 } else {
11209 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11210 if (chanpos > -1) {
11211 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11212 if (pri->pvts[chanpos]->realcall)
11213 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11214 else if (pri->pvts[chanpos]->owner) {
11215 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11216 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11217 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11218 else {
11219 switch (e->hangup.cause) {
11220 case PRI_CAUSE_USER_BUSY:
11221 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11222 break;
11223 case PRI_CAUSE_CALL_REJECTED:
11224 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11225 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11226 case PRI_CAUSE_SWITCH_CONGESTION:
11227 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11228 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11229 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11230 break;
11231 default:
11232 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11235 ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
11236 if (e->hangup.aoc_units > -1)
11237 ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11238 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11239 } else {
11240 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11241 pri->pvts[chanpos]->call = NULL;
11243 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11244 ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11245 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11246 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11247 pri->pvts[chanpos]->resetting = 1;
11250 #ifdef SUPPORT_USERUSER
11251 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11252 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11253 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11254 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11255 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11257 #endif
11259 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11260 } else {
11261 ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11264 break;
11265 case PRI_EVENT_HANGUP_ACK:
11266 chanpos = pri_find_principle(pri, e->hangup.channel);
11267 if (chanpos < 0) {
11268 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
11269 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11270 } else {
11271 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11272 if (chanpos > -1) {
11273 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11274 pri->pvts[chanpos]->call = NULL;
11275 pri->pvts[chanpos]->resetting = 0;
11276 if (pri->pvts[chanpos]->owner) {
11277 ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11280 #ifdef SUPPORT_USERUSER
11281 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11282 struct ast_channel *owner = pri->pvts[chanpos]->owner;
11283 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11284 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11285 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11287 #endif
11289 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11292 break;
11293 case PRI_EVENT_CONFIG_ERR:
11294 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11295 break;
11296 case PRI_EVENT_RESTART_ACK:
11297 chanpos = pri_find_principle(pri, e->restartack.channel);
11298 if (chanpos < 0) {
11299 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11300 channel number, so we have to figure it out... This must be why
11301 everybody resets exactly a channel at a time. */
11302 for (x = 0; x < pri->numchans; x++) {
11303 if (pri->pvts[x] && pri->pvts[x]->resetting) {
11304 chanpos = x;
11305 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11306 ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
11307 pri->pvts[chanpos]->prioffset, pri->span);
11308 if (pri->pvts[chanpos]->realcall)
11309 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11310 else if (pri->pvts[chanpos]->owner) {
11311 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
11312 pri->pvts[chanpos]->prioffset, pri->span);
11313 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11315 pri->pvts[chanpos]->resetting = 0;
11316 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11317 pri->pvts[chanpos]->prioffset, pri->span);
11318 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11319 if (pri->resetting)
11320 pri_check_restart(pri);
11321 break;
11324 if (chanpos < 0) {
11325 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
11326 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11328 } else {
11329 if (pri->pvts[chanpos]) {
11330 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11331 if (pri->pvts[chanpos]->realcall)
11332 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11333 else if (pri->pvts[chanpos]->owner) {
11334 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11335 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11336 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11338 pri->pvts[chanpos]->resetting = 0;
11339 pri->pvts[chanpos]->inservice = 1;
11340 ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11341 pri->pvts[chanpos]->prioffset, pri->span);
11342 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11343 if (pri->resetting)
11344 pri_check_restart(pri);
11347 break;
11348 case PRI_EVENT_SETUP_ACK:
11349 chanpos = pri_find_principle(pri, e->setup_ack.channel);
11350 if (chanpos < 0) {
11351 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
11352 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11353 } else {
11354 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11355 if (chanpos > -1) {
11356 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11357 pri->pvts[chanpos]->setup_ack = 1;
11358 /* Send any queued digits */
11359 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11360 ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11361 pri_information(pri->pri, pri->pvts[chanpos]->call,
11362 pri->pvts[chanpos]->dialdest[x]);
11364 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11365 } else
11366 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11368 break;
11369 case PRI_EVENT_NOTIFY:
11370 chanpos = pri_find_principle(pri, e->notify.channel);
11371 if (chanpos < 0) {
11372 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11373 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11374 } else {
11375 struct ast_frame f = { AST_FRAME_CONTROL, };
11376 ast_mutex_lock(&pri->pvts[chanpos]->lock);
11377 switch (e->notify.info) {
11378 case PRI_NOTIFY_REMOTE_HOLD:
11379 f.subclass = AST_CONTROL_HOLD;
11380 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11381 break;
11382 case PRI_NOTIFY_REMOTE_RETRIEVAL:
11383 f.subclass = AST_CONTROL_UNHOLD;
11384 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11385 break;
11387 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11389 break;
11390 default:
11391 ast_debug(1, "Event: %d\n", e->e);
11394 ast_mutex_unlock(&pri->lock);
11396 /* Never reached */
11397 return NULL;
11400 static int start_pri(struct dahdi_pri *pri)
11402 int res, x;
11403 struct dahdi_params p;
11404 struct dahdi_bufferinfo bi;
11405 struct dahdi_spaninfo si;
11406 int i;
11408 for (i = 0; i < NUM_DCHANS; i++) {
11409 if (!pri->dchannels[i])
11410 break;
11411 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11412 x = pri->dchannels[i];
11413 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11414 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11415 return -1;
11417 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11418 if (res) {
11419 dahdi_close(pri->fds[i]);
11420 pri->fds[i] = -1;
11421 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11422 return -1;
11424 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11425 dahdi_close(pri->fds[i]);
11426 pri->fds[i] = -1;
11427 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
11428 return -1;
11430 memset(&si, 0, sizeof(si));
11431 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11432 if (res) {
11433 dahdi_close(pri->fds[i]);
11434 pri->fds[i] = -1;
11435 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11437 if (!si.alarms)
11438 pri->dchanavail[i] |= DCHAN_NOTINALARM;
11439 else
11440 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11441 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11442 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11443 bi.numbufs = 32;
11444 bi.bufsize = 1024;
11445 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11446 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11447 dahdi_close(pri->fds[i]);
11448 pri->fds[i] = -1;
11449 return -1;
11451 switch (pri->sig) {
11452 case SIG_BRI:
11453 pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
11454 break;
11455 case SIG_BRI_PTMP:
11456 pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
11457 break;
11458 default:
11459 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11461 /* Force overlap dial if we're doing GR-303! */
11462 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11463 pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11464 pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11465 #ifdef HAVE_PRI_INBANDDISCONNECT
11466 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11467 #endif
11468 /* Enslave to master if appropriate */
11469 if (i)
11470 pri_enslave(pri->dchans[0], pri->dchans[i]);
11471 if (!pri->dchans[i]) {
11472 dahdi_close(pri->fds[i]);
11473 pri->fds[i] = -1;
11474 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11475 return -1;
11477 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11478 pri_set_nsf(pri->dchans[i], pri->nsf);
11479 #ifdef PRI_GETSET_TIMERS
11480 for (x = 0; x < PRI_MAX_TIMERS; x++) {
11481 if (pritimers[x] != 0)
11482 pri_set_timer(pri->dchans[i], x, pritimers[x]);
11484 #endif
11486 /* Assume primary is the one we use */
11487 pri->pri = pri->dchans[0];
11488 pri->resetpos = -1;
11489 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11490 for (i = 0; i < NUM_DCHANS; i++) {
11491 if (!pri->dchannels[i])
11492 break;
11493 dahdi_close(pri->fds[i]);
11494 pri->fds[i] = -1;
11496 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11497 return -1;
11499 return 0;
11502 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
11504 int which, span;
11505 char *ret = NULL;
11507 if (pos != rpos)
11508 return ret;
11510 for (which = span = 0; span < NUM_SPANS; span++) {
11511 if (pris[span].pri && ++which > state) {
11512 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
11513 break;
11516 return ret;
11519 static char *complete_span_4(const char *line, const char *word, int pos, int state)
11521 return complete_span_helper(line,word,pos,state,3);
11524 static char *complete_span_5(const char *line, const char *word, int pos, int state)
11526 return complete_span_helper(line,word,pos,state,4);
11529 static char *handle_pri_unset_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11531 switch (cmd) {
11532 case CLI_INIT:
11533 e->command = "pri unset debug file";
11534 e->usage = "Usage: pri unset debug file\n"
11535 " Stop sending debug output to the previously \n"
11536 " specified file\n";
11537 return NULL;
11538 case CLI_GENERATE:
11539 return NULL;
11541 /* Assume it is unset */
11542 ast_mutex_lock(&pridebugfdlock);
11543 close(pridebugfd);
11544 pridebugfd = -1;
11545 ast_cli(a->fd, "PRI debug output to file disabled\n");
11546 ast_mutex_unlock(&pridebugfdlock);
11547 return CLI_SUCCESS;
11550 static char *handle_pri_set_debug_file(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11552 int myfd;
11553 switch (cmd) {
11554 case CLI_INIT:
11555 e->command = "pri set debug file";
11556 e->usage = "Usage: pri set debug file [output-file]\n"
11557 " Sends PRI debug output to the specified output file\n";
11558 return NULL;
11559 case CLI_GENERATE:
11560 return NULL;
11562 if (a->argc < 5)
11563 return CLI_SHOWUSAGE;
11565 if (ast_strlen_zero(a->argv[4]))
11566 return CLI_SHOWUSAGE;
11568 myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
11569 if (myfd < 0) {
11570 ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
11571 return CLI_SUCCESS;
11574 ast_mutex_lock(&pridebugfdlock);
11576 if (pridebugfd >= 0)
11577 close(pridebugfd);
11579 pridebugfd = myfd;
11580 ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
11581 ast_mutex_unlock(&pridebugfdlock);
11582 ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
11583 return CLI_SUCCESS;
11586 static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11588 int span;
11589 int x;
11590 switch (cmd) {
11591 case CLI_INIT:
11592 e->command = "pri debug span";
11593 e->usage =
11594 "Usage: pri debug span <span>\n"
11595 " Enables debugging on a given PRI span\n";
11596 return NULL;
11597 case CLI_GENERATE:
11598 return complete_span_4(a->line, a->word, a->pos, a->n);
11600 if (a->argc < 4) {
11601 return CLI_SHOWUSAGE;
11603 span = atoi(a->argv[3]);
11604 if ((span < 1) || (span > NUM_SPANS)) {
11605 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
11606 return CLI_SUCCESS;
11608 if (!pris[span-1].pri) {
11609 ast_cli(a->fd, "No PRI running on span %d\n", span);
11610 return CLI_SUCCESS;
11612 for (x = 0; x < NUM_DCHANS; x++) {
11613 if (pris[span-1].dchans[x])
11614 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11615 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11616 PRI_DEBUG_Q921_STATE);
11618 ast_cli(a->fd, "Enabled debugging on span %d\n", span);
11619 return CLI_SUCCESS;
11624 static char *handle_pri_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11626 int span;
11627 int x;
11628 switch (cmd) {
11629 case CLI_INIT:
11630 e->command = "pri no debug span";
11631 e->usage =
11632 "Usage: pri no debug span <span>\n"
11633 " Disables debugging on a given PRI span\n";
11634 return NULL;
11635 case CLI_GENERATE:
11636 return complete_span_5(a->line, a->word, a->pos, a->n);
11638 if (a->argc < 5)
11639 return CLI_SHOWUSAGE;
11641 span = atoi(a->argv[4]);
11642 if ((span < 1) || (span > NUM_SPANS)) {
11643 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
11644 return CLI_SUCCESS;
11646 if (!pris[span-1].pri) {
11647 ast_cli(a->fd, "No PRI running on span %d\n", span);
11648 return CLI_SUCCESS;
11650 for (x = 0; x < NUM_DCHANS; x++) {
11651 if (pris[span-1].dchans[x])
11652 pri_set_debug(pris[span-1].dchans[x], 0);
11654 ast_cli(a->fd, "Disabled debugging on span %d\n", span);
11655 return CLI_SUCCESS;
11658 static char *handle_pri_really_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11660 int span;
11661 int x;
11662 switch (cmd) {
11663 case CLI_INIT:
11664 e->command = "pri intensive debug span";
11665 e->usage =
11666 "Usage: pri intensive debug span <span>\n"
11667 " Enables debugging down to the Q.921 level\n";
11668 return NULL;
11669 case CLI_GENERATE:
11670 return complete_span_5(a->line, a->word, a->pos, a->n);
11673 if (a->argc < 5)
11674 return CLI_SHOWUSAGE;
11675 span = atoi(a->argv[4]);
11676 if ((span < 1) || (span > NUM_SPANS)) {
11677 ast_cli(a->fd, "Invalid span %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
11678 return CLI_SUCCESS;
11680 if (!pris[span-1].pri) {
11681 ast_cli(a->fd, "No PRI running on span %d\n", span);
11682 return CLI_SUCCESS;
11684 for (x = 0; x < NUM_DCHANS; x++) {
11685 if (pris[span-1].dchans[x])
11686 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11687 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11688 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11690 ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11691 return CLI_SUCCESS;
11694 static void build_status(char *s, size_t len, int status, int active)
11696 if (!s || len < 1) {
11697 return;
11699 s[0] = '\0';
11700 if (status & DCHAN_PROVISIONED)
11701 strncat(s, "Provisioned, ", len - strlen(s) - 1);
11702 if (!(status & DCHAN_NOTINALARM))
11703 strncat(s, "In Alarm, ", len - strlen(s) - 1);
11704 if (status & DCHAN_UP)
11705 strncat(s, "Up", len - strlen(s) - 1);
11706 else
11707 strncat(s, "Down", len - strlen(s) - 1);
11708 if (active)
11709 strncat(s, ", Active", len - strlen(s) - 1);
11710 else
11711 strncat(s, ", Standby", len - strlen(s) - 1);
11712 s[len - 1] = '\0';
11715 static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11717 int span;
11718 int x;
11719 char status[256];
11721 switch (cmd) {
11722 case CLI_INIT:
11723 e->command = "pri show spans";
11724 e->usage =
11725 "Usage: pri show spans\n"
11726 " Displays PRI Information\n";
11727 return NULL;
11728 case CLI_GENERATE:
11729 return NULL;
11732 if (a->argc != 3)
11733 return CLI_SHOWUSAGE;
11735 for (span = 0; span < NUM_SPANS; span++) {
11736 if (pris[span].pri) {
11737 for (x = 0; x < NUM_DCHANS; x++) {
11738 if (pris[span].dchannels[x]) {
11739 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11740 ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11745 return CLI_SUCCESS;
11748 static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11750 int span;
11751 int x;
11752 char status[256];
11753 switch (cmd) {
11754 case CLI_INIT:
11755 e->command = "pri show span";
11756 e->usage =
11757 "Usage: pri show span <span>\n"
11758 " Displays PRI Information on a given PRI span\n";
11759 return NULL;
11760 case CLI_GENERATE:
11761 return complete_span_4(a->line, a->word, a->pos, a->n);
11764 if (a->argc < 4)
11765 return CLI_SHOWUSAGE;
11766 span = atoi(a->argv[3]);
11767 if ((span < 1) || (span > NUM_SPANS)) {
11768 ast_cli(a->fd, "Invalid span '%s'. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
11769 return CLI_SUCCESS;
11771 if (!pris[span-1].pri) {
11772 ast_cli(a->fd, "No PRI running on span %d\n", span);
11773 return CLI_SUCCESS;
11775 for (x = 0; x < NUM_DCHANS; x++) {
11776 if (pris[span-1].dchannels[x]) {
11777 #ifdef PRI_DUMP_INFO_STR
11778 char *info_str = NULL;
11779 #endif
11780 ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11781 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11782 ast_cli(a->fd, "Status: %s\n", status);
11783 #ifdef PRI_DUMP_INFO_STR
11784 info_str = pri_dump_info_str(pris[span-1].pri);
11785 if (info_str) {
11786 ast_cli(a->fd, "%s", info_str);
11787 ast_free(info_str);
11789 #else
11790 pri_dump_info(pris[span-1].pri);
11791 #endif
11792 ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
11795 return CLI_SUCCESS;
11798 static char *handle_pri_show_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11800 int x;
11801 int span;
11802 int count=0;
11803 int debug=0;
11805 switch (cmd) {
11806 case CLI_INIT:
11807 e->command = "pri show debug";
11808 return NULL;
11809 case CLI_GENERATE:
11810 return NULL;
11813 for (span = 0; span < NUM_SPANS; span++) {
11814 if (pris[span].pri) {
11815 for (x = 0; x < NUM_DCHANS; x++) {
11816 debug = 0;
11817 if (pris[span].dchans[x]) {
11818 debug = pri_get_debug(pris[span].dchans[x]);
11819 ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
11820 count++;
11826 ast_mutex_lock(&pridebugfdlock);
11827 if (pridebugfd >= 0)
11828 ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
11829 ast_mutex_unlock(&pridebugfdlock);
11831 if (!count)
11832 ast_cli(a->fd, "No debug set or no PRI running\n");
11833 return CLI_SUCCESS;
11836 static char *handle_pri_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11838 switch (cmd) {
11839 case CLI_INIT:
11840 e->command = "pri show version";
11841 return NULL;
11842 case CLI_GENERATE:
11843 return NULL;
11846 ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
11848 return CLI_SUCCESS;
11851 static struct ast_cli_entry dahdi_pri_cli[] = {
11852 AST_CLI_DEFINE(handle_pri_debug, "Enables PRI debugging on a span"),
11853 AST_CLI_DEFINE(handle_pri_no_debug, "Disables PRI debugging on a span"),
11854 AST_CLI_DEFINE(handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging"),
11855 AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI Information"),
11856 AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI Information"),
11857 AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
11858 AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
11859 AST_CLI_DEFINE(handle_pri_unset_debug_file, "Ends PRI debug output to file"),
11860 AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
11863 #endif /* HAVE_PRI */
11865 static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11867 int channel;
11868 int ret;
11869 switch (cmd) {
11870 case CLI_INIT:
11871 e->command = "dahdi destroy channel";
11872 e->usage =
11873 "Usage: dahdi destroy channel <chan num>\n"
11874 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
11875 return NULL;
11876 case CLI_GENERATE:
11877 return NULL;
11879 if (a->argc != 4)
11880 return CLI_SHOWUSAGE;
11882 channel = atoi(a->argv[3]);
11883 ret = dahdi_destroy_channel_bynum(channel);
11884 return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
11887 static int setup_dahdi(int reload);
11888 static int dahdi_restart(void)
11890 ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
11891 while (iflist) {
11892 ast_debug(1, "Destroying DAHDI channel no. %d\n", iflist->channel);
11893 /* Also updates iflist: */
11894 destroy_channel(NULL, iflist, 1);
11896 ast_debug(1, "Channels destroyed. Now re-reading config.\n");
11897 if (setup_dahdi(2) != 0) {
11898 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
11899 return 1;
11901 return 0;
11904 static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11906 switch (cmd) {
11907 case CLI_INIT:
11908 e->command = "dahdi restart";
11909 e->usage =
11910 "Usage: dahdi restart\n"
11911 " Restarts the DAHDI channels: destroys them all and then\n"
11912 " re-reads them from chan_dahdi.conf.\n"
11913 " Note that this will STOP any running CALL on DAHDI channels.\n"
11915 return NULL;
11916 case CLI_GENERATE:
11917 return NULL;
11919 if (a->argc != 2)
11920 return CLI_SHOWUSAGE;
11922 if (dahdi_restart() != 0)
11923 return CLI_FAILURE;
11924 return CLI_SUCCESS;
11927 static int action_dahdirestart(struct mansession *s, const struct message *m)
11929 if (dahdi_restart() != 0) {
11930 astman_send_error(s, m, "Failed rereading DAHDI configuration");
11931 return 1;
11933 astman_send_ack(s, m, "DAHDIRestart: Success");
11934 return 0;
11937 static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
11939 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
11940 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
11941 unsigned int targetnum = 0;
11942 int filtertype = 0;
11943 struct dahdi_pvt *tmp = NULL;
11944 char tmps[20] = "";
11945 char statestr[20] = "";
11946 char blockstr[20] = "";
11947 ast_mutex_t *lock;
11948 struct dahdi_pvt *start;
11949 #ifdef HAVE_PRI
11950 int trunkgroup;
11951 struct dahdi_pri *pri = NULL;
11952 int x;
11953 #endif
11954 switch (cmd) {
11955 case CLI_INIT:
11956 e->command = "dahdi show channels [trunkgroup|group|context]";
11957 e->usage =
11958 "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
11959 " Shows a list of available channels with optional filtering\n"
11960 " <group> must be a number between 0 and 63\n";
11961 return NULL;
11962 case CLI_GENERATE:
11963 return NULL;
11966 lock = &iflock;
11967 start = iflist;
11969 /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
11971 if (!((a->argc == 3) || (a->argc == 5)))
11972 return CLI_SHOWUSAGE;
11974 if (a->argc == 5) {
11975 #ifdef HAVE_PRI
11976 if (!strcasecmp(a->argv[3], "trunkgroup")) {
11977 /* this option requires no special handling, so leave filtertype to zero */
11978 if ((trunkgroup = atoi(a->argv[4])) < 1)
11979 return CLI_SHOWUSAGE;
11980 for (x = 0; x < NUM_SPANS; x++) {
11981 if (pris[x].trunkgroup == trunkgroup) {
11982 pri = pris + x;
11983 break;
11986 if (pri) {
11987 start = pri->crvs;
11988 lock = &pri->lock;
11989 } else {
11990 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
11991 return CLI_FAILURE;
11993 } else
11994 #endif
11995 if (!strcasecmp(a->argv[3], "group")) {
11996 targetnum = atoi(a->argv[4]);
11997 if ((targetnum < 0) || (targetnum > 63))
11998 return CLI_SHOWUSAGE;
11999 targetnum = 1 << targetnum;
12000 filtertype = 1;
12001 } else if (!strcasecmp(a->argv[3], "context")) {
12002 filtertype = 2;
12006 ast_mutex_lock(lock);
12007 #ifdef HAVE_PRI
12008 ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12009 #else
12010 ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12011 #endif
12013 tmp = start;
12014 while (tmp) {
12015 if (filtertype) {
12016 switch(filtertype) {
12017 case 1: /* dahdi show channels group <group> */
12018 if (tmp->group != targetnum) {
12019 tmp = tmp->next;
12020 continue;
12022 break;
12023 case 2: /* dahdi show channels context <context> */
12024 if (strcasecmp(tmp->context, a->argv[4])) {
12025 tmp = tmp->next;
12026 continue;
12028 break;
12029 default:
12033 if (tmp->channel > 0) {
12034 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12035 } else
12036 ast_copy_string(tmps, "pseudo", sizeof(tmps));
12038 if (tmp->locallyblocked)
12039 blockstr[0] = 'L';
12040 else
12041 blockstr[0] = ' ';
12043 if (tmp->remotelyblocked)
12044 blockstr[1] = 'R';
12045 else
12046 blockstr[1] = ' ';
12048 blockstr[2] = '\0';
12050 snprintf(statestr, sizeof(statestr), "%s", "In Service");
12052 ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12053 tmp = tmp->next;
12055 ast_mutex_unlock(lock);
12056 return CLI_SUCCESS;
12057 #undef FORMAT
12058 #undef FORMAT2
12061 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12063 int channel;
12064 struct dahdi_pvt *tmp = NULL;
12065 struct dahdi_confinfo ci;
12066 struct dahdi_params ps;
12067 int x;
12068 ast_mutex_t *lock;
12069 struct dahdi_pvt *start;
12070 #ifdef HAVE_PRI
12071 char *c;
12072 int trunkgroup;
12073 struct dahdi_pri *pri=NULL;
12074 #endif
12075 switch (cmd) {
12076 case CLI_INIT:
12077 e->command = "dahdi show channel";
12078 e->usage =
12079 "Usage: dahdi show channel <chan num>\n"
12080 " Detailed information about a given channel\n";
12081 return NULL;
12082 case CLI_GENERATE:
12083 return NULL;
12086 lock = &iflock;
12087 start = iflist;
12089 if (a->argc != 4)
12090 return CLI_SHOWUSAGE;
12091 #ifdef HAVE_PRI
12092 if ((c = strchr(a->argv[3], ':'))) {
12093 if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2)
12094 return CLI_SHOWUSAGE;
12095 if ((trunkgroup < 1) || (channel < 1))
12096 return CLI_SHOWUSAGE;
12097 for (x = 0; x < NUM_SPANS; x++) {
12098 if (pris[x].trunkgroup == trunkgroup) {
12099 pri = pris + x;
12100 break;
12103 if (pri) {
12104 start = pri->crvs;
12105 lock = &pri->lock;
12106 } else {
12107 ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12108 return CLI_FAILURE;
12110 } else
12111 #endif
12112 channel = atoi(a->argv[3]);
12114 ast_mutex_lock(lock);
12115 tmp = start;
12116 while (tmp) {
12117 if (tmp->channel == channel) {
12118 #ifdef HAVE_PRI
12119 if (pri)
12120 ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12121 else
12122 #endif
12123 ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12124 ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].zfd);
12125 ast_cli(a->fd, "Span: %d\n", tmp->span);
12126 ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12127 ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12128 ast_cli(a->fd, "Context: %s\n", tmp->context);
12129 ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12130 ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12131 ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12132 ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12133 if (tmp->vars) {
12134 struct ast_variable *v;
12135 ast_cli(a->fd, "Variables:\n");
12136 for (v = tmp->vars ; v ; v = v->next)
12137 ast_cli(a->fd, " %s = %s\n", v->name, v->value);
12139 ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12140 ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12141 ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12142 ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12143 ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12144 ast_cli(a->fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
12145 ast_cli(a->fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
12146 ast_cli(a->fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
12147 ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12148 ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12149 ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12150 ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12151 ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12152 if (tmp->busydetect) {
12153 #if defined(BUSYDETECT_TONEONLY)
12154 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12155 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12156 ast_cli(a->fd, " Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12157 #endif
12158 #ifdef BUSYDETECT_DEBUG
12159 ast_cli(a->fd, " Busy Detector Debug: Enabled\n");
12160 #endif
12161 ast_cli(a->fd, " Busy Count: %d\n", tmp->busycount);
12162 ast_cli(a->fd, " Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
12164 ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12165 ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12166 ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12167 ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12168 ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12169 ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12170 ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12171 ast_cli(a->fd, "Echo Cancellation:\n");
12173 if (tmp->echocancel.head.tap_length) {
12174 ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12175 for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12176 ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12178 ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12179 } else {
12180 ast_cli(a->fd, "\tnone\n");
12182 if (tmp->master)
12183 ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12184 for (x = 0; x < MAX_SLAVES; x++) {
12185 if (tmp->slaves[x])
12186 ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12188 #ifdef HAVE_SS7
12189 if (tmp->ss7) {
12190 ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12192 #endif
12193 #ifdef HAVE_PRI
12194 if (tmp->pri) {
12195 ast_cli(a->fd, "PRI Flags: ");
12196 if (tmp->resetting)
12197 ast_cli(a->fd, "Resetting ");
12198 if (tmp->call)
12199 ast_cli(a->fd, "Call ");
12200 if (tmp->bearer)
12201 ast_cli(a->fd, "Bearer ");
12202 ast_cli(a->fd, "\n");
12203 if (tmp->logicalspan)
12204 ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12205 else
12206 ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12209 #endif
12210 memset(&ci, 0, sizeof(ci));
12211 ps.channo = tmp->channel;
12212 if (tmp->subs[SUB_REAL].zfd > -1) {
12213 if (!ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GETCONF, &ci)) {
12214 ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12216 if (!ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GETCONFMUTE, &x)) {
12217 ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12219 if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps) < 0) {
12220 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12221 } else {
12222 ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12225 ast_mutex_unlock(lock);
12226 return CLI_SUCCESS;
12228 tmp = tmp->next;
12231 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12232 ast_mutex_unlock(lock);
12233 return CLI_FAILURE;
12236 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12238 int i, j;
12239 switch (cmd) {
12240 case CLI_INIT:
12241 e->command = "dahdi show cadences";
12242 e->usage =
12243 "Usage: dahdi show cadences\n"
12244 " Shows all cadences currently defined\n";
12245 return NULL;
12246 case CLI_GENERATE:
12247 return NULL;
12249 for (i = 0; i < num_cadence; i++) {
12250 char output[1024];
12251 char tmp[16], tmp2[64];
12252 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12253 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12255 for (j = 0; j < 16; j++) {
12256 if (cadences[i].ringcadence[j] == 0)
12257 break;
12258 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12259 if (cidrings[i] * 2 - 1 == j)
12260 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12261 else
12262 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12263 if (j != 0)
12264 strncat(output, ",", sizeof(output) - strlen(output) - 1);
12265 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12267 ast_cli(a->fd,"%s\n",output);
12269 return CLI_SUCCESS;
12272 /* Based on irqmiss.c */
12273 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12275 #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12276 #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12277 int span;
12278 int res;
12279 char alarmstr[50];
12281 int ctl;
12282 struct dahdi_spaninfo s;
12284 switch (cmd) {
12285 case CLI_INIT:
12286 e->command = "dahdi show status";
12287 e->usage =
12288 "Usage: dahdi show status\n"
12289 " Shows a list of DAHDI cards with status\n";
12290 return NULL;
12291 case CLI_GENERATE:
12292 return NULL;
12294 ctl = open("/dev/dahdi/ctl", O_RDWR);
12295 if (ctl < 0) {
12296 ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
12297 return CLI_FAILURE;
12299 ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
12301 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12302 s.spanno = span;
12303 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12304 if (res) {
12305 continue;
12307 alarmstr[0] = '\0';
12308 if (s.alarms > 0) {
12309 if (s.alarms & DAHDI_ALARM_BLUE)
12310 strcat(alarmstr, "BLU/");
12311 if (s.alarms & DAHDI_ALARM_YELLOW)
12312 strcat(alarmstr, "YEL/");
12313 if (s.alarms & DAHDI_ALARM_RED)
12314 strcat(alarmstr, "RED/");
12315 if (s.alarms & DAHDI_ALARM_LOOPBACK)
12316 strcat(alarmstr, "LB/");
12317 if (s.alarms & DAHDI_ALARM_RECOVER)
12318 strcat(alarmstr, "REC/");
12319 if (s.alarms & DAHDI_ALARM_NOTOPEN)
12320 strcat(alarmstr, "NOP/");
12321 if (!strlen(alarmstr))
12322 strcat(alarmstr, "UUU/");
12323 if (strlen(alarmstr)) {
12324 /* Strip trailing / */
12325 alarmstr[strlen(alarmstr) - 1] = '\0';
12327 } else {
12328 if (s.numchans)
12329 strcpy(alarmstr, "OK");
12330 else
12331 strcpy(alarmstr, "UNCONFIGURED");
12334 ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
12335 , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
12336 s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
12337 s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
12338 "CAS"
12339 , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
12340 s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
12341 s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
12342 "Unk"
12343 , s.lineconfig & DAHDI_CONFIG_CRC4 ?
12344 s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
12345 , lbostr[s.lbo]
12348 close(ctl);
12350 return CLI_SUCCESS;
12351 #undef FORMAT
12352 #undef FORMAT2
12355 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12357 int pseudo_fd = -1;
12358 struct dahdi_versioninfo vi;
12360 switch (cmd) {
12361 case CLI_INIT:
12362 e->command = "dahdi show version";
12363 e->usage =
12364 "Usage: dahdi show version\n"
12365 " Shows the DAHDI version in use\n";
12366 return NULL;
12367 case CLI_GENERATE:
12368 return NULL;
12370 if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
12371 ast_cli(a->fd, "Failed to open control file to get version.\n");
12372 return CLI_SUCCESS;
12375 strcpy(vi.version, "Unknown");
12376 strcpy(vi.echo_canceller, "Unknown");
12378 if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
12379 ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
12380 else
12381 ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
12383 close(pseudo_fd);
12385 return CLI_SUCCESS;
12388 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12390 int channel;
12391 int gain;
12392 int tx;
12393 struct dahdi_hwgain hwgain;
12394 struct dahdi_pvt *tmp = NULL;
12396 switch (cmd) {
12397 case CLI_INIT:
12398 e->command = "dahdi set hwgain";
12399 e->usage =
12400 "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
12401 " Sets the hardware gain on a a given channel, overriding the\n"
12402 " value provided at module loadtime, whether the channel is in\n"
12403 " use or not. Changes take effect immediately.\n"
12404 " <rx|tx> which direction do you want to change (relative to our module)\n"
12405 " <chan num> is the channel number relative to the device\n"
12406 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12407 return NULL;
12408 case CLI_GENERATE:
12409 return NULL;
12412 if (a->argc != 6)
12413 return CLI_SHOWUSAGE;
12415 if (!strcasecmp("rx", a->argv[3]))
12416 tx = 0; /* rx */
12417 else if (!strcasecmp("tx", a->argv[3]))
12418 tx = 1; /* tx */
12419 else
12420 return CLI_SHOWUSAGE;
12422 channel = atoi(a->argv[4]);
12423 gain = atof(a->argv[5])*10.0;
12425 ast_mutex_lock(&iflock);
12427 for (tmp = iflist; tmp; tmp = tmp->next) {
12429 if (tmp->channel != channel)
12430 continue;
12432 if (tmp->subs[SUB_REAL].zfd == -1)
12433 break;
12435 hwgain.newgain = gain;
12436 hwgain.tx = tx;
12437 if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
12438 ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
12439 ast_mutex_unlock(&iflock);
12440 return CLI_FAILURE;
12442 ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
12443 tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
12444 break;
12447 ast_mutex_unlock(&iflock);
12449 if (tmp)
12450 return CLI_SUCCESS;
12452 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12453 return CLI_FAILURE;
12457 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12459 int channel;
12460 float gain;
12461 int tx;
12462 int res;
12463 ast_mutex_t *lock;
12464 struct dahdi_pvt *tmp = NULL;
12466 switch (cmd) {
12467 case CLI_INIT:
12468 e->command = "dahdi set swgain";
12469 e->usage =
12470 "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
12471 " Sets the software gain on a a given channel, overriding the\n"
12472 " value provided at module loadtime, whether the channel is in\n"
12473 " use or not. Changes take effect immediately.\n"
12474 " <rx|tx> which direction do you want to change (relative to our module)\n"
12475 " <chan num> is the channel number relative to the device\n"
12476 " <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12477 return NULL;
12478 case CLI_GENERATE:
12479 return NULL;
12482 lock = &iflock;
12484 if (a->argc != 6)
12485 return CLI_SHOWUSAGE;
12487 if (!strcasecmp("rx", a->argv[3]))
12488 tx = 0; /* rx */
12489 else if (!strcasecmp("tx", a->argv[3]))
12490 tx = 1; /* tx */
12491 else
12492 return CLI_SHOWUSAGE;
12494 channel = atoi(a->argv[4]);
12495 gain = atof(a->argv[5]);
12497 ast_mutex_lock(lock);
12498 for (tmp = iflist; tmp; tmp = tmp->next) {
12500 if (tmp->channel != channel)
12501 continue;
12503 if (tmp->subs[SUB_REAL].zfd == -1)
12504 break;
12506 if (tx)
12507 res = set_actual_txgain(tmp->subs[SUB_REAL].zfd, channel, gain, tmp->law);
12508 else
12509 res = set_actual_rxgain(tmp->subs[SUB_REAL].zfd, channel, gain, tmp->law);
12511 if (res) {
12512 ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
12513 ast_mutex_unlock(lock);
12514 return CLI_FAILURE;
12517 ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
12518 tx ? "tx" : "rx", gain, channel);
12519 break;
12521 ast_mutex_unlock(lock);
12523 if (tmp)
12524 return CLI_SUCCESS;
12526 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12527 return CLI_FAILURE;
12531 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
12533 int channel;
12534 int on;
12535 struct dahdi_pvt *dahdi_chan = NULL;
12537 switch (cmd) {
12538 case CLI_INIT:
12539 e->command = "dahdi set dnd";
12540 e->usage =
12541 "Usage: dahdi set dnd <chan#> <on|off>\n"
12542 " Sets/resets DND (Do Not Disturb) mode on a channel.\n"
12543 " Changes take effect immediately.\n"
12544 " <chan num> is the channel number\n"
12545 " <on|off> Enable or disable DND mode?\n"
12547 return NULL;
12548 case CLI_GENERATE:
12549 return NULL;
12552 if (a->argc != 5)
12553 return CLI_SHOWUSAGE;
12555 if ((channel = atoi(a->argv[3])) <= 0) {
12556 ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
12557 return CLI_SHOWUSAGE;
12560 if (ast_true(a->argv[4]))
12561 on = 1;
12562 else if (ast_false(a->argv[4]))
12563 on = 0;
12564 else {
12565 ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
12566 return CLI_SHOWUSAGE;
12569 ast_mutex_lock(&iflock);
12570 for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
12571 if (dahdi_chan->channel != channel)
12572 continue;
12574 /* Found the channel. Actually set it */
12575 dahdi_dnd(dahdi_chan, on);
12576 break;
12578 ast_mutex_unlock(&iflock);
12580 if (!dahdi_chan) {
12581 ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12582 return CLI_FAILURE;
12585 return CLI_SUCCESS;
12588 static struct ast_cli_entry dahdi_cli[] = {
12589 AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
12590 AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
12591 AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
12592 AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
12593 AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
12594 AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
12595 AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
12596 AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
12597 AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
12598 AST_CLI_DEFINE(dahdi_set_dnd, "Set software gain on a channel"),
12601 #define TRANSFER 0
12602 #define HANGUP 1
12604 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12606 if (p) {
12607 switch (mode) {
12608 case TRANSFER:
12609 p->fake_event = DAHDI_EVENT_WINKFLASH;
12610 break;
12611 case HANGUP:
12612 p->fake_event = DAHDI_EVENT_ONHOOK;
12613 break;
12614 default:
12615 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
12618 return 0;
12620 static struct dahdi_pvt *find_channel(int channel)
12622 struct dahdi_pvt *p = iflist;
12623 while (p) {
12624 if (p->channel == channel) {
12625 break;
12627 p = p->next;
12629 return p;
12632 static int action_dahdidndon(struct mansession *s, const struct message *m)
12634 struct dahdi_pvt *p = NULL;
12635 const char *channel = astman_get_header(m, "DAHDIChannel");
12637 if (ast_strlen_zero(channel)) {
12638 astman_send_error(s, m, "No channel specified");
12639 return 0;
12641 p = find_channel(atoi(channel));
12642 if (!p) {
12643 astman_send_error(s, m, "No such channel");
12644 return 0;
12646 p->dnd = 1;
12647 astman_send_ack(s, m, "DND Enabled");
12648 return 0;
12651 static int action_dahdidndoff(struct mansession *s, const struct message *m)
12653 struct dahdi_pvt *p = NULL;
12654 const char *channel = astman_get_header(m, "DAHDIChannel");
12656 if (ast_strlen_zero(channel)) {
12657 astman_send_error(s, m, "No channel specified");
12658 return 0;
12660 p = find_channel(atoi(channel));
12661 if (!p) {
12662 astman_send_error(s, m, "No such channel");
12663 return 0;
12665 p->dnd = 0;
12666 astman_send_ack(s, m, "DND Disabled");
12667 return 0;
12670 static int action_transfer(struct mansession *s, const struct message *m)
12672 struct dahdi_pvt *p = NULL;
12673 const char *channel = astman_get_header(m, "DAHDIChannel");
12675 if (ast_strlen_zero(channel)) {
12676 astman_send_error(s, m, "No channel specified");
12677 return 0;
12679 p = find_channel(atoi(channel));
12680 if (!p) {
12681 astman_send_error(s, m, "No such channel");
12682 return 0;
12684 dahdi_fake_event(p,TRANSFER);
12685 astman_send_ack(s, m, "DAHDITransfer");
12686 return 0;
12689 static int action_transferhangup(struct mansession *s, const struct message *m)
12691 struct dahdi_pvt *p = NULL;
12692 const char *channel = astman_get_header(m, "DAHDIChannel");
12694 if (ast_strlen_zero(channel)) {
12695 astman_send_error(s, m, "No channel specified");
12696 return 0;
12698 p = find_channel(atoi(channel));
12699 if (!p) {
12700 astman_send_error(s, m, "No such channel");
12701 return 0;
12703 dahdi_fake_event(p,HANGUP);
12704 astman_send_ack(s, m, "DAHDIHangup");
12705 return 0;
12708 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
12710 struct dahdi_pvt *p = NULL;
12711 const char *channel = astman_get_header(m, "DAHDIChannel");
12712 const char *number = astman_get_header(m, "Number");
12713 int i;
12715 if (ast_strlen_zero(channel)) {
12716 astman_send_error(s, m, "No channel specified");
12717 return 0;
12719 if (ast_strlen_zero(number)) {
12720 astman_send_error(s, m, "No number specified");
12721 return 0;
12723 p = find_channel(atoi(channel));
12724 if (!p) {
12725 astman_send_error(s, m, "No such channel");
12726 return 0;
12728 if (!p->owner) {
12729 astman_send_error(s, m, "Channel does not have it's owner");
12730 return 0;
12732 for (i = 0; i < strlen(number); i++) {
12733 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12734 dahdi_queue_frame(p, &f, NULL);
12736 astman_send_ack(s, m, "DAHDIDialOffhook");
12737 return 0;
12740 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
12742 struct dahdi_pvt *tmp = NULL;
12743 const char *id = astman_get_header(m, "ActionID");
12744 const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
12745 char idText[256] = "";
12746 int channels = 0;
12747 int dahdichanquery = -1;
12748 if (!ast_strlen_zero(dahdichannel)) {
12749 dahdichanquery = atoi(dahdichannel);
12752 astman_send_ack(s, m, "DAHDI channel status will follow");
12753 if (!ast_strlen_zero(id))
12754 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
12756 ast_mutex_lock(&iflock);
12758 tmp = iflist;
12759 while (tmp) {
12760 if (tmp->channel > 0) {
12761 int alm = get_alarms(tmp);
12763 /* If a specific channel is queried for, only deliver status for that channel */
12764 if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
12765 continue;
12767 channels++;
12768 if (tmp->owner) {
12769 /* Add data if we have a current call */
12770 astman_append(s,
12771 "Event: DAHDIShowChannels\r\n"
12772 "DAHDIChannel: %d\r\n"
12773 "Channel: %s\r\n"
12774 "Uniqueid: %s\r\n"
12775 "AccountCode: %s\r\n"
12776 "Signalling: %s\r\n"
12777 "SignallingCode: %d\r\n"
12778 "Context: %s\r\n"
12779 "DND: %s\r\n"
12780 "Alarm: %s\r\n"
12781 "%s"
12782 "\r\n",
12783 tmp->channel,
12784 tmp->owner->name,
12785 tmp->owner->uniqueid,
12786 tmp->owner->accountcode,
12787 sig2str(tmp->sig),
12788 tmp->sig,
12789 tmp->context,
12790 tmp->dnd ? "Enabled" : "Disabled",
12791 alarm2str(alm), idText);
12792 } else {
12793 astman_append(s,
12794 "Event: DAHDIShowChannels\r\n"
12795 "DAHDIChannel: %d\r\n"
12796 "Signalling: %s\r\n"
12797 "SignallingCode: %d\r\n"
12798 "Context: %s\r\n"
12799 "DND: %s\r\n"
12800 "Alarm: %s\r\n"
12801 "%s"
12802 "\r\n",
12803 tmp->channel, sig2str(tmp->sig), tmp->sig,
12804 tmp->context,
12805 tmp->dnd ? "Enabled" : "Disabled",
12806 alarm2str(alm), idText);
12810 tmp = tmp->next;
12813 ast_mutex_unlock(&iflock);
12815 astman_append(s,
12816 "Event: DAHDIShowChannelsComplete\r\n"
12817 "%s"
12818 "Items: %d\r\n"
12819 "\r\n",
12820 idText,
12821 channels);
12822 return 0;
12825 static int __unload_module(void)
12827 int x;
12828 struct dahdi_pvt *p, *pl;
12829 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12830 int i;
12831 #endif
12833 #if defined(HAVE_PRI)
12834 for (i = 0; i < NUM_SPANS; i++) {
12835 if (pris[i].master != AST_PTHREADT_NULL)
12836 pthread_cancel(pris[i].master);
12838 ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
12839 ast_unregister_application(dahdi_send_keypad_facility_app);
12840 #endif
12842 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12843 ast_manager_unregister( "DAHDIDialOffhook" );
12844 ast_manager_unregister( "DAHDIHangup" );
12845 ast_manager_unregister( "DAHDITransfer" );
12846 ast_manager_unregister( "DAHDIDNDoff" );
12847 ast_manager_unregister( "DAHDIDNDon" );
12848 ast_manager_unregister("DAHDIShowChannels");
12849 ast_manager_unregister("DAHDIRestart");
12850 ast_channel_unregister(&dahdi_tech);
12851 ast_mutex_lock(&iflock);
12852 /* Hangup all interfaces if they have an owner */
12853 p = iflist;
12854 while (p) {
12855 if (p->owner)
12856 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12857 p = p->next;
12859 ast_mutex_unlock(&iflock);
12860 ast_mutex_lock(&monlock);
12861 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12862 pthread_cancel(monitor_thread);
12863 pthread_kill(monitor_thread, SIGURG);
12864 pthread_join(monitor_thread, NULL);
12866 monitor_thread = AST_PTHREADT_STOP;
12867 ast_mutex_unlock(&monlock);
12869 ast_mutex_lock(&iflock);
12870 /* Destroy all the interfaces and free their memory */
12871 p = iflist;
12872 while (p) {
12873 /* Free any callerid */
12874 if (p->cidspill)
12875 ast_free(p->cidspill);
12876 /* Close the DAHDI thingy */
12877 if (p->subs[SUB_REAL].zfd > -1)
12878 dahdi_close(p->subs[SUB_REAL].zfd);
12879 pl = p;
12880 p = p->next;
12881 x = pl->channel;
12882 /* Free associated memory */
12883 if (pl)
12884 destroy_dahdi_pvt(&pl);
12885 ast_verb(3, "Unregistered channel %d\n", x);
12887 iflist = NULL;
12888 ifcount = 0;
12889 ast_mutex_unlock(&iflock);
12891 #if defined(HAVE_PRI)
12892 for (i = 0; i < NUM_SPANS; i++) {
12893 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12894 pthread_join(pris[i].master, NULL);
12895 dahdi_close(pris[i].fds[i]);
12897 #endif /* HAVE_PRI */
12899 #if defined(HAVE_SS7)
12900 for (i = 0; i < NUM_SPANS; i++) {
12901 if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
12902 pthread_join(linksets[i].master, NULL);
12903 dahdi_close(linksets[i].fds[i]);
12905 #endif /* HAVE_SS7 */
12907 return 0;
12910 #ifdef HAVE_SS7
12911 static int linkset_addsigchan(int sigchan)
12913 struct dahdi_ss7 *link;
12914 int res;
12915 int curfd;
12916 struct dahdi_params p;
12917 struct dahdi_bufferinfo bi;
12918 struct dahdi_spaninfo si;
12921 link = ss7_resolve_linkset(cur_linkset);
12922 if (!link) {
12923 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
12924 return -1;
12927 if (cur_ss7type < 0) {
12928 ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
12929 return -1;
12932 if (!link->ss7)
12933 link->ss7 = ss7_new(cur_ss7type);
12935 if (!link->ss7) {
12936 ast_log(LOG_ERROR, "Can't create new SS7!\n");
12937 return -1;
12940 link->type = cur_ss7type;
12942 if (cur_pointcode < 0) {
12943 ast_log(LOG_ERROR, "Unspecified pointcode!\n");
12944 return -1;
12945 } else
12946 ss7_set_pc(link->ss7, cur_pointcode);
12948 if (sigchan < 0) {
12949 ast_log(LOG_ERROR, "Invalid sigchan!\n");
12950 return -1;
12951 } else {
12952 if (link->numsigchans >= NUM_DCHANS) {
12953 ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
12954 return -1;
12956 curfd = link->numsigchans;
12958 link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
12959 if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
12960 ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
12961 return -1;
12963 res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
12964 if (res) {
12965 dahdi_close(link->fds[curfd]);
12966 link->fds[curfd] = -1;
12967 ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
12968 return -1;
12970 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
12971 dahdi_close(link->fds[curfd]);
12972 link->fds[curfd] = -1;
12973 ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
12974 return -1;
12977 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12978 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12979 bi.numbufs = 32;
12980 bi.bufsize = 512;
12982 if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
12983 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
12984 dahdi_close(link->fds[curfd]);
12985 link->fds[curfd] = -1;
12986 return -1;
12989 if (p.sigtype == DAHDI_SIG_MTP2)
12990 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
12991 else
12992 ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
12994 link->numsigchans++;
12996 memset(&si, 0, sizeof(si));
12997 res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
12998 if (res) {
12999 dahdi_close(link->fds[curfd]);
13000 link->fds[curfd] = -1;
13001 ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13004 if (!si.alarms) {
13005 link->linkstate[curfd] = LINKSTATE_DOWN;
13006 ss7_link_noalarm(link->ss7, link->fds[curfd]);
13007 } else {
13008 link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13009 ss7_link_alarm(link->ss7, link->fds[curfd]);
13013 if (cur_adjpointcode < 0) {
13014 ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13015 return -1;
13016 } else {
13017 ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13020 if (cur_defaultdpc < 0) {
13021 ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13022 return -1;
13025 if (cur_networkindicator < 0) {
13026 ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13027 return -1;
13028 } else
13029 ss7_set_network_ind(link->ss7, cur_networkindicator);
13031 return 0;
13034 static char *handle_ss7_no_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13036 int span;
13037 switch (cmd) {
13038 case CLI_INIT:
13039 e->command = "ss7 no debug linkset";
13040 e->usage =
13041 "Usage: ss7 no debug linkset <span>\n"
13042 " Disables debugging on a given SS7 linkset\n";
13043 return NULL;
13044 case CLI_GENERATE:
13045 return NULL;
13047 if (a->argc < 5)
13048 return CLI_SHOWUSAGE;
13049 span = atoi(a->argv[4]);
13050 if ((span < 1) || (span > NUM_SPANS)) {
13051 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13052 return CLI_SUCCESS;
13054 if (!linksets[span-1].ss7) {
13055 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13056 return CLI_SUCCESS;
13058 if (linksets[span-1].ss7)
13059 ss7_set_debug(linksets[span-1].ss7, 0);
13061 ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13062 return CLI_SUCCESS;
13065 static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13067 int span;
13068 switch (cmd) {
13069 case CLI_INIT:
13070 e->command = "ss7 debug linkset";
13071 e->usage =
13072 "Usage: ss7 debug linkset <linkset>\n"
13073 " Enables debugging on a given SS7 linkset\n";
13074 return NULL;
13075 case CLI_GENERATE:
13076 return NULL;
13078 if (a->argc < 4)
13079 return CLI_SHOWUSAGE;
13080 span = atoi(a->argv[3]);
13081 if ((span < 1) || (span > NUM_SPANS)) {
13082 ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13083 return CLI_SUCCESS;
13085 if (!linksets[span-1].ss7) {
13086 ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13087 return CLI_SUCCESS;
13089 if (linksets[span-1].ss7)
13090 ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13092 ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13093 return CLI_SUCCESS;
13096 static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13098 int linkset, cic;
13099 int blocked = -1, i;
13100 switch (cmd) {
13101 case CLI_INIT:
13102 e->command = "ss7 block cic";
13103 e->usage =
13104 "Usage: ss7 block cic <linkset> <CIC>\n"
13105 " Sends a remote blocking request for the given CIC on the specified linkset\n";
13106 return NULL;
13107 case CLI_GENERATE:
13108 return NULL;
13110 if (a->argc == 5)
13111 linkset = atoi(a->argv[3]);
13112 else
13113 return CLI_SHOWUSAGE;
13115 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13116 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13117 return CLI_SUCCESS;
13120 if (!linksets[linkset-1].ss7) {
13121 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13122 return CLI_SUCCESS;
13125 cic = atoi(a->argv[4]);
13127 if (cic < 1) {
13128 ast_cli(a->fd, "Invalid CIC specified!\n");
13129 return CLI_SUCCESS;
13132 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13133 if (linksets[linkset-1].pvts[i]->cic == cic) {
13134 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13135 if (!blocked) {
13136 ast_mutex_lock(&linksets[linkset-1].lock);
13137 isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13138 ast_mutex_unlock(&linksets[linkset-1].lock);
13143 if (blocked < 0) {
13144 ast_cli(a->fd, "Invalid CIC specified!\n");
13145 return CLI_SUCCESS;
13148 if (!blocked)
13149 ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13150 else
13151 ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13153 /* Break poll on the linkset so it sends our messages */
13154 pthread_kill(linksets[linkset-1].master, SIGURG);
13156 return CLI_SUCCESS;
13159 static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13161 int linkset;
13162 int i;
13163 switch (cmd) {
13164 case CLI_INIT:
13165 e->command = "ss7 block linkset";
13166 e->usage =
13167 "Usage: ss7 block linkset <linkset number>\n"
13168 " Sends a remote blocking request for all CICs on the given linkset\n";
13169 return NULL;
13170 case CLI_GENERATE:
13171 return NULL;
13173 if (a->argc == 4)
13174 linkset = atoi(a->argv[3]);
13175 else
13176 return CLI_SHOWUSAGE;
13178 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13179 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13180 return CLI_SUCCESS;
13183 if (!linksets[linkset-1].ss7) {
13184 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13185 return CLI_SUCCESS;
13188 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13189 ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13190 ast_mutex_lock(&linksets[linkset-1].lock);
13191 isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13192 ast_mutex_unlock(&linksets[linkset-1].lock);
13195 /* Break poll on the linkset so it sends our messages */
13196 pthread_kill(linksets[linkset-1].master, SIGURG);
13198 return CLI_SUCCESS;
13201 static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13203 int linkset, cic;
13204 int i, blocked = -1;
13205 switch (cmd) {
13206 case CLI_INIT:
13207 e->command = "ss7 unblock cic";
13208 e->usage =
13209 "Usage: ss7 unblock cic <linkset> <CIC>\n"
13210 " Sends a remote unblocking request for the given CIC on the specified linkset\n";
13211 return NULL;
13212 case CLI_GENERATE:
13213 return NULL;
13216 if (a->argc == 5)
13217 linkset = atoi(a->argv[3]);
13218 else
13219 return CLI_SHOWUSAGE;
13221 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13222 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13223 return CLI_SUCCESS;
13226 if (!linksets[linkset-1].ss7) {
13227 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13228 return CLI_SUCCESS;
13231 cic = atoi(a->argv[4]);
13233 if (cic < 1) {
13234 ast_cli(a->fd, "Invalid CIC specified!\n");
13235 return CLI_SUCCESS;
13238 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13239 if (linksets[linkset-1].pvts[i]->cic == cic) {
13240 blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13241 if (blocked) {
13242 ast_mutex_lock(&linksets[linkset-1].lock);
13243 isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13244 ast_mutex_unlock(&linksets[linkset-1].lock);
13249 if (blocked > 0)
13250 ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13252 /* Break poll on the linkset so it sends our messages */
13253 pthread_kill(linksets[linkset-1].master, SIGURG);
13255 return CLI_SUCCESS;
13258 static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13260 int linkset;
13261 int i;
13262 switch (cmd) {
13263 case CLI_INIT:
13264 e->command = "ss7 unblock linkset";
13265 e->usage =
13266 "Usage: ss7 unblock linkset <linkset number>\n"
13267 " Sends a remote unblocking request for all CICs on the specified linkset\n";
13268 return NULL;
13269 case CLI_GENERATE:
13270 return NULL;
13273 if (a->argc == 4)
13274 linkset = atoi(a->argv[3]);
13275 else
13276 return CLI_SHOWUSAGE;
13278 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13279 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13280 return CLI_SUCCESS;
13283 if (!linksets[linkset-1].ss7) {
13284 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13285 return CLI_SUCCESS;
13288 for (i = 0; i < linksets[linkset-1].numchans; i++) {
13289 ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13290 ast_mutex_lock(&linksets[linkset-1].lock);
13291 isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13292 ast_mutex_unlock(&linksets[linkset-1].lock);
13295 /* Break poll on the linkset so it sends our messages */
13296 pthread_kill(linksets[linkset-1].master, SIGURG);
13298 return CLI_SUCCESS;
13301 static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13303 int linkset;
13304 struct dahdi_ss7 *ss7;
13305 switch (cmd) {
13306 case CLI_INIT:
13307 e->command = "ss7 show linkset";
13308 e->usage =
13309 "Usage: ss7 show linkset <span>\n"
13310 " Shows the status of an SS7 linkset.\n";
13311 return NULL;
13312 case CLI_GENERATE:
13313 return NULL;
13316 if (a->argc < 4)
13317 return CLI_SHOWUSAGE;
13318 linkset = atoi(a->argv[3]);
13319 if ((linkset < 1) || (linkset > NUM_SPANS)) {
13320 ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13321 return CLI_SUCCESS;
13323 if (!linksets[linkset-1].ss7) {
13324 ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13325 return CLI_SUCCESS;
13327 if (linksets[linkset-1].ss7)
13328 ss7 = &linksets[linkset-1];
13330 ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13332 return CLI_SUCCESS;
13335 static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
13337 switch (cmd) {
13338 case CLI_INIT:
13339 e->command = "ss7 show version";
13340 return NULL;
13341 case CLI_GENERATE:
13342 return NULL;
13345 ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
13347 return CLI_SUCCESS;
13350 static struct ast_cli_entry dahdi_ss7_cli[] = {
13351 AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
13352 AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"),
13353 AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
13354 AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
13355 AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
13356 AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
13357 AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
13358 AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
13360 #endif /* HAVE_SS7 */
13362 static int unload_module(void)
13364 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13365 int y;
13366 #endif
13367 #ifdef HAVE_PRI
13368 for (y = 0; y < NUM_SPANS; y++)
13369 ast_mutex_destroy(&pris[y].lock);
13370 #endif
13371 #ifdef HAVE_SS7
13372 for (y = 0; y < NUM_SPANS; y++)
13373 ast_mutex_destroy(&linksets[y].lock);
13374 #endif /* HAVE_SS7 */
13375 return __unload_module();
13378 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
13380 char *c, *chan;
13381 int x, start, finish;
13382 struct dahdi_pvt *tmp;
13383 #ifdef HAVE_PRI
13384 struct dahdi_pri *pri;
13385 int trunkgroup, y;
13386 #endif
13388 if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
13389 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
13390 return -1;
13393 c = ast_strdupa(value);
13395 #ifdef HAVE_PRI
13396 pri = NULL;
13397 if (iscrv) {
13398 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
13399 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
13400 return -1;
13402 if (trunkgroup < 1) {
13403 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
13404 return -1;
13406 c += y;
13407 for (y = 0; y < NUM_SPANS; y++) {
13408 if (pris[y].trunkgroup == trunkgroup) {
13409 pri = pris + y;
13410 break;
13413 if (!pri) {
13414 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
13415 return -1;
13418 #endif
13420 while ((chan = strsep(&c, ","))) {
13421 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
13422 /* Range */
13423 } else if (sscanf(chan, "%d", &start)) {
13424 /* Just one */
13425 finish = start;
13426 } else if (!strcasecmp(chan, "pseudo")) {
13427 finish = start = CHAN_PSEUDO;
13428 if (found_pseudo)
13429 *found_pseudo = 1;
13430 } else {
13431 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
13432 return -1;
13434 if (finish < start) {
13435 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
13436 x = finish;
13437 finish = start;
13438 start = x;
13441 for (x = start; x <= finish; x++) {
13442 #ifdef HAVE_PRI
13443 tmp = mkintf(x, conf, pri, reload);
13444 #else
13445 tmp = mkintf(x, conf, NULL, reload);
13446 #endif
13448 if (tmp) {
13449 #ifdef HAVE_PRI
13450 if (pri)
13451 ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
13452 else
13453 #endif
13454 ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
13455 } else {
13456 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
13457 (reload == 1) ? "reconfigure" : "register", value);
13458 return -1;
13463 return 0;
13466 /** The length of the parameters list of 'dahdichan'.
13467 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
13468 #define MAX_CHANLIST_LEN 80
13470 static void process_echocancel(struct dahdi_chan_conf *confp, const char *data, unsigned int line)
13472 char *parse = ast_strdupa(data);
13473 char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
13474 unsigned int param_count;
13475 unsigned int x;
13477 if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
13478 return;
13480 memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
13482 /* first parameter is tap length, process it here */
13484 x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
13486 if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
13487 confp->chan.echocancel.head.tap_length = x;
13488 else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
13489 confp->chan.echocancel.head.tap_length = 128;
13491 /* now process any remaining parameters */
13493 for (x = 1; x < param_count; x++) {
13494 struct {
13495 char *name;
13496 char *value;
13497 } param;
13499 if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
13500 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
13501 continue;
13504 if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
13505 ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
13506 continue;
13509 strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
13511 if (param.value) {
13512 if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
13513 ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
13514 continue;
13517 confp->chan.echocancel.head.param_count++;
13521 /*! process_dahdi() - ignore keyword 'channel' and similar */
13522 #define PROC_DAHDI_OPT_NOCHAN (1 << 0)
13523 /*! process_dahdi() - No warnings on non-existing cofiguration keywords */
13524 #define PROC_DAHDI_OPT_NOWARN (1 << 1)
13526 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
13528 struct dahdi_pvt *tmp;
13529 int y;
13530 int found_pseudo = 0;
13531 char dahdichan[MAX_CHANLIST_LEN] = {};
13533 for (; v; v = v->next) {
13534 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
13535 continue;
13537 /* must have parkinglot in confp before build_channels is called */
13538 if (!strcasecmp(v->name, "parkinglot")) {
13539 ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
13542 /* Create the interface list */
13543 if (!strcasecmp(v->name, "channel")
13544 #ifdef HAVE_PRI
13545 || !strcasecmp(v->name, "crv")
13546 #endif
13548 int iscrv;
13549 if (options && PROC_DAHDI_OPT_NOCHAN)
13550 continue;
13551 iscrv = !strcasecmp(v->name, "crv");
13552 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
13553 return -1;
13554 } else if (!strcasecmp(v->name, "buffers")) {
13555 int res;
13556 char policy[8] = "";
13557 res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
13558 if (res != 2) {
13559 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
13560 confp->chan.buf_no = numbufs;
13561 continue;
13563 if (confp->chan.buf_no < 0)
13564 confp->chan.buf_no = numbufs;
13565 if (!strcasecmp(policy, "full")) {
13566 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
13567 } else if (!strcasecmp(policy, "half")) {
13568 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /*HALF_FULL*/;
13569 } else if (!strcasecmp(policy, "immediate")) {
13570 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
13571 } else {
13572 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
13574 } else if (!strcasecmp(v->name, "dahdichan")) {
13575 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
13576 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
13577 usedistinctiveringdetection = ast_true(v->value);
13578 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
13579 distinctiveringaftercid = ast_true(v->value);
13580 } else if (!strcasecmp(v->name, "dring1context")) {
13581 ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
13582 } else if (!strcasecmp(v->name, "dring2context")) {
13583 ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
13584 } else if (!strcasecmp(v->name, "dring3context")) {
13585 ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
13586 } else if (!strcasecmp(v->name, "dring1range")) {
13587 confp->chan.drings.ringnum[0].range = atoi(v->value);
13588 } else if (!strcasecmp(v->name, "dring2range")) {
13589 confp->chan.drings.ringnum[1].range = atoi(v->value);
13590 } else if (!strcasecmp(v->name, "dring3range")) {
13591 confp->chan.drings.ringnum[2].range = atoi(v->value);
13592 } else if (!strcasecmp(v->name, "dring1")) {
13593 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
13594 } else if (!strcasecmp(v->name, "dring2")) {
13595 sscanf(v->value,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
13596 } else if (!strcasecmp(v->name, "dring3")) {
13597 sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
13598 } else if (!strcasecmp(v->name, "usecallerid")) {
13599 confp->chan.use_callerid = ast_true(v->value);
13600 } else if (!strcasecmp(v->name, "cidsignalling")) {
13601 if (!strcasecmp(v->value, "bell"))
13602 confp->chan.cid_signalling = CID_SIG_BELL;
13603 else if (!strcasecmp(v->value, "v23"))
13604 confp->chan.cid_signalling = CID_SIG_V23;
13605 else if (!strcasecmp(v->value, "dtmf"))
13606 confp->chan.cid_signalling = CID_SIG_DTMF;
13607 else if (!strcasecmp(v->value, "smdi"))
13608 confp->chan.cid_signalling = CID_SIG_SMDI;
13609 else if (!strcasecmp(v->value, "v23_jp"))
13610 confp->chan.cid_signalling = CID_SIG_V23_JP;
13611 else if (ast_true(v->value))
13612 confp->chan.cid_signalling = CID_SIG_BELL;
13613 } else if (!strcasecmp(v->name, "cidstart")) {
13614 if (!strcasecmp(v->value, "ring"))
13615 confp->chan.cid_start = CID_START_RING;
13616 else if (!strcasecmp(v->value, "polarity_in"))
13617 confp->chan.cid_start = CID_START_POLARITY_IN;
13618 else if (!strcasecmp(v->value, "polarity"))
13619 confp->chan.cid_start = CID_START_POLARITY;
13620 else if (ast_true(v->value))
13621 confp->chan.cid_start = CID_START_RING;
13622 } else if (!strcasecmp(v->name, "threewaycalling")) {
13623 confp->chan.threewaycalling = ast_true(v->value);
13624 } else if (!strcasecmp(v->name, "cancallforward")) {
13625 confp->chan.cancallforward = ast_true(v->value);
13626 } else if (!strcasecmp(v->name, "relaxdtmf")) {
13627 if (ast_true(v->value))
13628 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
13629 else
13630 confp->chan.dtmfrelax = 0;
13631 } else if (!strcasecmp(v->name, "mailbox")) {
13632 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
13633 } else if (!strcasecmp(v->name, "hasvoicemail")) {
13634 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
13635 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
13637 } else if (!strcasecmp(v->name, "adsi")) {
13638 confp->chan.adsi = ast_true(v->value);
13639 } else if (!strcasecmp(v->name, "usesmdi")) {
13640 confp->chan.use_smdi = ast_true(v->value);
13641 } else if (!strcasecmp(v->name, "smdiport")) {
13642 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
13643 } else if (!strcasecmp(v->name, "transfer")) {
13644 confp->chan.transfer = ast_true(v->value);
13645 } else if (!strcasecmp(v->name, "canpark")) {
13646 confp->chan.canpark = ast_true(v->value);
13647 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
13648 confp->chan.echocanbridged = ast_true(v->value);
13649 } else if (!strcasecmp(v->name, "busydetect")) {
13650 confp->chan.busydetect = ast_true(v->value);
13651 } else if (!strcasecmp(v->name, "busycount")) {
13652 confp->chan.busycount = atoi(v->value);
13653 } else if (!strcasecmp(v->name, "busypattern")) {
13654 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
13655 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
13657 } else if (!strcasecmp(v->name, "callprogress")) {
13658 confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
13659 if (ast_true(v->value))
13660 confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
13661 } else if (!strcasecmp(v->name, "faxdetect")) {
13662 confp->chan.callprogress &= ~CALLPROGRESS_FAX;
13663 if (!strcasecmp(v->value, "incoming")) {
13664 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
13665 } else if (!strcasecmp(v->value, "outgoing")) {
13666 confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
13667 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
13668 confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
13669 } else if (!strcasecmp(v->name, "echocancel")) {
13670 process_echocancel(confp, v->value, v->lineno);
13671 } else if (!strcasecmp(v->name, "echotraining")) {
13672 if (sscanf(v->value, "%d", &y) == 1) {
13673 if ((y < 10) || (y > 4000)) {
13674 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
13675 } else {
13676 confp->chan.echotraining = y;
13678 } else if (ast_true(v->value)) {
13679 confp->chan.echotraining = 400;
13680 } else
13681 confp->chan.echotraining = 0;
13682 } else if (!strcasecmp(v->name, "hidecallerid")) {
13683 confp->chan.hidecallerid = ast_true(v->value);
13684 } else if (!strcasecmp(v->name, "hidecalleridname")) {
13685 confp->chan.hidecalleridname = ast_true(v->value);
13686 } else if (!strcasecmp(v->name, "pulsedial")) {
13687 confp->chan.pulse = ast_true(v->value);
13688 } else if (!strcasecmp(v->name, "callreturn")) {
13689 confp->chan.callreturn = ast_true(v->value);
13690 } else if (!strcasecmp(v->name, "callwaiting")) {
13691 confp->chan.callwaiting = ast_true(v->value);
13692 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
13693 confp->chan.callwaitingcallerid = ast_true(v->value);
13694 } else if (!strcasecmp(v->name, "context")) {
13695 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
13696 } else if (!strcasecmp(v->name, "language")) {
13697 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
13698 } else if (!strcasecmp(v->name, "progzone")) {
13699 ast_copy_string(progzone, v->value, sizeof(progzone));
13700 } else if (!strcasecmp(v->name, "mohinterpret")
13701 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
13702 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
13703 } else if (!strcasecmp(v->name, "mohsuggest")) {
13704 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
13705 } else if (!strcasecmp(v->name, "parkinglot")) {
13706 ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
13707 } else if (!strcasecmp(v->name, "stripmsd")) {
13708 ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
13709 confp->chan.stripmsd = atoi(v->value);
13710 } else if (!strcasecmp(v->name, "jitterbuffers")) {
13711 numbufs = atoi(v->value);
13712 } else if (!strcasecmp(v->name, "group")) {
13713 confp->chan.group = ast_get_group(v->value);
13714 } else if (!strcasecmp(v->name, "callgroup")) {
13715 if (!strcasecmp(v->value, "none"))
13716 confp->chan.callgroup = 0;
13717 else
13718 confp->chan.callgroup = ast_get_group(v->value);
13719 } else if (!strcasecmp(v->name, "pickupgroup")) {
13720 if (!strcasecmp(v->value, "none"))
13721 confp->chan.pickupgroup = 0;
13722 else
13723 confp->chan.pickupgroup = ast_get_group(v->value);
13724 } else if (!strcasecmp(v->name, "setvar")) {
13725 char *varname = ast_strdupa(v->value), *varval = NULL;
13726 struct ast_variable *tmpvar;
13727 if (varname && (varval = strchr(varname, '='))) {
13728 *varval++ = '\0';
13729 if ((tmpvar = ast_variable_new(varname, varval, ""))) {
13730 tmpvar->next = confp->chan.vars;
13731 confp->chan.vars = tmpvar;
13734 } else if (!strcasecmp(v->name, "immediate")) {
13735 confp->chan.immediate = ast_true(v->value);
13736 } else if (!strcasecmp(v->name, "transfertobusy")) {
13737 confp->chan.transfertobusy = ast_true(v->value);
13738 } else if (!strcasecmp(v->name, "mwimonitor")) {
13739 if (!strcasecmp(v->value, "neon")) {
13740 confp->chan.mwimonitor_neon = 1;
13741 confp->chan.mwimonitor_fsk = 0;
13742 } else {
13743 confp->chan.mwimonitor_neon = 0;
13744 if (!strcasecmp(v->value, "fsk"))
13745 confp->chan.mwimonitor_fsk = 1;
13746 else
13747 confp->chan.mwimonitor_fsk = ast_true(v->value) ? 1 : 0;
13749 } else if (!strcasecmp(v->name, "cid_rxgain")) {
13750 if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
13751 ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
13753 } else if (!strcasecmp(v->name, "rxgain")) {
13754 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
13755 ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
13757 } else if (!strcasecmp(v->name, "txgain")) {
13758 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
13759 ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
13761 } else if (!strcasecmp(v->name, "tonezone")) {
13762 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
13763 ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
13765 } else if (!strcasecmp(v->name, "callerid")) {
13766 if (!strcasecmp(v->value, "asreceived")) {
13767 confp->chan.cid_num[0] = '\0';
13768 confp->chan.cid_name[0] = '\0';
13769 } else {
13770 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
13772 } else if (!strcasecmp(v->name, "fullname")) {
13773 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
13774 } else if (!strcasecmp(v->name, "cid_number")) {
13775 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
13776 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
13777 confp->chan.dahditrcallerid = ast_true(v->value);
13778 } else if (!strcasecmp(v->name, "restrictcid")) {
13779 confp->chan.restrictcid = ast_true(v->value);
13780 } else if (!strcasecmp(v->name, "usecallingpres")) {
13781 confp->chan.use_callingpres = ast_true(v->value);
13782 } else if (!strcasecmp(v->name, "accountcode")) {
13783 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
13784 } else if (!strcasecmp(v->name, "amaflags")) {
13785 y = ast_cdr_amaflags2int(v->value);
13786 if (y < 0)
13787 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
13788 else
13789 confp->chan.amaflags = y;
13790 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
13791 confp->chan.polarityonanswerdelay = atoi(v->value);
13792 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
13793 confp->chan.answeronpolarityswitch = ast_true(v->value);
13794 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
13795 confp->chan.hanguponpolarityswitch = ast_true(v->value);
13796 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
13797 confp->chan.sendcalleridafter = atoi(v->value);
13798 } else if (!strcasecmp(v->name, "mwimonitornotify")) {
13799 ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
13800 } else if (!strcasecmp(v->name, "mwisendtype")) {
13801 if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
13802 mwisend_rpas = 1;
13803 } else {
13804 mwisend_rpas = 0;
13806 } else if (!reload){
13807 if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
13808 int orig_radio = confp->chan.radio;
13809 int orig_outsigmod = confp->chan.outsigmod;
13810 int orig_auto = confp->is_sig_auto;
13812 confp->chan.radio = 0;
13813 confp->chan.outsigmod = -1;
13814 confp->is_sig_auto = 0;
13815 if (!strcasecmp(v->value, "em")) {
13816 confp->chan.sig = SIG_EM;
13817 } else if (!strcasecmp(v->value, "em_e1")) {
13818 confp->chan.sig = SIG_EM_E1;
13819 } else if (!strcasecmp(v->value, "em_w")) {
13820 confp->chan.sig = SIG_EMWINK;
13821 } else if (!strcasecmp(v->value, "fxs_ls")) {
13822 confp->chan.sig = SIG_FXSLS;
13823 } else if (!strcasecmp(v->value, "fxs_gs")) {
13824 confp->chan.sig = SIG_FXSGS;
13825 } else if (!strcasecmp(v->value, "fxs_ks")) {
13826 confp->chan.sig = SIG_FXSKS;
13827 } else if (!strcasecmp(v->value, "fxo_ls")) {
13828 confp->chan.sig = SIG_FXOLS;
13829 } else if (!strcasecmp(v->value, "fxo_gs")) {
13830 confp->chan.sig = SIG_FXOGS;
13831 } else if (!strcasecmp(v->value, "fxo_ks")) {
13832 confp->chan.sig = SIG_FXOKS;
13833 } else if (!strcasecmp(v->value, "fxs_rx")) {
13834 confp->chan.sig = SIG_FXSKS;
13835 confp->chan.radio = 1;
13836 } else if (!strcasecmp(v->value, "fxo_rx")) {
13837 confp->chan.sig = SIG_FXOLS;
13838 confp->chan.radio = 1;
13839 } else if (!strcasecmp(v->value, "fxs_tx")) {
13840 confp->chan.sig = SIG_FXSLS;
13841 confp->chan.radio = 1;
13842 } else if (!strcasecmp(v->value, "fxo_tx")) {
13843 confp->chan.sig = SIG_FXOGS;
13844 confp->chan.radio = 1;
13845 } else if (!strcasecmp(v->value, "em_rx")) {
13846 confp->chan.sig = SIG_EM;
13847 confp->chan.radio = 1;
13848 } else if (!strcasecmp(v->value, "em_tx")) {
13849 confp->chan.sig = SIG_EM;
13850 confp->chan.radio = 1;
13851 } else if (!strcasecmp(v->value, "em_rxtx")) {
13852 confp->chan.sig = SIG_EM;
13853 confp->chan.radio = 2;
13854 } else if (!strcasecmp(v->value, "em_txrx")) {
13855 confp->chan.sig = SIG_EM;
13856 confp->chan.radio = 2;
13857 } else if (!strcasecmp(v->value, "sf")) {
13858 confp->chan.sig = SIG_SF;
13859 } else if (!strcasecmp(v->value, "sf_w")) {
13860 confp->chan.sig = SIG_SFWINK;
13861 } else if (!strcasecmp(v->value, "sf_featd")) {
13862 confp->chan.sig = SIG_FEATD;
13863 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13864 confp->chan.sig = SIG_FEATDMF;
13865 } else if (!strcasecmp(v->value, "sf_featb")) {
13866 confp->chan.sig = SIG_SF_FEATB;
13867 } else if (!strcasecmp(v->value, "sf")) {
13868 confp->chan.sig = SIG_SF;
13869 } else if (!strcasecmp(v->value, "sf_rx")) {
13870 confp->chan.sig = SIG_SF;
13871 confp->chan.radio = 1;
13872 } else if (!strcasecmp(v->value, "sf_tx")) {
13873 confp->chan.sig = SIG_SF;
13874 confp->chan.radio = 1;
13875 } else if (!strcasecmp(v->value, "sf_rxtx")) {
13876 confp->chan.sig = SIG_SF;
13877 confp->chan.radio = 2;
13878 } else if (!strcasecmp(v->value, "sf_txrx")) {
13879 confp->chan.sig = SIG_SF;
13880 confp->chan.radio = 2;
13881 } else if (!strcasecmp(v->value, "featd")) {
13882 confp->chan.sig = SIG_FEATD;
13883 } else if (!strcasecmp(v->value, "featdmf")) {
13884 confp->chan.sig = SIG_FEATDMF;
13885 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13886 confp->chan.sig = SIG_FEATDMF_TA;
13887 } else if (!strcasecmp(v->value, "e911")) {
13888 confp->chan.sig = SIG_E911;
13889 } else if (!strcasecmp(v->value, "fgccama")) {
13890 confp->chan.sig = SIG_FGC_CAMA;
13891 } else if (!strcasecmp(v->value, "fgccamamf")) {
13892 confp->chan.sig = SIG_FGC_CAMAMF;
13893 } else if (!strcasecmp(v->value, "featb")) {
13894 confp->chan.sig = SIG_FEATB;
13895 #ifdef HAVE_PRI
13896 } else if (!strcasecmp(v->value, "pri_net")) {
13897 confp->chan.sig = SIG_PRI;
13898 confp->pri.nodetype = PRI_NETWORK;
13899 } else if (!strcasecmp(v->value, "pri_cpe")) {
13900 confp->chan.sig = SIG_PRI;
13901 confp->pri.nodetype = PRI_CPE;
13902 } else if (!strcasecmp(v->value, "bri_cpe")) {
13903 confp->chan.sig = SIG_BRI;
13904 confp->pri.nodetype = PRI_CPE;
13905 } else if (!strcasecmp(v->value, "bri_net")) {
13906 confp->chan.sig = SIG_BRI;
13907 confp->pri.nodetype = PRI_NETWORK;
13908 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
13909 confp->chan.sig = SIG_BRI_PTMP;
13910 confp->pri.nodetype = PRI_CPE;
13911 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
13912 ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode! For now, sucks for you. (line %d)\n", v->lineno);
13913 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
13914 confp->chan.sig = SIG_GR303FXOKS;
13915 confp->pri.nodetype = PRI_NETWORK;
13916 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
13917 confp->chan.sig = SIG_GR303FXSKS;
13918 confp->pri.nodetype = PRI_CPE;
13919 #endif
13920 #ifdef HAVE_SS7
13921 } else if (!strcasecmp(v->value, "ss7")) {
13922 confp->chan.sig = SIG_SS7;
13923 #endif
13924 } else if (!strcasecmp(v->value, "auto")) {
13925 confp->is_sig_auto = 1;
13926 } else {
13927 confp->chan.outsigmod = orig_outsigmod;
13928 confp->chan.radio = orig_radio;
13929 confp->is_sig_auto = orig_auto;
13930 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
13932 } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
13933 if (!strcasecmp(v->value, "em")) {
13934 confp->chan.outsigmod = SIG_EM;
13935 } else if (!strcasecmp(v->value, "em_e1")) {
13936 confp->chan.outsigmod = SIG_EM_E1;
13937 } else if (!strcasecmp(v->value, "em_w")) {
13938 confp->chan.outsigmod = SIG_EMWINK;
13939 } else if (!strcasecmp(v->value, "sf")) {
13940 confp->chan.outsigmod = SIG_SF;
13941 } else if (!strcasecmp(v->value, "sf_w")) {
13942 confp->chan.outsigmod = SIG_SFWINK;
13943 } else if (!strcasecmp(v->value, "sf_featd")) {
13944 confp->chan.outsigmod = SIG_FEATD;
13945 } else if (!strcasecmp(v->value, "sf_featdmf")) {
13946 confp->chan.outsigmod = SIG_FEATDMF;
13947 } else if (!strcasecmp(v->value, "sf_featb")) {
13948 confp->chan.outsigmod = SIG_SF_FEATB;
13949 } else if (!strcasecmp(v->value, "sf")) {
13950 confp->chan.outsigmod = SIG_SF;
13951 } else if (!strcasecmp(v->value, "featd")) {
13952 confp->chan.outsigmod = SIG_FEATD;
13953 } else if (!strcasecmp(v->value, "featdmf")) {
13954 confp->chan.outsigmod = SIG_FEATDMF;
13955 } else if (!strcasecmp(v->value, "featdmf_ta")) {
13956 confp->chan.outsigmod = SIG_FEATDMF_TA;
13957 } else if (!strcasecmp(v->value, "e911")) {
13958 confp->chan.outsigmod = SIG_E911;
13959 } else if (!strcasecmp(v->value, "fgccama")) {
13960 confp->chan.outsigmod = SIG_FGC_CAMA;
13961 } else if (!strcasecmp(v->value, "fgccamamf")) {
13962 confp->chan.outsigmod = SIG_FGC_CAMAMF;
13963 } else if (!strcasecmp(v->value, "featb")) {
13964 confp->chan.outsigmod = SIG_FEATB;
13965 } else {
13966 ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
13968 #ifdef HAVE_PRI
13969 } else if (!strcasecmp(v->name, "pridialplan")) {
13970 if (!strcasecmp(v->value, "national")) {
13971 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
13972 } else if (!strcasecmp(v->value, "unknown")) {
13973 confp->pri.dialplan = PRI_UNKNOWN + 1;
13974 } else if (!strcasecmp(v->value, "private")) {
13975 confp->pri.dialplan = PRI_PRIVATE + 1;
13976 } else if (!strcasecmp(v->value, "international")) {
13977 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
13978 } else if (!strcasecmp(v->value, "local")) {
13979 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
13980 } else if (!strcasecmp(v->value, "dynamic")) {
13981 confp->pri.dialplan = -1;
13982 } else if (!strcasecmp(v->value, "redundant")) {
13983 confp->pri.dialplan = -2;
13984 } else {
13985 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
13987 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
13988 if (!strcasecmp(v->value, "national")) {
13989 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
13990 } else if (!strcasecmp(v->value, "unknown")) {
13991 confp->pri.localdialplan = PRI_UNKNOWN + 1;
13992 } else if (!strcasecmp(v->value, "private")) {
13993 confp->pri.localdialplan = PRI_PRIVATE + 1;
13994 } else if (!strcasecmp(v->value, "international")) {
13995 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
13996 } else if (!strcasecmp(v->value, "local")) {
13997 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
13998 } else if (!strcasecmp(v->value, "dynamic")) {
13999 confp->pri.localdialplan = -1;
14000 } else if (!strcasecmp(v->value, "redundant")) {
14001 confp->pri.localdialplan = -2;
14002 } else {
14003 ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14005 } else if (!strcasecmp(v->name, "switchtype")) {
14006 if (!strcasecmp(v->value, "national"))
14007 confp->pri.switchtype = PRI_SWITCH_NI2;
14008 else if (!strcasecmp(v->value, "ni1"))
14009 confp->pri.switchtype = PRI_SWITCH_NI1;
14010 else if (!strcasecmp(v->value, "dms100"))
14011 confp->pri.switchtype = PRI_SWITCH_DMS100;
14012 else if (!strcasecmp(v->value, "4ess"))
14013 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14014 else if (!strcasecmp(v->value, "5ess"))
14015 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14016 else if (!strcasecmp(v->value, "euroisdn"))
14017 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14018 else if (!strcasecmp(v->value, "qsig"))
14019 confp->pri.switchtype = PRI_SWITCH_QSIG;
14020 else {
14021 ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14022 return -1;
14024 } else if (!strcasecmp(v->name, "nsf")) {
14025 if (!strcasecmp(v->value, "sdn"))
14026 confp->pri.nsf = PRI_NSF_SDN;
14027 else if (!strcasecmp(v->value, "megacom"))
14028 confp->pri.nsf = PRI_NSF_MEGACOM;
14029 else if (!strcasecmp(v->value, "tollfreemegacom"))
14030 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
14031 else if (!strcasecmp(v->value, "accunet"))
14032 confp->pri.nsf = PRI_NSF_ACCUNET;
14033 else if (!strcasecmp(v->value, "none"))
14034 confp->pri.nsf = PRI_NSF_NONE;
14035 else {
14036 ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14037 confp->pri.nsf = PRI_NSF_NONE;
14039 } else if (!strcasecmp(v->name, "priindication")) {
14040 if (!strcasecmp(v->value, "outofband"))
14041 confp->chan.priindication_oob = 1;
14042 else if (!strcasecmp(v->value, "inband"))
14043 confp->chan.priindication_oob = 0;
14044 else
14045 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14046 v->value, v->lineno);
14047 } else if (!strcasecmp(v->name, "priexclusive")) {
14048 confp->chan.priexclusive = ast_true(v->value);
14049 } else if (!strcasecmp(v->name, "internationalprefix")) {
14050 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14051 } else if (!strcasecmp(v->name, "nationalprefix")) {
14052 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14053 } else if (!strcasecmp(v->name, "localprefix")) {
14054 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14055 } else if (!strcasecmp(v->name, "privateprefix")) {
14056 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14057 } else if (!strcasecmp(v->name, "unknownprefix")) {
14058 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14059 } else if (!strcasecmp(v->name, "resetinterval")) {
14060 if (!strcasecmp(v->value, "never"))
14061 confp->pri.resetinterval = -1;
14062 else if (atoi(v->value) >= 60)
14063 confp->pri.resetinterval = atoi(v->value);
14064 else
14065 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14066 v->value, v->lineno);
14067 } else if (!strcasecmp(v->name, "minunused")) {
14068 confp->pri.minunused = atoi(v->value);
14069 } else if (!strcasecmp(v->name, "minidle")) {
14070 confp->pri.minidle = atoi(v->value);
14071 } else if (!strcasecmp(v->name, "idleext")) {
14072 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14073 } else if (!strcasecmp(v->name, "idledial")) {
14074 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14075 } else if (!strcasecmp(v->name, "overlapdial")) {
14076 if (ast_true(v->value)) {
14077 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14078 } else if (!strcasecmp(v->value, "incoming")) {
14079 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14080 } else if (!strcasecmp(v->value, "outgoing")) {
14081 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14082 } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14083 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14084 } else {
14085 confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14087 #ifdef HAVE_PRI_INBANDDISCONNECT
14088 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14089 confp->pri.inbanddisconnect = ast_true(v->value);
14090 #endif
14091 } else if (!strcasecmp(v->name, "pritimer")) {
14092 #ifdef PRI_GETSET_TIMERS
14093 char tmp[20], *timerc, *c = tmp;
14094 int timer, timeridx;
14095 ast_copy_string(tmp, v->value, sizeof(tmp));
14096 timerc = strsep(&c, ",");
14097 if (timerc) {
14098 timer = atoi(c);
14099 if (!timer)
14100 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno);
14101 else {
14102 if ((timeridx = pri_timer2idx(timerc)) >= 0)
14103 pritimers[timeridx] = timer;
14104 else
14105 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno);
14107 } else
14108 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno);
14110 } else if (!strcasecmp(v->name, "facilityenable")) {
14111 confp->pri.facilityenable = ast_true(v->value);
14112 #endif /* PRI_GETSET_TIMERS */
14113 #endif /* HAVE_PRI */
14114 #ifdef HAVE_SS7
14115 } else if (!strcasecmp(v->name, "ss7type")) {
14116 if (!strcasecmp(v->value, "itu")) {
14117 cur_ss7type = SS7_ITU;
14118 } else if (!strcasecmp(v->value, "ansi")) {
14119 cur_ss7type = SS7_ANSI;
14120 } else
14121 ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14122 } else if (!strcasecmp(v->name, "linkset")) {
14123 cur_linkset = atoi(v->value);
14124 } else if (!strcasecmp(v->name, "pointcode")) {
14125 cur_pointcode = parse_pointcode(v->value);
14126 } else if (!strcasecmp(v->name, "adjpointcode")) {
14127 cur_adjpointcode = parse_pointcode(v->value);
14128 } else if (!strcasecmp(v->name, "defaultdpc")) {
14129 cur_defaultdpc = parse_pointcode(v->value);
14130 } else if (!strcasecmp(v->name, "cicbeginswith")) {
14131 cur_cicbeginswith = atoi(v->value);
14132 } else if (!strcasecmp(v->name, "networkindicator")) {
14133 if (!strcasecmp(v->value, "national"))
14134 cur_networkindicator = SS7_NI_NAT;
14135 else if (!strcasecmp(v->value, "national_spare"))
14136 cur_networkindicator = SS7_NI_NAT_SPARE;
14137 else if (!strcasecmp(v->value, "international"))
14138 cur_networkindicator = SS7_NI_INT;
14139 else if (!strcasecmp(v->value, "international_spare"))
14140 cur_networkindicator = SS7_NI_INT_SPARE;
14141 else
14142 cur_networkindicator = -1;
14143 } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14144 ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14145 } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14146 ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14147 } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14148 ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14149 } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14150 ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14151 } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14152 if (!strcasecmp(v->value, "national")) {
14153 confp->ss7.called_nai = SS7_NAI_NATIONAL;
14154 } else if (!strcasecmp(v->value, "international")) {
14155 confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14156 } else if (!strcasecmp(v->value, "subscriber")) {
14157 confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14158 } else if (!strcasecmp(v->value, "dynamic")) {
14159 confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14160 } else {
14161 ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14163 } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14164 if (!strcasecmp(v->value, "national")) {
14165 confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14166 } else if (!strcasecmp(v->value, "international")) {
14167 confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14168 } else if (!strcasecmp(v->value, "subscriber")) {
14169 confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14170 } else if (!strcasecmp(v->value, "dynamic")) {
14171 confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14172 } else {
14173 ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14175 } else if (!strcasecmp(v->name, "sigchan")) {
14176 int sigchan, res;
14177 sigchan = atoi(v->value);
14178 res = linkset_addsigchan(sigchan);
14179 if (res < 0)
14180 return -1;
14182 } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14183 struct dahdi_ss7 *link;
14184 link = ss7_resolve_linkset(cur_linkset);
14185 if (!link) {
14186 ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
14187 return -1;
14189 if (ast_true(v->value))
14190 link->flags |= LINKSET_FLAG_EXPLICITACM;
14192 #endif /* HAVE_SS7 */
14193 } else if (!strcasecmp(v->name, "cadence")) {
14194 /* setup to scan our argument */
14195 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14196 int i;
14197 struct dahdi_ring_cadence new_cadence;
14198 int cid_location = -1;
14199 int firstcadencepos = 0;
14200 char original_args[80];
14201 int cadence_is_ok = 1;
14203 ast_copy_string(original_args, v->value, sizeof(original_args));
14204 /* 16 cadences allowed (8 pairs) */
14205 element_count = sscanf(v->value, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &c[0], &c[1], &c[2], &c[3], &c[4], &c[5], &c[6], &c[7], &c[8], &c[9], &c[10], &c[11], &c[12], &c[13], &c[14], &c[15]);
14207 /* Cadence must be even (on/off) */
14208 if (element_count % 2 == 1) {
14209 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14210 cadence_is_ok = 0;
14213 /* Ring cadences cannot be negative */
14214 for (i = 0; i < element_count; i++) {
14215 if (c[i] == 0) {
14216 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14217 cadence_is_ok = 0;
14218 break;
14219 } else if (c[i] < 0) {
14220 if (i % 2 == 1) {
14221 /* Silence duration, negative possibly okay */
14222 if (cid_location == -1) {
14223 cid_location = i;
14224 c[i] *= -1;
14225 } else {
14226 ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14227 cadence_is_ok = 0;
14228 break;
14230 } else {
14231 if (firstcadencepos == 0) {
14232 firstcadencepos = i; /* only recorded to avoid duplicate specification */
14233 /* duration will be passed negative to the DAHDI driver */
14234 } else {
14235 ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14236 cadence_is_ok = 0;
14237 break;
14243 /* Substitute our scanned cadence */
14244 for (i = 0; i < 16; i++) {
14245 new_cadence.ringcadence[i] = c[i];
14248 if (cadence_is_ok) {
14249 /* ---we scanned it without getting annoyed; now some sanity checks--- */
14250 if (element_count < 2) {
14251 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14252 } else {
14253 if (cid_location == -1) {
14254 /* user didn't say; default to first pause */
14255 cid_location = 1;
14256 } else {
14257 /* convert element_index to cidrings value */
14258 cid_location = (cid_location + 1) / 2;
14260 /* ---we like their cadence; try to install it--- */
14261 if (!user_has_defined_cadences++)
14262 /* this is the first user-defined cadence; clear the default user cadences */
14263 num_cadence = 0;
14264 if ((num_cadence+1) >= NUM_CADENCE_MAX)
14265 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
14266 else {
14267 cadences[num_cadence] = new_cadence;
14268 cidrings[num_cadence++] = cid_location;
14269 ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
14273 } else if (!strcasecmp(v->name, "ringtimeout")) {
14274 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
14275 } else if (!strcasecmp(v->name, "prewink")) {
14276 confp->timing.prewinktime = atoi(v->value);
14277 } else if (!strcasecmp(v->name, "preflash")) {
14278 confp->timing.preflashtime = atoi(v->value);
14279 } else if (!strcasecmp(v->name, "wink")) {
14280 confp->timing.winktime = atoi(v->value);
14281 } else if (!strcasecmp(v->name, "flash")) {
14282 confp->timing.flashtime = atoi(v->value);
14283 } else if (!strcasecmp(v->name, "start")) {
14284 confp->timing.starttime = atoi(v->value);
14285 } else if (!strcasecmp(v->name, "rxwink")) {
14286 confp->timing.rxwinktime = atoi(v->value);
14287 } else if (!strcasecmp(v->name, "rxflash")) {
14288 confp->timing.rxflashtime = atoi(v->value);
14289 } else if (!strcasecmp(v->name, "debounce")) {
14290 confp->timing.debouncetime = atoi(v->value);
14291 } else if (!strcasecmp(v->name, "toneduration")) {
14292 int toneduration;
14293 int ctlfd;
14294 int res;
14295 struct dahdi_dialparams dps;
14297 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
14298 if (ctlfd == -1) {
14299 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
14300 return -1;
14303 toneduration = atoi(v->value);
14304 if (toneduration > -1) {
14305 memset(&dps, 0, sizeof(dps));
14307 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
14308 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
14309 if (res < 0) {
14310 ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
14311 return -1;
14314 close(ctlfd);
14315 } else if (!strcasecmp(v->name, "defaultcic")) {
14316 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
14317 } else if (!strcasecmp(v->name, "defaultozz")) {
14318 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
14319 } else if (!strcasecmp(v->name, "mwilevel")) {
14320 mwilevel = atoi(v->value);
14322 } else if (!(options && PROC_DAHDI_OPT_NOWARN) )
14323 ast_log(LOG_WARNING, "Ignoring %s at line %d.\n", v->name, v->lineno);
14325 if (dahdichan[0]) {
14326 /* The user has set 'dahdichan' */
14327 /*< \todo pass proper line number instead of 0 */
14328 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
14329 return -1;
14332 /*< \todo why check for the pseudo in the per-channel section.
14333 * Any actual use for manual setup of the pseudo channel? */
14334 if (!found_pseudo && reload == 0) {
14335 /* Make sure pseudo isn't a member of any groups if
14336 we're automatically making it. */
14338 confp->chan.group = 0;
14339 confp->chan.callgroup = 0;
14340 confp->chan.pickupgroup = 0;
14342 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
14344 if (tmp) {
14345 ast_verb(3, "Automatically generated pseudo channel\n");
14346 } else {
14347 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
14350 return 0;
14353 static int setup_dahdi(int reload)
14355 struct ast_config *cfg, *ucfg;
14356 struct ast_variable *v;
14357 struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
14358 struct dahdi_chan_conf conf;
14359 struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
14360 const char *cat;
14361 int res;
14363 #ifdef HAVE_PRI
14364 char *c;
14365 int spanno;
14366 int i;
14367 int logicalspan;
14368 int trunkgroup;
14369 int dchannels[NUM_DCHANS];
14370 #endif
14372 cfg = ast_config_load(config, config_flags);
14374 /* Error if we have no config file */
14375 if (!cfg) {
14376 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
14377 return 0;
14378 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
14379 ucfg = ast_config_load("users.conf", config_flags);
14380 if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
14381 return 0;
14382 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14383 cfg = ast_config_load(config, config_flags);
14384 } else {
14385 ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14386 ucfg = ast_config_load("users.conf", config_flags);
14389 /* It's a little silly to lock it, but we mind as well just to be sure */
14390 ast_mutex_lock(&iflock);
14391 #ifdef HAVE_PRI
14392 if (!reload) {
14393 /* Process trunkgroups first */
14394 v = ast_variable_browse(cfg, "trunkgroups");
14395 while (v) {
14396 if (!strcasecmp(v->name, "trunkgroup")) {
14397 trunkgroup = atoi(v->value);
14398 if (trunkgroup > 0) {
14399 if ((c = strchr(v->value, ','))) {
14400 i = 0;
14401 memset(dchannels, 0, sizeof(dchannels));
14402 while (c && (i < NUM_DCHANS)) {
14403 dchannels[i] = atoi(c + 1);
14404 if (dchannels[i] < 0) {
14405 ast_log(LOG_WARNING, "D-channel for trunk group %d must be a postiive number at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14406 } else
14407 i++;
14408 c = strchr(c + 1, ',');
14410 if (i) {
14411 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
14412 ast_log(LOG_WARNING, "Unable to create trunk group %d with Primary D-channel %d at line %d of chan_dahdi.conf\n", trunkgroup, dchannels[0], v->lineno);
14413 } else
14414 ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
14415 } else
14416 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14417 } else
14418 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14419 } else
14420 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
14421 } else if (!strcasecmp(v->name, "spanmap")) {
14422 spanno = atoi(v->value);
14423 if (spanno > 0) {
14424 if ((c = strchr(v->value, ','))) {
14425 trunkgroup = atoi(c + 1);
14426 if (trunkgroup > 0) {
14427 if ((c = strchr(c + 1, ',')))
14428 logicalspan = atoi(c + 1);
14429 else
14430 logicalspan = 0;
14431 if (logicalspan >= 0) {
14432 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
14433 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14434 } else
14435 ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14436 } else
14437 ast_log(LOG_WARNING, "Logical span must be a postive number, or '0' (for unspecified) at line %d of chan_dahdi.conf\n", v->lineno);
14438 } else
14439 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
14440 } else
14441 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
14442 } else
14443 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
14444 } else {
14445 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
14447 v = v->next;
14450 #endif
14452 /* Copy the default jb config over global_jbconf */
14453 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
14455 mwimonitornotify[0] = '\0';
14457 v = ast_variable_browse(cfg, "channels");
14458 if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
14459 ast_mutex_unlock(&iflock);
14460 ast_config_destroy(cfg);
14461 if (ucfg) {
14462 ast_config_destroy(ucfg);
14464 return res;
14467 /* Now get configuration from all normal sections in chan_dahdi.conf: */
14468 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
14469 /* [channels] and [trunkgroups] are used. Let's also reserve
14470 * [globals] and [general] for future use
14472 if (!strcasecmp(cat, "general") ||
14473 !strcasecmp(cat, "trunkgroups") ||
14474 !strcasecmp(cat, "globals") ||
14475 !strcasecmp(cat, "channels")) {
14476 continue;
14479 memcpy(&conf, &base_conf, sizeof(conf));
14481 if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
14482 ast_mutex_unlock(&iflock);
14483 ast_config_destroy(cfg);
14484 if (ucfg) {
14485 ast_config_destroy(cfg);
14487 return res;
14491 ast_config_destroy(cfg);
14493 if (ucfg) {
14494 const char *chans;
14496 process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
14498 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
14499 if (!strcasecmp(cat, "general")) {
14500 continue;
14503 chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
14505 if (ast_strlen_zero(chans)) {
14506 continue;
14509 memcpy(&conf, &base_conf, sizeof(conf));
14511 if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
14512 ast_config_destroy(ucfg);
14513 ast_mutex_unlock(&iflock);
14514 return res;
14517 ast_config_destroy(ucfg);
14519 ast_mutex_unlock(&iflock);
14521 #ifdef HAVE_PRI
14522 if (!reload) {
14523 int x;
14524 for (x = 0; x < NUM_SPANS; x++) {
14525 if (pris[x].pvts[0]) {
14526 if (start_pri(pris + x)) {
14527 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
14528 return -1;
14529 } else
14530 ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
14534 #endif
14535 #ifdef HAVE_SS7
14536 if (!reload) {
14537 int x;
14538 for (x = 0; x < NUM_SPANS; x++) {
14539 if (linksets[x].ss7) {
14540 if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
14541 ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
14542 return -1;
14543 } else
14544 ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
14548 #endif
14549 /* And start the monitor for the first time */
14550 restart_monitor();
14551 return 0;
14554 static int load_module(void)
14556 int res;
14557 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14558 int y, i;
14559 #endif
14561 #ifdef HAVE_PRI
14562 memset(pris, 0, sizeof(pris));
14563 for (y = 0; y < NUM_SPANS; y++) {
14564 ast_mutex_init(&pris[y].lock);
14565 pris[y].offset = -1;
14566 pris[y].master = AST_PTHREADT_NULL;
14567 for (i = 0; i < NUM_DCHANS; i++)
14568 pris[y].fds[i] = -1;
14570 pri_set_error(dahdi_pri_error);
14571 pri_set_message(dahdi_pri_message);
14572 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
14573 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
14574 #endif
14575 #ifdef HAVE_SS7
14576 memset(linksets, 0, sizeof(linksets));
14577 for (y = 0; y < NUM_SPANS; y++) {
14578 ast_mutex_init(&linksets[y].lock);
14579 linksets[y].master = AST_PTHREADT_NULL;
14580 for (i = 0; i < NUM_DCHANS; i++)
14581 linksets[y].fds[i] = -1;
14583 ss7_set_error(dahdi_ss7_error);
14584 ss7_set_message(dahdi_ss7_message);
14585 #endif /* HAVE_SS7 */
14586 res = setup_dahdi(0);
14587 /* Make sure we can register our DAHDI channel type */
14588 if (res)
14589 return AST_MODULE_LOAD_DECLINE;
14590 if (ast_channel_register(&dahdi_tech)) {
14591 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
14592 __unload_module();
14593 return AST_MODULE_LOAD_FAILURE;
14595 #ifdef HAVE_PRI
14596 ast_string_field_init(&inuse, 16);
14597 ast_string_field_set(&inuse, name, "GR-303InUse");
14598 ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14599 #endif
14600 #ifdef HAVE_SS7
14601 ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
14602 #endif
14604 ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
14606 memset(round_robin, 0, sizeof(round_robin));
14607 ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
14608 ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
14609 ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
14610 ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
14611 ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
14612 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
14613 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
14615 return res;
14618 static int dahdi_sendtext(struct ast_channel *c, const char *text)
14620 #define END_SILENCE_LEN 400
14621 #define HEADER_MS 50
14622 #define TRAILER_MS 5
14623 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
14624 #define ASCII_BYTES_PER_CHAR 80
14626 unsigned char *buf,*mybuf;
14627 struct dahdi_pvt *p = c->tech_pvt;
14628 struct pollfd fds[1];
14629 int size,res,fd,len,x;
14630 int bytes=0;
14631 /* Initial carrier (imaginary) */
14632 float cr = 1.0;
14633 float ci = 0.0;
14634 float scont = 0.0;
14635 int idx;
14637 idx = dahdi_get_index(c, p, 0);
14638 if (idx < 0) {
14639 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
14640 return -1;
14642 if (!text[0]) return(0); /* if nothing to send, dont */
14643 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
14644 if (p->mate)
14645 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
14646 else
14647 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
14648 if (!buf)
14649 return -1;
14650 mybuf = buf;
14651 if (p->mate) {
14652 int codec = AST_LAW(p);
14653 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
14654 PUT_CLID_MARKMS;
14656 /* Put actual message */
14657 for (x = 0; text[x]; x++) {
14658 PUT_CLID(text[x]);
14660 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
14661 PUT_CLID_MARKMS;
14663 len = bytes;
14664 buf = mybuf;
14665 } else {
14666 len = tdd_generate(p->tdd, buf, text);
14667 if (len < 1) {
14668 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
14669 ast_free(mybuf);
14670 return -1;
14673 memset(buf + len, 0x7f, END_SILENCE_LEN);
14674 len += END_SILENCE_LEN;
14675 fd = p->subs[idx].zfd;
14676 while (len) {
14677 if (ast_check_hangup(c)) {
14678 ast_free(mybuf);
14679 return -1;
14681 size = len;
14682 if (size > READ_SIZE)
14683 size = READ_SIZE;
14684 fds[0].fd = fd;
14685 fds[0].events = POLLOUT | POLLPRI;
14686 fds[0].revents = 0;
14687 res = poll(fds, 1, -1);
14688 if (!res) {
14689 ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
14690 continue;
14692 /* if got exception */
14693 if (fds[0].revents & POLLPRI) {
14694 ast_free(mybuf);
14695 return -1;
14697 if (!(fds[0].revents & POLLOUT)) {
14698 ast_debug(1, "write fd not ready on channel %d\n", p->channel);
14699 continue;
14701 res = write(fd, buf, size);
14702 if (res != size) {
14703 if (res == -1) {
14704 ast_free(mybuf);
14705 return -1;
14707 ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
14708 break;
14710 len -= size;
14711 buf += size;
14713 ast_free(mybuf);
14714 return(0);
14718 static int reload(void)
14720 int res = 0;
14722 res = setup_dahdi(1);
14723 if (res) {
14724 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
14725 return -1;
14727 return 0;
14730 /* This is a workaround so that menuselect displays a proper description
14731 * AST_MODULE_INFO(, , "DAHDI Telephony"
14734 #ifdef HAVE_PRI
14735 #ifdef HAVE_SS7
14736 #define tdesc "DAHDI Telephony w/PRI & SS7"
14737 #else
14738 #define tdesc "DAHDI Telephony w/PRI"
14739 #endif
14740 #else
14741 #ifdef HAVE_SS7
14742 #define tdesc "DAHDI Telephony w/SS7"
14743 #else
14744 #define tdesc "DAHDI Telephony"
14745 #endif
14746 #endif
14748 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
14749 .load = load_module,
14750 .unload = unload_module,
14751 .reload = reload,