new installations should be using DAHDI instead of Zaptel, so the sample config file...
[asterisk-bristuff.git] / channels / chan_dahdi.c
blobf74cd3169aedf4b3052e9f8aa2bde9a9c5514006
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 Pseudo TDM interface
23 * \author Mark Spencer <markster@digium.com>
25 * Connects to the DAHDI telephony library as well as
26 * libpri. Libpri is optional and needed only if you are
27 * going to use ISDN connections.
29 * You need to install libraries before you attempt to compile
30 * and install the DAHDI channel.
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 <depend>res_features</depend>
45 <use>pri</use>
46 ***/
48 #include "asterisk.h"
50 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
52 #include <stdio.h>
53 #include <string.h>
54 #ifdef __NetBSD__
55 #include <pthread.h>
56 #include <signal.h>
57 #else
58 #include <sys/signal.h>
59 #endif
60 #include <errno.h>
61 #include <stdlib.h>
62 #if !defined(SOLARIS) && !defined(__FreeBSD__)
63 #include <stdint.h>
64 #endif
65 #include <unistd.h>
66 #include <sys/ioctl.h>
67 #include <math.h>
68 #include <ctype.h>
70 #ifdef HAVE_PRI
71 #include <libpri.h>
72 #endif
74 #include "asterisk/lock.h"
75 #include "asterisk/channel.h"
76 #include "asterisk/config.h"
77 #include "asterisk/logger.h"
78 #include "asterisk/module.h"
79 #include "asterisk/pbx.h"
80 #include "asterisk/options.h"
81 #include "asterisk/file.h"
82 #include "asterisk/ulaw.h"
83 #include "asterisk/alaw.h"
84 #include "asterisk/callerid.h"
85 #include "asterisk/adsi.h"
86 #include "asterisk/cli.h"
87 #include "asterisk/cdr.h"
88 #include "asterisk/features.h"
89 #include "asterisk/musiconhold.h"
90 #include "asterisk/say.h"
91 #include "asterisk/tdd.h"
92 #include "asterisk/app.h"
93 #include "asterisk/dsp.h"
94 #include "asterisk/astdb.h"
95 #include "asterisk/manager.h"
96 #include "asterisk/causes.h"
97 #include "asterisk/term.h"
98 #include "asterisk/utils.h"
99 #include "asterisk/transcap.h"
100 #include "asterisk/stringfields.h"
101 #include "asterisk/abstract_jb.h"
102 #include "asterisk/smdi.h"
103 #include "asterisk/astobj.h"
104 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
106 #include "asterisk/dahdi_compat.h"
107 #include "asterisk/tonezone_compat.h"
109 /*! Global jitterbuffer configuration - by default, jb is disabled */
110 static struct ast_jb_conf default_jbconf =
112 .flags = 0,
113 .max_size = -1,
114 .resync_threshold = -1,
115 .impl = ""
117 static struct ast_jb_conf global_jbconf;
119 #if !defined(DAHDI_SIG_EM_E1) || (defined(HAVE_PRI) && !defined(DAHDI_SIG_HARDHDLC))
120 #error "Your DAHDI is too old. Please update"
121 #endif
123 #ifndef DAHDI_TONEDETECT
124 /* Work around older code with no tone detect */
125 #define DAHDI_EVENT_DTMFDOWN 0
126 #define DAHDI_EVENT_DTMFUP 0
127 #endif
129 /* define this to send PRI user-user information elements */
130 #undef SUPPORT_USERUSER
132 /*!
133 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
134 * the user hangs up to reset the state machine so ring works properly.
135 * This is used to be able to support kewlstart by putting the zhone in
136 * groundstart mode since their forward disconnect supervision is entirely
137 * broken even though their documentation says it isn't and their support
138 * is entirely unwilling to provide any assistance with their channel banks
139 * even though their web site says they support their products for life.
141 /* #define ZHONE_HACK */
143 /*! \note
144 * Define if you want to check the hook state for an FXO (FXS signalled) interface
145 * before dialing on it. Certain FXO interfaces always think they're out of
146 * service with this method however.
148 /* #define DAHDI_CHECK_HOOKSTATE */
150 /*! \brief Typically, how many rings before we should send Caller*ID */
151 #define DEFAULT_CIDRINGS 1
153 #define CHANNEL_PSEUDO -12
155 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
157 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
158 #define NEED_MFDETECT(p) (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
160 static const char tdesc[] = "DAHDI Telephony Driver"
161 #ifdef HAVE_PRI
162 " w/PRI"
163 #endif
166 #define SIG_EM DAHDI_SIG_EM
167 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
168 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
169 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
170 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
171 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
172 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
173 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
174 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
175 #define SIG_FXSLS DAHDI_SIG_FXSLS
176 #define SIG_FXSGS DAHDI_SIG_FXSGS
177 #define SIG_FXSKS DAHDI_SIG_FXSKS
178 #define SIG_FXOLS DAHDI_SIG_FXOLS
179 #define SIG_FXOGS DAHDI_SIG_FXOGS
180 #define SIG_FXOKS DAHDI_SIG_FXOKS
181 #define SIG_PRI DAHDI_SIG_CLEAR
182 #define SIG_SF DAHDI_SIG_SF
183 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
184 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
185 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
186 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
187 #define SIG_EM_E1 DAHDI_SIG_EM_E1
188 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
189 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
191 #define NUM_SPANS 32
192 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
193 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
195 #define CHAN_PSEUDO -2
197 #define DCHAN_PROVISIONED (1 << 0)
198 #define DCHAN_NOTINALARM (1 << 1)
199 #define DCHAN_UP (1 << 2)
201 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
203 static char defaultcic[64] = "";
204 static char defaultozz[64] = "";
206 static char progzone[10] = "";
208 static int distinctiveringaftercid = 0;
210 static int numbufs = 4;
212 #ifdef HAVE_PRI
213 static struct ast_channel inuse;
214 #ifdef PRI_GETSET_TIMERS
215 static int pritimers[PRI_MAX_TIMERS];
216 #endif
217 static int pridebugfd = -1;
218 static char pridebugfilename[1024] = "";
219 #endif
221 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
222 static int firstdigittimeout = 16000;
224 /*! \brief How long to wait for following digits (FXO logic) */
225 static int gendigittimeout = 8000;
227 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
228 static int matchdigittimeout = 3000;
230 /*! \brief Protect the interface list (of dahdi_pvt's) */
231 AST_MUTEX_DEFINE_STATIC(iflock);
234 static int ifcount = 0;
236 #ifdef HAVE_PRI
237 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
238 #endif
240 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
241 when it's doing something critical. */
242 AST_MUTEX_DEFINE_STATIC(monlock);
244 /*! \brief This is the thread for the monitor which checks for input on the channels
245 which are not currently in use. */
246 static pthread_t monitor_thread = AST_PTHREADT_NULL;
248 static int restart_monitor(void);
250 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);
252 static int dahdi_sendtext(struct ast_channel *c, const char *text);
254 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
255 static inline int dahdi_get_event(int fd)
257 int j;
258 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
259 return -1;
260 return j;
263 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
264 static inline int dahdi_wait_event(int fd)
266 int i, j = 0;
267 i = DAHDI_IOMUX_SIGEVENT;
268 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
269 return -1;
270 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
271 return -1;
272 return j;
275 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
276 #define READ_SIZE 160
278 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
279 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
281 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
282 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
283 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
284 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
285 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
287 struct dahdi_pvt;
289 static int ringt_base = DEFAULT_RINGT;
291 #ifdef HAVE_PRI
293 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
294 #define PRI_CHANNEL(p) ((p) & 0xff)
295 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
296 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
298 struct dahdi_pri {
299 pthread_t master; /*!< Thread of master */
300 ast_mutex_t lock; /*!< Mutex */
301 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
302 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
303 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
304 int minunused; /*!< Min # of channels to keep empty */
305 int minidle; /*!< Min # of "idling" calls to keep active */
306 int nodetype; /*!< Node type */
307 int switchtype; /*!< Type of switch to emulate */
308 int nsf; /*!< Network-Specific Facilities */
309 int dialplan; /*!< Dialing plan */
310 int localdialplan; /*!< Local dialing plan */
311 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
312 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
313 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
314 char privateprefix[20]; /*!< for private dialplans */
315 char unknownprefix[20]; /*!< for unknown dialplans */
316 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
317 int trunkgroup; /*!< What our trunkgroup is */
318 int mastertrunkgroup; /*!< What trunk group is our master */
319 int prilogicalspan; /*!< Logical span number within trunk group */
320 int numchans; /*!< Num of channels we represent */
321 int overlapdial; /*!< In overlap dialing mode */
322 int facilityenable; /*!< Enable facility IEs */
323 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
324 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
325 struct pri *pri; /*!< Currently active D-channel */
326 int debug;
327 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
328 int offset;
329 int span;
330 int resetting;
331 int resetpos;
332 #ifdef HAVE_PRI_INBANDRELEASE
333 unsigned int inbandrelease:1; /*!< Should we support inband audio after receiving RELEASE? */
334 #endif
335 time_t lastreset; /*!< time when unused channels were last reset */
336 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
337 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
338 struct dahdi_pvt *crvs; /*!< Member CRV structs */
339 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
343 static struct dahdi_pri pris[NUM_SPANS];
345 #if 0
346 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
347 #else
348 #define DEFAULT_PRI_DEBUG 0
349 #endif
351 static inline void pri_rel(struct dahdi_pri *pri)
353 ast_mutex_unlock(&pri->lock);
356 #else
357 /*! Shut up the compiler */
358 struct dahdi_pri;
359 #endif
361 #define SUB_REAL 0 /*!< Active call */
362 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
363 #define SUB_THREEWAY 2 /*!< Three-way call */
365 /* Polarity states */
366 #define POLARITY_IDLE 0
367 #define POLARITY_REV 1
370 static struct dahdi_distRings drings;
372 struct distRingData {
373 int ring[3];
375 struct ringContextData {
376 char contextData[AST_MAX_CONTEXT];
378 struct dahdi_distRings {
379 struct distRingData ringnum[3];
380 struct ringContextData ringContext[3];
383 static char *subnames[] = {
384 "Real",
385 "Callwait",
386 "Threeway"
389 struct dahdi_subchannel {
390 int dfd;
391 struct ast_channel *owner;
392 int chan;
393 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
394 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
395 unsigned int needringing:1;
396 unsigned int needbusy:1;
397 unsigned int needcongestion:1;
398 unsigned int needcallerid:1;
399 unsigned int needanswer:1;
400 unsigned int needflash:1;
401 unsigned int needhold:1;
402 unsigned int needunhold:1;
403 unsigned int linear:1;
404 unsigned int inthreeway:1;
405 DAHDI_CONFINFO curconf;
408 #define CONF_USER_REAL (1 << 0)
409 #define CONF_USER_THIRDCALL (1 << 1)
411 #define MAX_SLAVES 4
413 static struct dahdi_pvt {
414 ast_mutex_t lock;
415 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
416 /*!< Up to three channels can be associated with this call */
418 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
419 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
420 DAHDI_CONFINFO saveconf; /*!< Saved conference info */
422 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
423 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
424 int inconference; /*!< If our real should be in the conference */
426 int sig; /*!< Signalling style */
427 int radio; /*!< radio type */
428 int outsigmod; /*!< Outbound Signalling style (modifier) */
429 int oprmode; /*!< "Operator Services" mode */
430 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
431 float rxgain;
432 float txgain;
433 int tonezone; /*!< tone zone for this chan, or -1 for default */
434 struct dahdi_pvt *next; /*!< Next channel in list */
435 struct dahdi_pvt *prev; /*!< Prev channel in list */
437 /* flags */
438 unsigned int adsi:1;
439 unsigned int answeronpolarityswitch:1;
440 unsigned int busydetect:1;
441 unsigned int callreturn:1;
442 unsigned int callwaiting:1;
443 unsigned int callwaitingcallerid:1;
444 unsigned int cancallforward:1;
445 unsigned int canpark:1;
446 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
447 unsigned int destroy:1;
448 unsigned int didtdd:1; /*!< flag to say its done it once */
449 unsigned int dialednone:1;
450 unsigned int dialing:1;
451 unsigned int digital:1;
452 unsigned int dnd:1;
453 unsigned int echobreak:1;
454 unsigned int echocanbridged:1;
455 unsigned int echocanon:1;
456 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
457 unsigned int firstradio:1;
458 unsigned int hanguponpolarityswitch:1;
459 unsigned int hardwaredtmf:1;
460 unsigned int hidecallerid:1;
461 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
462 unsigned int ignoredtmf:1;
463 unsigned int immediate:1; /*!< Answer before getting digits? */
464 unsigned int inalarm:1;
465 unsigned int unknown_alarm:1;
466 unsigned int mate:1; /*!< flag to say its in MATE mode */
467 unsigned int outgoing:1;
468 unsigned int overlapdial:1;
469 unsigned int permcallwaiting:1;
470 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
471 unsigned int priindication_oob:1;
472 unsigned int priexclusive:1;
473 unsigned int pulse:1;
474 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
475 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
476 unsigned int threewaycalling:1;
477 unsigned int transfer:1;
478 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
479 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
480 unsigned int usedistinctiveringdetection:1;
481 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
482 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
483 #if defined(HAVE_PRI)
484 unsigned int alerting:1;
485 unsigned int alreadyhungup:1;
486 unsigned int isidlecall:1;
487 unsigned int proceeding:1;
488 unsigned int progress:1;
489 unsigned int resetting:1;
490 unsigned int setup_ack:1;
491 #endif
492 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
493 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
495 struct dahdi_distRings drings;
497 char context[AST_MAX_CONTEXT];
498 char defcontext[AST_MAX_CONTEXT];
499 char exten[AST_MAX_EXTENSION];
500 char language[MAX_LANGUAGE];
501 char mohinterpret[MAX_MUSICCLASS];
502 char mohsuggest[MAX_MUSICCLASS];
503 #ifdef PRI_ANI
504 char cid_ani[AST_MAX_EXTENSION];
505 #endif
506 char cid_num[AST_MAX_EXTENSION];
507 int cid_ton; /*!< Type Of Number (TON) */
508 char cid_name[AST_MAX_EXTENSION];
509 char lastcid_num[AST_MAX_EXTENSION];
510 char lastcid_name[AST_MAX_EXTENSION];
511 char *origcid_num; /*!< malloced original callerid */
512 char *origcid_name; /*!< malloced original callerid */
513 char callwait_num[AST_MAX_EXTENSION];
514 char callwait_name[AST_MAX_EXTENSION];
515 char rdnis[AST_MAX_EXTENSION];
516 char dnid[AST_MAX_EXTENSION];
517 ast_group_t group;
518 int law;
519 int confno; /*!< Our conference */
520 int confusers; /*!< Who is using our conference */
521 int propconfno; /*!< Propagated conference number */
522 ast_group_t callgroup;
523 ast_group_t pickupgroup;
524 int channel; /*!< Channel Number or CRV */
525 int span; /*!< Span number */
526 time_t guardtime; /*!< Must wait this much time before using for new call */
527 int cid_signalling; /*!< CID signalling type bell202 or v23 */
528 int cid_start; /*!< CID start indicator, polarity or ring */
529 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
530 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
531 int cidcwexpire; /*!< When to expire our muting for CID/CW */
532 unsigned char *cidspill;
533 int cidpos;
534 int cidlen;
535 int ringt;
536 int ringt_base;
537 int stripmsd;
538 int callwaitcas;
539 int callwaitrings;
540 int echocancel;
541 int echotraining;
542 char echorest[20];
543 int busycount;
544 int busy_tonelength;
545 int busy_quietlength;
546 int callprogress;
547 struct timeval flashtime; /*!< Last flash-hook time */
548 struct ast_dsp *dsp;
549 int cref; /*!< Call reference number */
550 DAHDI_DIAL_OPERATION dop;
551 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
552 char finaldial[64];
553 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
554 int amaflags; /*!< AMA Flags */
555 struct tdd_state *tdd; /*!< TDD flag */
556 char call_forward[AST_MAX_EXTENSION];
557 char mailbox[AST_MAX_EXTENSION];
558 char dialdest[256];
559 int onhooktime;
560 int msgstate;
561 int distinctivering; /*!< Which distinctivering to use */
562 int cidrings; /*!< Which ring to deliver CID on */
563 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
564 int fake_event;
565 int polarityonanswerdelay;
566 struct timeval polaritydelaytv;
567 int sendcalleridafter;
568 #ifdef HAVE_PRI
569 struct dahdi_pri *pri;
570 struct dahdi_pvt *bearer;
571 struct dahdi_pvt *realcall;
572 q931_call *call;
573 int prioffset;
574 int logicalspan;
575 #endif
576 int polarity;
577 int dsp_features;
578 char begindigit;
579 } *iflist = NULL, *ifend = NULL;
581 /*! \brief Channel configuration from chan_dahdi.conf .
582 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
583 * Generally there is a field here for every possible configuration item.
585 * The state of fields is saved along the parsing and whenever a 'channel'
586 * statement is reached, the current dahdi_chan_conf is used to configure the
587 * channel (struct dahdi_pvt)
589 * @seealso dahdi_chan_init for the default values.
591 struct dahdi_chan_conf {
592 struct dahdi_pvt chan;
593 #ifdef HAVE_PRI
594 struct dahdi_pri pri;
595 #endif
596 DAHDI_PARAMS timing;
598 char smdi_port[SMDI_MAX_FILENAME_LEN];
601 /** returns a new dahdi_chan_conf with default values (by-value) */
602 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
603 /* recall that if a field is not included here it is initialized
604 * to 0 or equivalent
606 struct dahdi_chan_conf conf = {
607 #ifdef HAVE_PRI
608 .pri = {
609 .nsf = PRI_NSF_NONE,
610 .switchtype = PRI_SWITCH_NI2,
611 .dialplan = PRI_NATIONAL_ISDN + 1,
612 .localdialplan = PRI_NATIONAL_ISDN + 1,
613 .nodetype = PRI_CPE,
615 .minunused = 2,
616 .idleext = "",
617 .idledial = "",
618 .internationalprefix = "",
619 .nationalprefix = "",
620 .localprefix = "",
621 .privateprefix = "",
622 .unknownprefix = "",
624 .resetinterval = 3600
626 #endif
627 .chan = {
628 .context = "default",
629 .cid_num = "",
630 .cid_name = "",
631 .mohinterpret = "default",
632 .mohsuggest = "",
633 .transfertobusy = 1,
635 .cid_signalling = CID_SIG_BELL,
636 .cid_start = CID_START_RING,
637 .dahditrcallerid = 0,
638 .use_callerid = 1,
639 .sig = -1,
640 .outsigmod = -1,
642 .tonezone = -1,
644 .echocancel = 1,
646 .busycount = 3,
648 .accountcode = "",
650 .mailbox = "",
653 .polarityonanswerdelay = 600,
655 .sendcalleridafter = DEFAULT_CIDRINGS
657 .timing = {
658 .prewinktime = -1,
659 .preflashtime = -1,
660 .winktime = -1,
661 .flashtime = -1,
662 .starttime = -1,
663 .rxwinktime = -1,
664 .rxflashtime = -1,
665 .debouncetime = -1
667 .smdi_port = "/dev/ttyS0",
670 return conf;
674 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
675 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
676 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
677 static int dahdi_sendtext(struct ast_channel *c, const char *text);
678 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
679 static int dahdi_hangup(struct ast_channel *ast);
680 static int dahdi_answer(struct ast_channel *ast);
681 static struct ast_frame *dahdi_read(struct ast_channel *ast);
682 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
683 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
684 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
685 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
686 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
687 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
689 static const struct ast_channel_tech dahdi_tech = {
690 .type = "DAHDI",
691 .description = tdesc,
692 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
693 .requester = dahdi_request,
694 .send_digit_begin = dahdi_digit_begin,
695 .send_digit_end = dahdi_digit_end,
696 .send_text = dahdi_sendtext,
697 .call = dahdi_call,
698 .hangup = dahdi_hangup,
699 .answer = dahdi_answer,
700 .read = dahdi_read,
701 .write = dahdi_write,
702 .bridge = dahdi_bridge,
703 .exception = dahdi_exception,
704 .indicate = dahdi_indicate,
705 .fixup = dahdi_fixup,
706 .setoption = dahdi_setoption,
707 .func_channel_read = dahdi_func_read,
710 #ifdef HAVE_PRI
711 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
712 #else
713 #define GET_CHANNEL(p) ((p)->channel)
714 #endif
716 struct dahdi_pvt *round_robin[32];
718 #ifdef HAVE_PRI
719 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
721 int res;
722 /* Grab the lock first */
723 do {
724 res = ast_mutex_trylock(&pri->lock);
725 if (res) {
726 DEADLOCK_AVOIDANCE(&pvt->lock);
728 } while (res);
729 /* Then break the poll */
730 pthread_kill(pri->master, SIGURG);
731 return 0;
733 #endif
735 #define NUM_CADENCE_MAX 25
736 static int num_cadence = 4;
737 static int user_has_defined_cadences = 0;
739 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
740 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
741 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
742 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
743 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
746 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
747 * is 1, the second pause is 2 and so on.
750 static int cidrings[NUM_CADENCE_MAX] = {
751 2, /*!< Right after first long ring */
752 4, /*!< Right after long part */
753 3, /*!< After third chirp */
754 2, /*!< Second spell */
757 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
758 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
760 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
761 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
763 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
765 int res;
766 if (p->subs[0].owner == ast)
767 res = 0;
768 else if (p->subs[1].owner == ast)
769 res = 1;
770 else if (p->subs[2].owner == ast)
771 res = 2;
772 else {
773 res = -1;
774 if (!nullok)
775 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
777 return res;
780 #ifdef HAVE_PRI
781 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
782 #else
783 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
784 #endif
786 #ifdef HAVE_PRI
787 if (pri)
788 ast_mutex_unlock(&pri->lock);
789 #endif
790 for (;;) {
791 if (p->subs[a].owner) {
792 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
793 DEADLOCK_AVOIDANCE(&p->lock);
794 } else {
795 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
796 ast_mutex_unlock(&p->subs[a].owner->lock);
797 break;
799 } else
800 break;
802 #ifdef HAVE_PRI
803 if (pri)
804 ast_mutex_lock(&pri->lock);
805 #endif
808 #ifdef HAVE_PRI
809 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
810 #else
811 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
812 #endif
814 /* We must unlock the PRI to avoid the possibility of a deadlock */
815 #ifdef HAVE_PRI
816 if (pri)
817 ast_mutex_unlock(&pri->lock);
818 #endif
819 for (;;) {
820 if (p->owner) {
821 if (ast_mutex_trylock(&p->owner->lock)) {
822 DEADLOCK_AVOIDANCE(&p->lock);
823 } else {
824 ast_queue_frame(p->owner, f);
825 ast_mutex_unlock(&p->owner->lock);
826 break;
828 } else
829 break;
831 #ifdef HAVE_PRI
832 if (pri)
833 ast_mutex_lock(&pri->lock);
834 #endif
837 static int restore_gains(struct dahdi_pvt *p);
839 static void swap_subs(struct dahdi_pvt *p, int a, int b)
841 int tchan;
842 int tinthreeway;
843 struct ast_channel *towner;
845 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
847 tchan = p->subs[a].chan;
848 towner = p->subs[a].owner;
849 tinthreeway = p->subs[a].inthreeway;
851 p->subs[a].chan = p->subs[b].chan;
852 p->subs[a].owner = p->subs[b].owner;
853 p->subs[a].inthreeway = p->subs[b].inthreeway;
855 p->subs[b].chan = tchan;
856 p->subs[b].owner = towner;
857 p->subs[b].inthreeway = tinthreeway;
859 if (p->subs[a].owner)
860 p->subs[a].owner->fds[0] = p->subs[a].dfd;
861 if (p->subs[b].owner)
862 p->subs[b].owner->fds[0] = p->subs[b].dfd;
863 wakeup_sub(p, a, NULL);
864 wakeup_sub(p, b, NULL);
867 static int dahdi_open(char *fn)
869 int fd;
870 int isnum;
871 int chan = 0;
872 int bs;
873 int x;
874 isnum = 1;
875 for (x = 0; x < strlen(fn); x++) {
876 if (!isdigit(fn[x])) {
877 isnum = 0;
878 break;
881 if (isnum) {
882 chan = atoi(fn);
883 if (chan < 1) {
884 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
885 return -1;
887 #ifdef HAVE_ZAPTEL
888 fn = "/dev/zap/channel";
889 #else
890 fn = "/dev/dahdi/channel";
891 #endif
893 fd = open(fn, O_RDWR | O_NONBLOCK);
894 if (fd < 0) {
895 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
896 return -1;
898 if (chan) {
899 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
900 x = errno;
901 close(fd);
902 errno = x;
903 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
904 return -1;
907 bs = READ_SIZE;
908 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
909 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
910 x = errno;
911 close(fd);
912 errno = x;
913 return -1;
915 return fd;
918 static void dahdi_close(int fd)
920 if (fd > 0)
921 close(fd);
924 static int dahdi_setlinear(int dfd, int linear)
926 int res;
927 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
928 if (res)
929 return res;
930 return 0;
934 static int alloc_sub(struct dahdi_pvt *p, int x)
936 DAHDI_BUFFERINFO bi;
937 int res;
938 if (p->subs[x].dfd < 0) {
939 #ifdef HAVE_ZAPTEL
940 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
941 #else
942 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
943 #endif
944 if (p->subs[x].dfd > -1) {
945 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
946 if (!res) {
947 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
948 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
949 bi.numbufs = numbufs;
950 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
951 if (res < 0) {
952 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
954 } else
955 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
956 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
957 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
958 dahdi_close(p->subs[x].dfd);
959 p->subs[x].dfd = -1;
960 return -1;
962 if (option_debug)
963 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
964 return 0;
965 } else
966 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
967 return -1;
969 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
970 return -1;
973 static int unalloc_sub(struct dahdi_pvt *p, int x)
975 if (!x) {
976 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
977 return -1;
979 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
980 if (p->subs[x].dfd > -1) {
981 dahdi_close(p->subs[x].dfd);
983 p->subs[x].dfd = -1;
984 p->subs[x].linear = 0;
985 p->subs[x].chan = 0;
986 p->subs[x].owner = NULL;
987 p->subs[x].inthreeway = 0;
988 p->polarity = POLARITY_IDLE;
989 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
990 return 0;
993 static int digit_to_dtmfindex(char digit)
995 if (isdigit(digit))
996 return DAHDI_TONE_DTMF_BASE + (digit - '0');
997 else if (digit >= 'A' && digit <= 'D')
998 return DAHDI_TONE_DTMF_A + (digit - 'A');
999 else if (digit >= 'a' && digit <= 'd')
1000 return DAHDI_TONE_DTMF_A + (digit - 'a');
1001 else if (digit == '*')
1002 return DAHDI_TONE_DTMF_s;
1003 else if (digit == '#')
1004 return DAHDI_TONE_DTMF_p;
1005 else
1006 return -1;
1009 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1011 struct dahdi_pvt *pvt;
1012 int index;
1013 int dtmf = -1;
1015 pvt = chan->tech_pvt;
1017 ast_mutex_lock(&pvt->lock);
1019 index = dahdi_get_index(chan, pvt, 0);
1021 if ((index != SUB_REAL) || !pvt->owner)
1022 goto out;
1024 #ifdef HAVE_PRI
1025 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1026 if (pvt->setup_ack) {
1027 if (!pri_grab(pvt, pvt->pri)) {
1028 pri_information(pvt->pri->pri, pvt->call, digit);
1029 pri_rel(pvt->pri);
1030 } else
1031 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1032 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1033 int res;
1034 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1035 res = strlen(pvt->dialdest);
1036 pvt->dialdest[res++] = digit;
1037 pvt->dialdest[res] = '\0';
1039 goto out;
1041 #endif
1042 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1043 goto out;
1045 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1046 int res;
1047 DAHDI_DIAL_OPERATION zo = {
1048 .op = DAHDI_DIAL_OP_APPEND,
1049 .dialstr[0] = 'T',
1050 .dialstr[1] = digit,
1051 .dialstr[2] = 0,
1053 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1054 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1055 else
1056 pvt->dialing = 1;
1057 } else {
1058 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1059 pvt->dialing = 1;
1060 pvt->begindigit = digit;
1063 out:
1064 ast_mutex_unlock(&pvt->lock);
1066 return 0;
1069 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1071 struct dahdi_pvt *pvt;
1072 int res = 0;
1073 int index;
1074 int x;
1076 pvt = chan->tech_pvt;
1078 ast_mutex_lock(&pvt->lock);
1080 index = dahdi_get_index(chan, pvt, 0);
1082 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1083 goto out;
1085 #ifdef HAVE_PRI
1086 /* This means that the digit was already sent via PRI signalling */
1087 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1088 goto out;
1089 #endif
1091 if (pvt->begindigit) {
1092 x = -1;
1093 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1094 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1095 pvt->dialing = 0;
1096 pvt->begindigit = 0;
1099 out:
1100 ast_mutex_unlock(&pvt->lock);
1102 return res;
1105 static char *events[] = {
1106 "No event",
1107 "On hook",
1108 "Ring/Answered",
1109 "Wink/Flash",
1110 "Alarm",
1111 "No more alarm",
1112 "HDLC Abort",
1113 "HDLC Overrun",
1114 "HDLC Bad FCS",
1115 "Dial Complete",
1116 "Ringer On",
1117 "Ringer Off",
1118 "Hook Transition Complete",
1119 "Bits Changed",
1120 "Pulse Start",
1121 "Timer Expired",
1122 "Timer Ping",
1123 "Polarity Reversal",
1124 "Ring Begin",
1127 static struct {
1128 int alarm;
1129 char *name;
1130 } alarms[] = {
1131 { DAHDI_ALARM_RED, "Red Alarm" },
1132 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1133 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1134 { DAHDI_ALARM_RECOVER, "Recovering" },
1135 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1136 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1137 { DAHDI_ALARM_NONE, "None" },
1140 static char *alarm2str(int alarm)
1142 int x;
1143 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1144 if (alarms[x].alarm & alarm)
1145 return alarms[x].name;
1147 return alarm ? "Unknown Alarm" : "No Alarm";
1150 static char *event2str(int event)
1152 static char buf[256];
1153 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1154 return events[event];
1155 sprintf(buf, "Event %d", event); /* safe */
1156 return buf;
1159 #ifdef HAVE_PRI
1160 static char *dialplan2str(int dialplan)
1162 if (dialplan == -1) {
1163 return("Dynamically set dialplan in ISDN");
1165 return (pri_plan2str(dialplan));
1167 #endif
1169 static char *dahdi_sig2str(int sig)
1171 static char buf[256];
1172 switch (sig) {
1173 case SIG_EM:
1174 return "E & M Immediate";
1175 case SIG_EMWINK:
1176 return "E & M Wink";
1177 case SIG_EM_E1:
1178 return "E & M E1";
1179 case SIG_FEATD:
1180 return "Feature Group D (DTMF)";
1181 case SIG_FEATDMF:
1182 return "Feature Group D (MF)";
1183 case SIG_FEATDMF_TA:
1184 return "Feature Groud D (MF) Tandem Access";
1185 case SIG_FEATB:
1186 return "Feature Group B (MF)";
1187 case SIG_E911:
1188 return "E911 (MF)";
1189 case SIG_FGC_CAMA:
1190 return "FGC/CAMA (Dialpulse)";
1191 case SIG_FGC_CAMAMF:
1192 return "FGC/CAMA (MF)";
1193 case SIG_FXSLS:
1194 return "FXS Loopstart";
1195 case SIG_FXSGS:
1196 return "FXS Groundstart";
1197 case SIG_FXSKS:
1198 return "FXS Kewlstart";
1199 case SIG_FXOLS:
1200 return "FXO Loopstart";
1201 case SIG_FXOGS:
1202 return "FXO Groundstart";
1203 case SIG_FXOKS:
1204 return "FXO Kewlstart";
1205 case SIG_PRI:
1206 return "ISDN PRI";
1207 case SIG_SF:
1208 return "SF (Tone) Immediate";
1209 case SIG_SFWINK:
1210 return "SF (Tone) Wink";
1211 case SIG_SF_FEATD:
1212 return "SF (Tone) with Feature Group D (DTMF)";
1213 case SIG_SF_FEATDMF:
1214 return "SF (Tone) with Feature Group D (MF)";
1215 case SIG_SF_FEATB:
1216 return "SF (Tone) with Feature Group B (MF)";
1217 case SIG_GR303FXOKS:
1218 return "GR-303 with FXOKS";
1219 case SIG_GR303FXSKS:
1220 return "GR-303 with FXSKS";
1221 case 0:
1222 return "Pseudo";
1223 default:
1224 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1225 return buf;
1229 #define sig2str dahdi_sig2str
1231 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1233 /* If the conference already exists, and we're already in it
1234 don't bother doing anything */
1235 DAHDI_CONFINFO zi;
1237 memset(&zi, 0, sizeof(zi));
1238 zi.chan = 0;
1240 if (slavechannel > 0) {
1241 /* If we have only one slave, do a digital mon */
1242 zi.confmode = DAHDI_CONF_DIGITALMON;
1243 zi.confno = slavechannel;
1244 } else {
1245 if (!index) {
1246 /* Real-side and pseudo-side both participate in conference */
1247 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1248 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1249 } else
1250 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1251 zi.confno = p->confno;
1253 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1254 return 0;
1255 if (c->dfd < 0)
1256 return 0;
1257 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1258 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1259 return -1;
1261 if (slavechannel < 1) {
1262 p->confno = zi.confno;
1264 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1265 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1266 return 0;
1269 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1271 /* If they're listening to our channel, they're ours */
1272 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1273 return 1;
1274 /* If they're a talker on our (allocated) conference, they're ours */
1275 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1276 return 1;
1277 return 0;
1280 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1282 DAHDI_CONFINFO zi;
1283 if (/* Can't delete if there's no dfd */
1284 (c->dfd < 0) ||
1285 /* Don't delete from the conference if it's not our conference */
1286 !isourconf(p, c)
1287 /* Don't delete if we don't think it's conferenced at all (implied) */
1288 ) return 0;
1289 memset(&zi, 0, sizeof(zi));
1290 zi.chan = 0;
1291 zi.confno = 0;
1292 zi.confmode = 0;
1293 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1294 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1295 return -1;
1297 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1298 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1299 return 0;
1302 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1304 int x;
1305 int useslavenative;
1306 struct dahdi_pvt *slave = NULL;
1307 /* Start out optimistic */
1308 useslavenative = 1;
1309 /* Update conference state in a stateless fashion */
1310 for (x = 0; x < 3; x++) {
1311 /* Any three-way calling makes slave native mode *definitely* out
1312 of the question */
1313 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1314 useslavenative = 0;
1316 /* If we don't have any 3-way calls, check to see if we have
1317 precisely one slave */
1318 if (useslavenative) {
1319 for (x = 0; x < MAX_SLAVES; x++) {
1320 if (p->slaves[x]) {
1321 if (slave) {
1322 /* Whoops already have a slave! No
1323 slave native and stop right away */
1324 slave = NULL;
1325 useslavenative = 0;
1326 break;
1327 } else {
1328 /* We have one slave so far */
1329 slave = p->slaves[x];
1334 /* If no slave, slave native definitely out */
1335 if (!slave)
1336 useslavenative = 0;
1337 else if (slave->law != p->law) {
1338 useslavenative = 0;
1339 slave = NULL;
1341 if (out)
1342 *out = slave;
1343 return useslavenative;
1346 static int reset_conf(struct dahdi_pvt *p)
1348 DAHDI_CONFINFO zi;
1349 memset(&zi, 0, sizeof(zi));
1350 p->confno = -1;
1351 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1352 if (p->subs[SUB_REAL].dfd > -1) {
1353 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1354 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1356 return 0;
1359 static int update_conf(struct dahdi_pvt *p)
1361 int needconf = 0;
1362 int x;
1363 int useslavenative;
1364 struct dahdi_pvt *slave = NULL;
1366 useslavenative = isslavenative(p, &slave);
1367 /* Start with the obvious, general stuff */
1368 for (x = 0; x < 3; x++) {
1369 /* Look for three way calls */
1370 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1371 conf_add(p, &p->subs[x], x, 0);
1372 needconf++;
1373 } else {
1374 conf_del(p, &p->subs[x], x);
1377 /* If we have a slave, add him to our conference now. or DAX
1378 if this is slave native */
1379 for (x = 0; x < MAX_SLAVES; x++) {
1380 if (p->slaves[x]) {
1381 if (useslavenative)
1382 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1383 else {
1384 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1385 needconf++;
1389 /* If we're supposed to be in there, do so now */
1390 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1391 if (useslavenative)
1392 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1393 else {
1394 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1395 needconf++;
1398 /* If we have a master, add ourselves to his conference */
1399 if (p->master) {
1400 if (isslavenative(p->master, NULL)) {
1401 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1402 } else {
1403 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1406 if (!needconf) {
1407 /* Nobody is left (or should be left) in our conference.
1408 Kill it. */
1409 p->confno = -1;
1411 if (option_debug)
1412 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1413 return 0;
1416 static void dahdi_enable_ec(struct dahdi_pvt *p)
1418 int x;
1419 int res;
1420 if (!p)
1421 return;
1422 if (p->echocanon) {
1423 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1424 return;
1426 if (p->digital) {
1427 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
1428 return;
1430 if (p->echocancel) {
1431 if (p->sig == SIG_PRI) {
1432 x = 1;
1433 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1434 if (res)
1435 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1437 x = p->echocancel;
1438 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1439 if (res)
1440 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1441 else {
1442 p->echocanon = 1;
1443 if (option_debug)
1444 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1446 } else if (option_debug)
1447 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1450 static void dahdi_train_ec(struct dahdi_pvt *p)
1452 int x;
1453 int res;
1454 if (p && p->echocancel && p->echotraining) {
1455 x = p->echotraining;
1456 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1457 if (res)
1458 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1459 else {
1460 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1462 } else
1463 ast_log(LOG_DEBUG, "No echo training requested\n");
1466 static void dahdi_disable_ec(struct dahdi_pvt *p)
1468 int x;
1469 int res;
1470 if (p->echocancel) {
1471 x = 0;
1472 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1473 if (res)
1474 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1475 else if (option_debug)
1476 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1478 p->echocanon = 0;
1481 static void fill_txgain(DAHDI_GAINS *g, float gain, int law)
1483 int j;
1484 int k;
1485 float linear_gain = pow(10.0, gain / 20.0);
1487 switch (law) {
1488 case DAHDI_LAW_ALAW:
1489 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1490 if (gain) {
1491 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1492 if (k > 32767) k = 32767;
1493 if (k < -32767) k = -32767;
1494 g->txgain[j] = AST_LIN2A(k);
1495 } else {
1496 g->txgain[j] = j;
1499 break;
1500 case DAHDI_LAW_MULAW:
1501 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1502 if (gain) {
1503 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1504 if (k > 32767) k = 32767;
1505 if (k < -32767) k = -32767;
1506 g->txgain[j] = AST_LIN2MU(k);
1507 } else {
1508 g->txgain[j] = j;
1511 break;
1515 static void fill_rxgain(DAHDI_GAINS *g, float gain, int law)
1517 int j;
1518 int k;
1519 float linear_gain = pow(10.0, gain / 20.0);
1521 switch (law) {
1522 case DAHDI_LAW_ALAW:
1523 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1524 if (gain) {
1525 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1526 if (k > 32767) k = 32767;
1527 if (k < -32767) k = -32767;
1528 g->rxgain[j] = AST_LIN2A(k);
1529 } else {
1530 g->rxgain[j] = j;
1533 break;
1534 case DAHDI_LAW_MULAW:
1535 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1536 if (gain) {
1537 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1538 if (k > 32767) k = 32767;
1539 if (k < -32767) k = -32767;
1540 g->rxgain[j] = AST_LIN2MU(k);
1541 } else {
1542 g->rxgain[j] = j;
1545 break;
1549 static int set_actual_txgain(int fd, int chan, float gain, int law)
1551 DAHDI_GAINS g;
1552 int res;
1554 memset(&g, 0, sizeof(g));
1555 g.chan = chan;
1556 res = ioctl(fd, DAHDI_GETGAINS, &g);
1557 if (res) {
1558 if (option_debug)
1559 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1560 return res;
1563 fill_txgain(&g, gain, law);
1565 return ioctl(fd, DAHDI_SETGAINS, &g);
1568 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1570 DAHDI_GAINS g;
1571 int res;
1573 memset(&g, 0, sizeof(g));
1574 g.chan = chan;
1575 res = ioctl(fd, DAHDI_GETGAINS, &g);
1576 if (res) {
1577 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1578 return res;
1581 fill_rxgain(&g, gain, law);
1583 return ioctl(fd, DAHDI_SETGAINS, &g);
1586 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1588 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1591 static int bump_gains(struct dahdi_pvt *p)
1593 int res;
1595 /* Bump receive gain by 5.0db */
1596 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1597 if (res) {
1598 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1599 return -1;
1602 return 0;
1605 static int restore_gains(struct dahdi_pvt *p)
1607 int res;
1609 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1610 if (res) {
1611 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1612 return -1;
1615 return 0;
1618 static inline int dahdi_set_hook(int fd, int hs)
1620 int x, res;
1622 x = hs;
1623 res = ioctl(fd, DAHDI_HOOK, &x);
1625 if (res < 0) {
1626 if (errno == EINPROGRESS)
1627 return 0;
1628 ast_log(LOG_WARNING, "dahdi hook failed: %s\n", strerror(errno));
1631 return res;
1634 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1636 int x, y, res;
1637 x = muted;
1638 if (p->sig == SIG_PRI) {
1639 y = 1;
1640 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1641 if (res)
1642 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1644 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1645 if (res < 0)
1646 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1647 return res;
1650 static int save_conference(struct dahdi_pvt *p)
1652 DAHDI_CONFINFO c;
1653 int res;
1654 if (p->saveconf.confmode) {
1655 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1656 return -1;
1658 p->saveconf.chan = 0;
1659 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1660 if (res) {
1661 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1662 p->saveconf.confmode = 0;
1663 return -1;
1665 c.chan = 0;
1666 c.confno = 0;
1667 c.confmode = DAHDI_CONF_NORMAL;
1668 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1669 if (res) {
1670 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1671 return -1;
1673 if (option_debug)
1674 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1675 return 0;
1678 static int restore_conference(struct dahdi_pvt *p)
1680 int res;
1681 if (p->saveconf.confmode) {
1682 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1683 p->saveconf.confmode = 0;
1684 if (res) {
1685 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1686 return -1;
1689 if (option_debug)
1690 ast_log(LOG_DEBUG, "Restored conferencing\n");
1691 return 0;
1694 static int send_callerid(struct dahdi_pvt *p);
1696 static int send_cwcidspill(struct dahdi_pvt *p)
1698 p->callwaitcas = 0;
1699 p->cidcwexpire = 0;
1700 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1701 return -1;
1702 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1703 /* Make sure we account for the end */
1704 p->cidlen += READ_SIZE * 4;
1705 p->cidpos = 0;
1706 send_callerid(p);
1707 if (option_verbose > 2)
1708 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1709 return 0;
1712 static int has_voicemail(struct dahdi_pvt *p)
1715 return ast_app_has_voicemail(p->mailbox, NULL);
1718 static int send_callerid(struct dahdi_pvt *p)
1720 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1721 int res;
1722 /* Take out of linear mode if necessary */
1723 if (p->subs[SUB_REAL].linear) {
1724 p->subs[SUB_REAL].linear = 0;
1725 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1727 while (p->cidpos < p->cidlen) {
1728 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1729 if (res < 0) {
1730 if (errno == EAGAIN)
1731 return 0;
1732 else {
1733 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1734 return -1;
1737 if (!res)
1738 return 0;
1739 p->cidpos += res;
1741 free(p->cidspill);
1742 p->cidspill = NULL;
1743 if (p->callwaitcas) {
1744 /* Wait for CID/CW to expire */
1745 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1746 } else
1747 restore_conference(p);
1748 return 0;
1751 static int dahdi_callwait(struct ast_channel *ast)
1753 struct dahdi_pvt *p = ast->tech_pvt;
1754 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1755 if (p->cidspill) {
1756 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1757 free(p->cidspill);
1759 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1760 return -1;
1761 save_conference(p);
1762 /* Silence */
1763 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1764 if (!p->callwaitrings && p->callwaitingcallerid) {
1765 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1766 p->callwaitcas = 1;
1767 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1768 } else {
1769 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1770 p->callwaitcas = 0;
1771 p->cidlen = 2400 + READ_SIZE * 4;
1773 p->cidpos = 0;
1774 send_callerid(p);
1776 return 0;
1779 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1781 struct dahdi_pvt *p = ast->tech_pvt;
1782 int x, res, index,mysig;
1783 char *c, *n, *l;
1784 #ifdef HAVE_PRI
1785 char *s = NULL;
1786 #endif
1787 char dest[256]; /* must be same length as p->dialdest */
1788 ast_mutex_lock(&p->lock);
1789 ast_copy_string(dest, rdest, sizeof(dest));
1790 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1791 if ((ast->_state == AST_STATE_BUSY)) {
1792 p->subs[SUB_REAL].needbusy = 1;
1793 ast_mutex_unlock(&p->lock);
1794 return 0;
1796 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1797 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1798 ast_mutex_unlock(&p->lock);
1799 return -1;
1801 p->dialednone = 0;
1802 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1804 /* Special pseudo -- automatically up */
1805 ast_setstate(ast, AST_STATE_UP);
1806 ast_mutex_unlock(&p->lock);
1807 return 0;
1809 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1810 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1811 if (res)
1812 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1813 p->outgoing = 1;
1815 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1817 mysig = p->sig;
1818 if (p->outsigmod > -1)
1819 mysig = p->outsigmod;
1821 switch (mysig) {
1822 case SIG_FXOLS:
1823 case SIG_FXOGS:
1824 case SIG_FXOKS:
1825 if (p->owner == ast) {
1826 /* Normal ring, on hook */
1828 /* Don't send audio while on hook, until the call is answered */
1829 p->dialing = 1;
1830 if (p->use_callerid) {
1831 /* Generate the Caller-ID spill if desired */
1832 if (p->cidspill) {
1833 ast_log(LOG_WARNING, "cidspill already exists??\n");
1834 free(p->cidspill);
1836 p->callwaitcas = 0;
1837 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1838 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1839 p->cidpos = 0;
1840 send_callerid(p);
1843 /* Choose proper cadence */
1844 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1845 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1846 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1847 p->cidrings = cidrings[p->distinctivering - 1];
1848 } else {
1849 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1850 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1851 p->cidrings = p->sendcalleridafter;
1854 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1855 c = strchr(dest, '/');
1856 if (c)
1857 c++;
1858 if (c && (strlen(c) < p->stripmsd)) {
1859 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1860 c = NULL;
1862 if (c) {
1863 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1864 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
1865 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
1866 } else {
1867 p->dop.dialstr[0] = '\0';
1869 x = DAHDI_RING;
1870 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
1871 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
1872 ast_mutex_unlock(&p->lock);
1873 return -1;
1875 p->dialing = 1;
1876 } else {
1877 /* Call waiting call */
1878 p->callwaitrings = 0;
1879 if (ast->cid.cid_num)
1880 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
1881 else
1882 p->callwait_num[0] = '\0';
1883 if (ast->cid.cid_name)
1884 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
1885 else
1886 p->callwait_name[0] = '\0';
1887 /* Call waiting tone instead */
1888 if (dahdi_callwait(ast)) {
1889 ast_mutex_unlock(&p->lock);
1890 return -1;
1892 /* Make ring-back */
1893 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
1894 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
1897 n = ast->cid.cid_name;
1898 l = ast->cid.cid_num;
1899 if (l)
1900 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
1901 else
1902 p->lastcid_num[0] = '\0';
1903 if (n)
1904 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
1905 else
1906 p->lastcid_name[0] = '\0';
1907 ast_setstate(ast, AST_STATE_RINGING);
1908 index = dahdi_get_index(ast, p, 0);
1909 if (index > -1) {
1910 p->subs[index].needringing = 1;
1912 break;
1913 case SIG_FXSLS:
1914 case SIG_FXSGS:
1915 case SIG_FXSKS:
1916 case SIG_EMWINK:
1917 case SIG_EM:
1918 case SIG_EM_E1:
1919 case SIG_FEATD:
1920 case SIG_FEATDMF:
1921 case SIG_E911:
1922 case SIG_FGC_CAMA:
1923 case SIG_FGC_CAMAMF:
1924 case SIG_FEATB:
1925 case SIG_SFWINK:
1926 case SIG_SF:
1927 case SIG_SF_FEATD:
1928 case SIG_SF_FEATDMF:
1929 case SIG_FEATDMF_TA:
1930 case SIG_SF_FEATB:
1931 c = strchr(dest, '/');
1932 if (c)
1933 c++;
1934 else
1935 c = "";
1936 if (strlen(c) < p->stripmsd) {
1937 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1938 ast_mutex_unlock(&p->lock);
1939 return -1;
1941 #ifdef HAVE_PRI
1942 /* Start the trunk, if not GR-303 */
1943 if (!p->pri) {
1944 #endif
1945 x = DAHDI_START;
1946 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
1947 if (res < 0) {
1948 if (errno != EINPROGRESS) {
1949 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
1950 ast_mutex_unlock(&p->lock);
1951 return -1;
1954 #ifdef HAVE_PRI
1956 #endif
1957 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
1958 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1960 c += p->stripmsd;
1962 switch (mysig) {
1963 case SIG_FEATD:
1964 l = ast->cid.cid_num;
1965 if (l)
1966 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
1967 else
1968 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
1969 break;
1970 case SIG_FEATDMF:
1971 l = ast->cid.cid_num;
1972 if (l)
1973 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
1974 else
1975 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
1976 break;
1977 case SIG_FEATDMF_TA:
1979 const char *cic, *ozz;
1981 /* If you have to go through a Tandem Access point you need to use this */
1982 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
1983 if (!ozz)
1984 ozz = defaultozz;
1985 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
1986 if (!cic)
1987 cic = defaultcic;
1988 if (!ozz || !cic) {
1989 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
1990 ast_mutex_unlock(&p->lock);
1991 return -1;
1993 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
1994 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
1995 p->whichwink = 0;
1997 break;
1998 case SIG_E911:
1999 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2000 break;
2001 case SIG_FGC_CAMA:
2002 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2003 break;
2004 case SIG_FGC_CAMAMF:
2005 case SIG_FEATB:
2006 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2007 break;
2008 default:
2009 if (p->pulse)
2010 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2011 else
2012 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2013 break;
2016 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2017 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2018 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2019 p->echorest[sizeof(p->echorest) - 1] = '\0';
2020 p->echobreak = 1;
2021 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2022 } else
2023 p->echobreak = 0;
2024 if (!res) {
2025 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2026 int saveerr = errno;
2028 x = DAHDI_ONHOOK;
2029 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2030 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2031 ast_mutex_unlock(&p->lock);
2032 return -1;
2034 } else
2035 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2036 p->dialing = 1;
2037 if (ast_strlen_zero(c))
2038 p->dialednone = 1;
2039 ast_setstate(ast, AST_STATE_DIALING);
2040 break;
2041 case 0:
2042 /* Special pseudo -- automatically up*/
2043 ast_setstate(ast, AST_STATE_UP);
2044 break;
2045 case SIG_PRI:
2046 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2047 p->dialdest[0] = '\0';
2048 break;
2049 default:
2050 ast_log(LOG_DEBUG, "not yet implemented\n");
2051 ast_mutex_unlock(&p->lock);
2052 return -1;
2054 #ifdef HAVE_PRI
2055 if (p->pri) {
2056 struct pri_sr *sr;
2057 #ifdef SUPPORT_USERUSER
2058 const char *useruser;
2059 #endif
2060 int pridialplan;
2061 int dp_strip;
2062 int prilocaldialplan;
2063 int ldp_strip;
2064 int exclusive;
2065 const char *rr_str;
2066 int redirect_reason;
2068 c = strchr(dest, '/');
2069 if (c)
2070 c++;
2071 else
2072 c = dest;
2074 l = NULL;
2075 n = NULL;
2077 if (!p->hidecallerid) {
2078 l = ast->cid.cid_num;
2079 if (!p->hidecalleridname) {
2080 n = ast->cid.cid_name;
2085 if (strlen(c) < p->stripmsd) {
2086 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2087 ast_mutex_unlock(&p->lock);
2088 return -1;
2090 if (mysig != SIG_FXSKS) {
2091 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2092 s = strchr(c + p->stripmsd, 'w');
2093 if (s) {
2094 if (strlen(s) > 1)
2095 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2096 else
2097 p->dop.dialstr[0] = '\0';
2098 *s = '\0';
2099 } else {
2100 p->dop.dialstr[0] = '\0';
2103 if (pri_grab(p, p->pri)) {
2104 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2105 ast_mutex_unlock(&p->lock);
2106 return -1;
2108 if (!(p->call = pri_new_call(p->pri->pri))) {
2109 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2110 pri_rel(p->pri);
2111 ast_mutex_unlock(&p->lock);
2112 return -1;
2114 if (!(sr = pri_sr_new())) {
2115 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2116 pri_destroycall(p->pri->pri, p->call);
2117 p->call = NULL;
2118 pri_rel(p->pri);
2119 ast_mutex_unlock(&p->lock);
2120 return -1;
2122 if (p->bearer || (mysig == SIG_FXSKS)) {
2123 if (p->bearer) {
2124 ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
2125 p->bearer->call = p->call;
2126 } else
2127 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2128 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2130 p->digital = IS_DIGITAL(ast->transfercapability);
2131 /* Add support for exclusive override */
2132 if (p->priexclusive)
2133 exclusive = 1;
2134 else {
2135 /* otherwise, traditional behavior */
2136 if (p->pri->nodetype == PRI_NETWORK)
2137 exclusive = 0;
2138 else
2139 exclusive = 1;
2142 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2143 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2144 (p->digital ? -1 :
2145 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2146 if (p->pri->facilityenable)
2147 pri_facility_enable(p->pri->pri);
2149 if (option_verbose > 2)
2150 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2151 dp_strip = 0;
2152 pridialplan = p->pri->dialplan - 1;
2153 if (pridialplan == -2) { /* compute dynamically */
2154 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2155 dp_strip = strlen(p->pri->internationalprefix);
2156 pridialplan = PRI_INTERNATIONAL_ISDN;
2157 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2158 dp_strip = strlen(p->pri->nationalprefix);
2159 pridialplan = PRI_NATIONAL_ISDN;
2160 } else {
2161 pridialplan = PRI_LOCAL_ISDN;
2164 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2166 ldp_strip = 0;
2167 prilocaldialplan = p->pri->localdialplan - 1;
2168 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2169 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2170 ldp_strip = strlen(p->pri->internationalprefix);
2171 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2172 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2173 ldp_strip = strlen(p->pri->nationalprefix);
2174 prilocaldialplan = PRI_NATIONAL_ISDN;
2175 } else {
2176 prilocaldialplan = PRI_LOCAL_ISDN;
2179 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2180 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2181 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2182 if (!strcasecmp(rr_str, "UNKNOWN"))
2183 redirect_reason = 0;
2184 else if (!strcasecmp(rr_str, "BUSY"))
2185 redirect_reason = 1;
2186 else if (!strcasecmp(rr_str, "NO_REPLY"))
2187 redirect_reason = 2;
2188 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2189 redirect_reason = 15;
2190 else
2191 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2192 } else
2193 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2194 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2196 #ifdef SUPPORT_USERUSER
2197 /* User-user info */
2198 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2200 if (useruser)
2201 pri_sr_set_useruser(sr, useruser);
2202 #endif
2204 if (pri_setup(p->pri->pri, p->call, sr)) {
2205 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2206 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2207 pri_rel(p->pri);
2208 ast_mutex_unlock(&p->lock);
2209 pri_sr_free(sr);
2210 return -1;
2212 pri_sr_free(sr);
2213 ast_setstate(ast, AST_STATE_DIALING);
2214 pri_rel(p->pri);
2216 #endif
2217 ast_mutex_unlock(&p->lock);
2218 return 0;
2221 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2223 struct dahdi_pvt *p = *pvt;
2224 /* Remove channel from the list */
2225 if (p->prev)
2226 p->prev->next = p->next;
2227 if (p->next)
2228 p->next->prev = p->prev;
2229 if (p->use_smdi)
2230 ast_smdi_interface_unref(p->smdi_iface);
2231 ast_mutex_destroy(&p->lock);
2232 free(p);
2233 *pvt = NULL;
2236 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2238 int owned = 0;
2239 int i = 0;
2241 if (!now) {
2242 if (cur->owner) {
2243 owned = 1;
2246 for (i = 0; i < 3; i++) {
2247 if (cur->subs[i].owner) {
2248 owned = 1;
2251 if (!owned) {
2252 if (prev) {
2253 prev->next = cur->next;
2254 if (prev->next)
2255 prev->next->prev = prev;
2256 else
2257 ifend = prev;
2258 } else {
2259 iflist = cur->next;
2260 if (iflist)
2261 iflist->prev = NULL;
2262 else
2263 ifend = NULL;
2265 if (cur->subs[SUB_REAL].dfd > -1) {
2266 dahdi_close(cur->subs[SUB_REAL].dfd);
2268 destroy_dahdi_pvt(&cur);
2270 } else {
2271 if (prev) {
2272 prev->next = cur->next;
2273 if (prev->next)
2274 prev->next->prev = prev;
2275 else
2276 ifend = prev;
2277 } else {
2278 iflist = cur->next;
2279 if (iflist)
2280 iflist->prev = NULL;
2281 else
2282 ifend = NULL;
2284 if (cur->subs[SUB_REAL].dfd > -1) {
2285 dahdi_close(cur->subs[SUB_REAL].dfd);
2287 destroy_dahdi_pvt(&cur);
2289 return 0;
2292 #ifdef HAVE_PRI
2293 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2295 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2297 static char *dahdi_send_keypad_facility_descrip =
2298 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2299 " IE over the current channel.\n";
2301 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2303 /* Data will be our digit string */
2304 struct dahdi_pvt *p;
2305 char *digits = (char *) data;
2307 if (ast_strlen_zero(digits)) {
2308 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2309 return -1;
2312 p = (struct dahdi_pvt *)chan->tech_pvt;
2314 if (!p) {
2315 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2316 return -1;
2319 ast_mutex_lock(&p->lock);
2321 if (!p->pri || !p->call) {
2322 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2323 ast_mutex_unlock(&p->lock);
2324 return -1;
2327 if (!pri_grab(p, p->pri)) {
2328 pri_keypad_facility(p->pri->pri, p->call, digits);
2329 pri_rel(p->pri);
2330 } else {
2331 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2332 ast_mutex_unlock(&p->lock);
2333 return -1;
2336 ast_mutex_unlock(&p->lock);
2338 return 0;
2341 static int pri_is_up(struct dahdi_pri *pri)
2343 int x;
2344 for (x = 0; x < NUM_DCHANS; x++) {
2345 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2346 return 1;
2348 return 0;
2351 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2353 bearer->owner = &inuse;
2354 bearer->realcall = crv;
2355 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2356 if (crv->subs[SUB_REAL].owner)
2357 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2358 crv->bearer = bearer;
2359 crv->call = bearer->call;
2360 crv->pri = pri;
2361 return 0;
2364 static char *pri_order(int level)
2366 switch (level) {
2367 case 0:
2368 return "Primary";
2369 case 1:
2370 return "Secondary";
2371 case 2:
2372 return "Tertiary";
2373 case 3:
2374 return "Quaternary";
2375 default:
2376 return "<Unknown>";
2380 /* Returns fd of the active dchan */
2381 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2383 int x = -1;
2385 for (x = 0; x < NUM_DCHANS; x++) {
2386 if ((pri->dchans[x] == pri->pri))
2387 break;
2390 return pri->fds[x];
2393 static int pri_find_dchan(struct dahdi_pri *pri)
2395 int oldslot = -1;
2396 struct pri *old;
2397 int newslot = -1;
2398 int x;
2399 old = pri->pri;
2400 for (x = 0; x < NUM_DCHANS; x++) {
2401 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2402 newslot = x;
2403 if (pri->dchans[x] == old) {
2404 oldslot = x;
2407 if (newslot < 0) {
2408 newslot = 0;
2409 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2410 pri->dchannels[newslot]);
2412 if (old && (oldslot != newslot))
2413 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2414 pri->dchannels[oldslot], pri->dchannels[newslot]);
2415 pri->pri = pri->dchans[newslot];
2416 return 0;
2418 #endif
2420 static int dahdi_hangup(struct ast_channel *ast)
2422 int res;
2423 int index,x, law;
2424 /*static int restore_gains(struct dahdi_pvt *p);*/
2425 struct dahdi_pvt *p = ast->tech_pvt;
2426 struct dahdi_pvt *tmp = NULL;
2427 struct dahdi_pvt *prev = NULL;
2428 DAHDI_PARAMS par;
2430 if (option_debug)
2431 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2432 if (!ast->tech_pvt) {
2433 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2434 return 0;
2437 ast_mutex_lock(&p->lock);
2439 index = dahdi_get_index(ast, p, 1);
2441 if (p->sig == SIG_PRI) {
2442 x = 1;
2443 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2446 x = 0;
2447 dahdi_confmute(p, 0);
2448 restore_gains(p);
2449 if (p->origcid_num) {
2450 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2451 free(p->origcid_num);
2452 p->origcid_num = NULL;
2454 if (p->origcid_name) {
2455 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2456 free(p->origcid_name);
2457 p->origcid_name = NULL;
2459 if (p->dsp)
2460 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2461 if (p->exten)
2462 p->exten[0] = '\0';
2464 if (option_debug)
2465 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2466 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2467 p->ignoredtmf = 0;
2469 if (index > -1) {
2470 /* Real channel, do some fixup */
2471 p->subs[index].owner = NULL;
2472 p->subs[index].needanswer = 0;
2473 p->subs[index].needflash = 0;
2474 p->subs[index].needringing = 0;
2475 p->subs[index].needbusy = 0;
2476 p->subs[index].needcongestion = 0;
2477 p->subs[index].linear = 0;
2478 p->subs[index].needcallerid = 0;
2479 p->polarity = POLARITY_IDLE;
2480 dahdi_setlinear(p->subs[index].dfd, 0);
2481 if (index == SUB_REAL) {
2482 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2483 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2484 if (p->subs[SUB_CALLWAIT].inthreeway) {
2485 /* We had flipped over to answer a callwait and now it's gone */
2486 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2487 /* Move to the call-wait, but un-own us until they flip back. */
2488 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2489 unalloc_sub(p, SUB_CALLWAIT);
2490 p->owner = NULL;
2491 } else {
2492 /* The three way hung up, but we still have a call wait */
2493 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2494 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2495 unalloc_sub(p, SUB_THREEWAY);
2496 if (p->subs[SUB_REAL].inthreeway) {
2497 /* This was part of a three way call. Immediately make way for
2498 another call */
2499 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2500 p->owner = p->subs[SUB_REAL].owner;
2501 } else {
2502 /* This call hasn't been completed yet... Set owner to NULL */
2503 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2504 p->owner = NULL;
2506 p->subs[SUB_REAL].inthreeway = 0;
2508 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2509 /* Move to the call-wait and switch back to them. */
2510 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2511 unalloc_sub(p, SUB_CALLWAIT);
2512 p->owner = p->subs[SUB_REAL].owner;
2513 if (p->owner->_state != AST_STATE_UP)
2514 p->subs[SUB_REAL].needanswer = 1;
2515 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2516 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2517 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2518 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2519 unalloc_sub(p, SUB_THREEWAY);
2520 if (p->subs[SUB_REAL].inthreeway) {
2521 /* This was part of a three way call. Immediately make way for
2522 another call */
2523 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2524 p->owner = p->subs[SUB_REAL].owner;
2525 } else {
2526 /* This call hasn't been completed yet... Set owner to NULL */
2527 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2528 p->owner = NULL;
2530 p->subs[SUB_REAL].inthreeway = 0;
2532 } else if (index == SUB_CALLWAIT) {
2533 /* Ditch the holding callwait call, and immediately make it availabe */
2534 if (p->subs[SUB_CALLWAIT].inthreeway) {
2535 /* This is actually part of a three way, placed on hold. Place the third part
2536 on music on hold now */
2537 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2538 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2539 S_OR(p->mohsuggest, NULL),
2540 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2542 p->subs[SUB_THREEWAY].inthreeway = 0;
2543 /* Make it the call wait now */
2544 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2545 unalloc_sub(p, SUB_THREEWAY);
2546 } else
2547 unalloc_sub(p, SUB_CALLWAIT);
2548 } else if (index == SUB_THREEWAY) {
2549 if (p->subs[SUB_CALLWAIT].inthreeway) {
2550 /* The other party of the three way call is currently in a call-wait state.
2551 Start music on hold for them, and take the main guy out of the third call */
2552 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2553 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2554 S_OR(p->mohsuggest, NULL),
2555 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2557 p->subs[SUB_CALLWAIT].inthreeway = 0;
2559 p->subs[SUB_REAL].inthreeway = 0;
2560 /* If this was part of a three way call index, let us make
2561 another three way call */
2562 unalloc_sub(p, SUB_THREEWAY);
2563 } else {
2564 /* This wasn't any sort of call, but how are we an index? */
2565 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2569 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2570 p->owner = NULL;
2571 p->ringt = 0;
2572 p->distinctivering = 0;
2573 p->confirmanswer = 0;
2574 p->cidrings = 1;
2575 p->outgoing = 0;
2576 p->digital = 0;
2577 p->faxhandled = 0;
2578 p->pulsedial = 0;
2579 p->onhooktime = time(NULL);
2580 #ifdef HAVE_PRI
2581 p->proceeding = 0;
2582 p->progress = 0;
2583 p->alerting = 0;
2584 p->setup_ack = 0;
2585 #endif
2586 if (p->dsp) {
2587 ast_dsp_free(p->dsp);
2588 p->dsp = NULL;
2591 law = DAHDI_LAW_DEFAULT;
2592 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2593 if (res < 0)
2594 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2595 /* Perform low level hangup if no owner left */
2596 #ifdef HAVE_PRI
2597 if (p->pri) {
2598 #ifdef SUPPORT_USERUSER
2599 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2600 #endif
2602 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2603 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2604 if (!pri_grab(p, p->pri)) {
2605 if (p->alreadyhungup) {
2606 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2608 #ifdef SUPPORT_USERUSER
2609 pri_call_set_useruser(p->call, useruser);
2610 #endif
2612 pri_hangup(p->pri->pri, p->call, -1);
2613 p->call = NULL;
2614 if (p->bearer)
2615 p->bearer->call = NULL;
2616 } else {
2617 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2618 int icause = ast->hangupcause ? ast->hangupcause : -1;
2619 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2621 #ifdef SUPPORT_USERUSER
2622 pri_call_set_useruser(p->call, useruser);
2623 #endif
2625 p->alreadyhungup = 1;
2626 if (p->bearer)
2627 p->bearer->alreadyhungup = 1;
2628 if (cause) {
2629 if (atoi(cause))
2630 icause = atoi(cause);
2632 pri_hangup(p->pri->pri, p->call, icause);
2634 if (res < 0)
2635 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2636 pri_rel(p->pri);
2637 } else {
2638 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2639 res = -1;
2641 } else {
2642 if (p->bearer)
2643 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2644 p->call = NULL;
2645 res = 0;
2648 #endif
2649 if (p->sig && (p->sig != SIG_PRI))
2650 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2651 if (res < 0) {
2652 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2654 switch (p->sig) {
2655 case SIG_FXOGS:
2656 case SIG_FXOLS:
2657 case SIG_FXOKS:
2658 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2659 if (!res) {
2660 #if 0
2661 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2662 #endif
2663 /* If they're off hook, try playing congestion */
2664 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2665 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2666 else
2667 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2669 break;
2670 case SIG_FXSGS:
2671 case SIG_FXSLS:
2672 case SIG_FXSKS:
2673 /* Make sure we're not made available for at least two seconds assuming
2674 we were actually used for an inbound or outbound call. */
2675 if (ast->_state != AST_STATE_RESERVED) {
2676 time(&p->guardtime);
2677 p->guardtime += 2;
2679 break;
2680 default:
2681 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2683 if (p->cidspill)
2684 free(p->cidspill);
2685 if (p->sig)
2686 dahdi_disable_ec(p);
2687 x = 0;
2688 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2689 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2690 p->didtdd = 0;
2691 p->cidspill = NULL;
2692 p->callwaitcas = 0;
2693 p->callwaiting = p->permcallwaiting;
2694 p->hidecallerid = p->permhidecallerid;
2695 p->dialing = 0;
2696 p->rdnis[0] = '\0';
2697 update_conf(p);
2698 reset_conf(p);
2699 /* Restore data mode */
2700 if (p->sig == SIG_PRI) {
2701 x = 0;
2702 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2704 #ifdef HAVE_PRI
2705 if (p->bearer) {
2706 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2707 /* Free up the bearer channel as well, and
2708 don't use its file descriptor anymore */
2709 update_conf(p->bearer);
2710 reset_conf(p->bearer);
2711 p->bearer->owner = NULL;
2712 p->bearer->realcall = NULL;
2713 p->bearer = NULL;
2714 p->subs[SUB_REAL].dfd = -1;
2715 p->pri = NULL;
2717 #endif
2718 restart_monitor();
2721 p->callwaitingrepeat = 0;
2722 p->cidcwexpire = 0;
2723 p->oprmode = 0;
2724 ast->tech_pvt = NULL;
2725 ast_mutex_unlock(&p->lock);
2726 ast_module_unref(ast_module_info->self);
2727 if (option_verbose > 2)
2728 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2730 ast_mutex_lock(&iflock);
2731 tmp = iflist;
2732 prev = NULL;
2733 if (p->destroy) {
2734 while (tmp) {
2735 if (tmp == p) {
2736 destroy_channel(prev, tmp, 0);
2737 break;
2738 } else {
2739 prev = tmp;
2740 tmp = tmp->next;
2744 ast_mutex_unlock(&iflock);
2745 return 0;
2748 static int dahdi_answer(struct ast_channel *ast)
2750 struct dahdi_pvt *p = ast->tech_pvt;
2751 int res = 0;
2752 int index;
2753 int oldstate = ast->_state;
2754 ast_setstate(ast, AST_STATE_UP);
2755 ast_mutex_lock(&p->lock);
2756 index = dahdi_get_index(ast, p, 0);
2757 if (index < 0)
2758 index = SUB_REAL;
2759 /* nothing to do if a radio channel */
2760 if ((p->radio || (p->oprmode < 0))) {
2761 ast_mutex_unlock(&p->lock);
2762 return 0;
2764 switch (p->sig) {
2765 case SIG_FXSLS:
2766 case SIG_FXSGS:
2767 case SIG_FXSKS:
2768 p->ringt = 0;
2769 /* Fall through */
2770 case SIG_EM:
2771 case SIG_EM_E1:
2772 case SIG_EMWINK:
2773 case SIG_FEATD:
2774 case SIG_FEATDMF:
2775 case SIG_FEATDMF_TA:
2776 case SIG_E911:
2777 case SIG_FGC_CAMA:
2778 case SIG_FGC_CAMAMF:
2779 case SIG_FEATB:
2780 case SIG_SF:
2781 case SIG_SFWINK:
2782 case SIG_SF_FEATD:
2783 case SIG_SF_FEATDMF:
2784 case SIG_SF_FEATB:
2785 case SIG_FXOLS:
2786 case SIG_FXOGS:
2787 case SIG_FXOKS:
2788 /* Pick up the line */
2789 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
2790 if (p->hanguponpolarityswitch) {
2791 gettimeofday(&p->polaritydelaytv, NULL);
2793 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2794 tone_zone_play_tone(p->subs[index].dfd, -1);
2795 p->dialing = 0;
2796 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
2797 if (oldstate == AST_STATE_RINGING) {
2798 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
2799 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
2800 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2801 p->owner = p->subs[SUB_REAL].owner;
2804 if (p->sig & __DAHDI_SIG_FXS) {
2805 dahdi_enable_ec(p);
2806 dahdi_train_ec(p);
2808 break;
2809 #ifdef HAVE_PRI
2810 case SIG_PRI:
2811 /* Send a pri acknowledge */
2812 if (!pri_grab(p, p->pri)) {
2813 p->proceeding = 1;
2814 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2815 pri_rel(p->pri);
2816 } else {
2817 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2818 res = -1;
2820 break;
2821 #endif
2822 case 0:
2823 ast_mutex_unlock(&p->lock);
2824 return 0;
2825 default:
2826 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
2827 res = -1;
2829 ast_mutex_unlock(&p->lock);
2830 return res;
2833 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
2835 char *cp;
2836 signed char *scp;
2837 int x;
2838 int index;
2839 struct dahdi_pvt *p = chan->tech_pvt, *pp;
2840 struct oprmode *oprmode;
2843 /* all supported options require data */
2844 if (!data || (datalen < 1)) {
2845 errno = EINVAL;
2846 return -1;
2849 switch (option) {
2850 case AST_OPTION_TXGAIN:
2851 scp = (signed char *) data;
2852 index = dahdi_get_index(chan, p, 0);
2853 if (index < 0) {
2854 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
2855 return -1;
2857 if (option_debug)
2858 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
2859 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
2860 case AST_OPTION_RXGAIN:
2861 scp = (signed char *) data;
2862 index = dahdi_get_index(chan, p, 0);
2863 if (index < 0) {
2864 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
2865 return -1;
2867 if (option_debug)
2868 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
2869 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
2870 case AST_OPTION_TONE_VERIFY:
2871 if (!p->dsp)
2872 break;
2873 cp = (char *) data;
2874 switch (*cp) {
2875 case 1:
2876 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
2877 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
2878 break;
2879 case 2:
2880 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
2881 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
2882 break;
2883 default:
2884 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
2885 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
2886 break;
2888 break;
2889 case AST_OPTION_TDD:
2890 /* turn on or off TDD */
2891 cp = (char *) data;
2892 p->mate = 0;
2893 if (!*cp) { /* turn it off */
2894 if (option_debug)
2895 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
2896 if (p->tdd)
2897 tdd_free(p->tdd);
2898 p->tdd = 0;
2899 break;
2901 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
2902 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
2903 dahdi_disable_ec(p);
2904 /* otherwise, turn it on */
2905 if (!p->didtdd) { /* if havent done it yet */
2906 unsigned char mybuf[41000], *buf;
2907 int size, res, fd, len;
2908 struct pollfd fds[1];
2910 buf = mybuf;
2911 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
2912 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
2913 len = 40000;
2914 index = dahdi_get_index(chan, p, 0);
2915 if (index < 0) {
2916 ast_log(LOG_WARNING, "No index in TDD?\n");
2917 return -1;
2919 fd = p->subs[index].dfd;
2920 while (len) {
2921 if (ast_check_hangup(chan))
2922 return -1;
2923 size = len;
2924 if (size > READ_SIZE)
2925 size = READ_SIZE;
2926 fds[0].fd = fd;
2927 fds[0].events = POLLPRI | POLLOUT;
2928 fds[0].revents = 0;
2929 res = poll(fds, 1, -1);
2930 if (!res) {
2931 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
2932 continue;
2934 /* if got exception */
2935 if (fds[0].revents & POLLPRI)
2936 return -1;
2937 if (!(fds[0].revents & POLLOUT)) {
2938 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
2939 continue;
2941 res = write(fd, buf, size);
2942 if (res != size) {
2943 if (res == -1) return -1;
2944 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
2945 break;
2947 len -= size;
2948 buf += size;
2950 p->didtdd = 1; /* set to have done it now */
2952 if (*cp == 2) { /* Mate mode */
2953 if (p->tdd)
2954 tdd_free(p->tdd);
2955 p->tdd = 0;
2956 p->mate = 1;
2957 break;
2959 if (!p->tdd) { /* if we dont have one yet */
2960 p->tdd = tdd_new(); /* allocate one */
2962 break;
2963 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
2964 if (!p->dsp)
2965 break;
2966 cp = (char *) data;
2967 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
2968 *cp ? "ON" : "OFF", (int) *cp, chan->name);
2969 p->dtmfrelax = 0;
2970 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
2971 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
2972 break;
2973 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
2974 cp = (char *) data;
2975 if (!*cp) {
2976 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
2977 x = 0;
2978 dahdi_disable_ec(p);
2979 } else {
2980 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
2981 x = 1;
2983 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
2984 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
2985 break;
2986 case AST_OPTION_OPRMODE: /* Operator services mode */
2987 oprmode = (struct oprmode *) data;
2988 pp = oprmode->peer->tech_pvt;
2989 p->oprmode = pp->oprmode = 0;
2990 /* setup peers */
2991 p->oprpeer = pp;
2992 pp->oprpeer = p;
2993 /* setup modes, if any */
2994 if (oprmode->mode)
2996 pp->oprmode = oprmode->mode;
2997 p->oprmode = -oprmode->mode;
2999 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
3000 oprmode->mode, chan->name,oprmode->peer->name);;
3001 break;
3002 case AST_OPTION_ECHOCAN:
3003 cp = (char *) data;
3004 if (*cp) {
3005 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3006 dahdi_enable_ec(p);
3007 } else {
3008 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3009 dahdi_disable_ec(p);
3011 break;
3013 errno = 0;
3015 return 0;
3018 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3020 struct dahdi_pvt *p = chan->tech_pvt;
3022 if (!strcasecmp(data, "rxgain")) {
3023 ast_mutex_lock(&p->lock);
3024 snprintf(buf, len, "%f", p->rxgain);
3025 ast_mutex_unlock(&p->lock);
3026 } else if (!strcasecmp(data, "txgain")) {
3027 ast_mutex_lock(&p->lock);
3028 snprintf(buf, len, "%f", p->txgain);
3029 ast_mutex_unlock(&p->lock);
3030 } else {
3031 ast_copy_string(buf, "", len);
3033 return 0;
3037 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3039 /* Unlink a specific slave or all slaves/masters from a given master */
3040 int x;
3041 int hasslaves;
3042 if (!master)
3043 return;
3044 if (needlock) {
3045 ast_mutex_lock(&master->lock);
3046 if (slave) {
3047 while (ast_mutex_trylock(&slave->lock)) {
3048 DEADLOCK_AVOIDANCE(&master->lock);
3052 hasslaves = 0;
3053 for (x = 0; x < MAX_SLAVES; x++) {
3054 if (master->slaves[x]) {
3055 if (!slave || (master->slaves[x] == slave)) {
3056 /* Take slave out of the conference */
3057 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3058 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3059 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3060 master->slaves[x]->master = NULL;
3061 master->slaves[x] = NULL;
3062 } else
3063 hasslaves = 1;
3065 if (!hasslaves)
3066 master->inconference = 0;
3068 if (!slave) {
3069 if (master->master) {
3070 /* Take master out of the conference */
3071 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3072 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3073 hasslaves = 0;
3074 for (x = 0; x < MAX_SLAVES; x++) {
3075 if (master->master->slaves[x] == master)
3076 master->master->slaves[x] = NULL;
3077 else if (master->master->slaves[x])
3078 hasslaves = 1;
3080 if (!hasslaves)
3081 master->master->inconference = 0;
3083 master->master = NULL;
3085 update_conf(master);
3086 if (needlock) {
3087 if (slave)
3088 ast_mutex_unlock(&slave->lock);
3089 ast_mutex_unlock(&master->lock);
3093 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3094 int x;
3095 if (!slave || !master) {
3096 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3097 return;
3099 for (x = 0; x < MAX_SLAVES; x++) {
3100 if (!master->slaves[x]) {
3101 master->slaves[x] = slave;
3102 break;
3105 if (x >= MAX_SLAVES) {
3106 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3107 master->slaves[MAX_SLAVES - 1] = slave;
3109 if (slave->master)
3110 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3111 slave->master = master;
3113 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3116 static void disable_dtmf_detect(struct dahdi_pvt *p)
3118 #ifdef DAHDI_TONEDETECT
3119 int val;
3120 #endif
3122 p->ignoredtmf = 1;
3124 #ifdef DAHDI_TONEDETECT
3125 val = 0;
3126 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3127 #endif
3128 if (!p->hardwaredtmf && p->dsp) {
3129 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3130 ast_dsp_set_features(p->dsp, p->dsp_features);
3134 static void enable_dtmf_detect(struct dahdi_pvt *p)
3136 #ifdef DAHDI_TONEDETECT
3137 int val;
3138 #endif
3140 if (p->channel == CHAN_PSEUDO)
3141 return;
3143 p->ignoredtmf = 0;
3145 #ifdef DAHDI_TONEDETECT
3146 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3147 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3148 #endif
3149 if (!p->hardwaredtmf && p->dsp) {
3150 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3151 ast_dsp_set_features(p->dsp, p->dsp_features);
3155 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)
3157 struct ast_channel *who;
3158 struct dahdi_pvt *p0, *p1, *op0, *op1;
3159 struct dahdi_pvt *master = NULL, *slave = NULL;
3160 struct ast_frame *f;
3161 int inconf = 0;
3162 int nothingok = 1;
3163 int ofd0, ofd1;
3164 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3165 int os0 = -1, os1 = -1;
3166 int priority = 0;
3167 struct ast_channel *oc0, *oc1;
3168 enum ast_bridge_result res;
3170 #ifdef PRI_2BCT
3171 int triedtopribridge = 0;
3172 q931_call *q931c0 = NULL, *q931c1 = NULL;
3173 #endif
3175 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3176 There is code below to handle it properly until DTMF is actually seen,
3177 but due to currently unresolved issues it's ignored...
3180 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3181 return AST_BRIDGE_FAILED_NOWARN;
3183 ast_mutex_lock(&c0->lock);
3184 while (ast_mutex_trylock(&c1->lock)) {
3185 DEADLOCK_AVOIDANCE(&c0->lock);
3188 p0 = c0->tech_pvt;
3189 p1 = c1->tech_pvt;
3190 /* cant do pseudo-channels here */
3191 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3192 ast_mutex_unlock(&c0->lock);
3193 ast_mutex_unlock(&c1->lock);
3194 return AST_BRIDGE_FAILED_NOWARN;
3197 oi0 = dahdi_get_index(c0, p0, 0);
3198 oi1 = dahdi_get_index(c1, p1, 0);
3199 if ((oi0 < 0) || (oi1 < 0)) {
3200 ast_mutex_unlock(&c0->lock);
3201 ast_mutex_unlock(&c1->lock);
3202 return AST_BRIDGE_FAILED;
3205 op0 = p0 = c0->tech_pvt;
3206 op1 = p1 = c1->tech_pvt;
3207 ofd0 = c0->fds[0];
3208 ofd1 = c1->fds[0];
3209 oc0 = p0->owner;
3210 oc1 = p1->owner;
3212 if (ast_mutex_trylock(&p0->lock)) {
3213 /* Don't block, due to potential for deadlock */
3214 ast_mutex_unlock(&c0->lock);
3215 ast_mutex_unlock(&c1->lock);
3216 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3217 return AST_BRIDGE_RETRY;
3219 if (ast_mutex_trylock(&p1->lock)) {
3220 /* Don't block, due to potential for deadlock */
3221 ast_mutex_unlock(&p0->lock);
3222 ast_mutex_unlock(&c0->lock);
3223 ast_mutex_unlock(&c1->lock);
3224 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3225 return AST_BRIDGE_RETRY;
3228 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3229 if (p0->owner && p1->owner) {
3230 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3231 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3232 master = p0;
3233 slave = p1;
3234 inconf = 1;
3235 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3236 master = p1;
3237 slave = p0;
3238 inconf = 1;
3239 } else {
3240 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3241 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3242 p0->channel,
3243 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3244 p0->subs[SUB_REAL].inthreeway, p0->channel,
3245 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3246 p1->subs[SUB_REAL].inthreeway);
3248 nothingok = 0;
3250 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3251 if (p1->subs[SUB_THREEWAY].inthreeway) {
3252 master = p1;
3253 slave = p0;
3254 nothingok = 0;
3256 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3257 if (p0->subs[SUB_THREEWAY].inthreeway) {
3258 master = p0;
3259 slave = p1;
3260 nothingok = 0;
3262 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3263 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3264 don't put us in anything */
3265 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3266 master = p1;
3267 slave = p0;
3268 nothingok = 0;
3270 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3271 /* Same as previous */
3272 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3273 master = p0;
3274 slave = p1;
3275 nothingok = 0;
3278 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3279 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3280 if (master && slave) {
3281 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3282 in an active threeway call with a channel that is ringing, we should
3283 indicate ringing. */
3284 if ((oi1 == SUB_THREEWAY) &&
3285 p1->subs[SUB_THREEWAY].inthreeway &&
3286 p1->subs[SUB_REAL].owner &&
3287 p1->subs[SUB_REAL].inthreeway &&
3288 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3289 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3290 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3291 os1 = p1->subs[SUB_REAL].owner->_state;
3292 } else {
3293 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3294 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3296 if ((oi0 == SUB_THREEWAY) &&
3297 p0->subs[SUB_THREEWAY].inthreeway &&
3298 p0->subs[SUB_REAL].owner &&
3299 p0->subs[SUB_REAL].inthreeway &&
3300 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3301 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3302 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3303 os0 = p0->subs[SUB_REAL].owner->_state;
3304 } else {
3305 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3306 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3308 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3309 if (!p0->echocanbridged || !p1->echocanbridged) {
3310 /* Disable echo cancellation if appropriate */
3311 dahdi_disable_ec(p0);
3312 dahdi_disable_ec(p1);
3315 dahdi_link(slave, master);
3316 master->inconference = inconf;
3317 } else if (!nothingok)
3318 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3320 update_conf(p0);
3321 update_conf(p1);
3322 t0 = p0->subs[SUB_REAL].inthreeway;
3323 t1 = p1->subs[SUB_REAL].inthreeway;
3325 ast_mutex_unlock(&p0->lock);
3326 ast_mutex_unlock(&p1->lock);
3328 ast_mutex_unlock(&c0->lock);
3329 ast_mutex_unlock(&c1->lock);
3331 /* Native bridge failed */
3332 if ((!master || !slave) && !nothingok) {
3333 dahdi_enable_ec(p0);
3334 dahdi_enable_ec(p1);
3335 return AST_BRIDGE_FAILED;
3338 if (option_verbose > 2)
3339 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3341 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3342 disable_dtmf_detect(op0);
3344 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3345 disable_dtmf_detect(op1);
3347 for (;;) {
3348 struct ast_channel *c0_priority[2] = {c0, c1};
3349 struct ast_channel *c1_priority[2] = {c1, c0};
3351 /* Here's our main loop... Start by locking things, looking for private parts,
3352 and then balking if anything is wrong */
3353 ast_mutex_lock(&c0->lock);
3354 while (ast_mutex_trylock(&c1->lock)) {
3355 DEADLOCK_AVOIDANCE(&c0->lock);
3358 p0 = c0->tech_pvt;
3359 p1 = c1->tech_pvt;
3361 if (op0 == p0)
3362 i0 = dahdi_get_index(c0, p0, 1);
3363 if (op1 == p1)
3364 i1 = dahdi_get_index(c1, p1, 1);
3365 ast_mutex_unlock(&c0->lock);
3366 ast_mutex_unlock(&c1->lock);
3368 if (!timeoutms ||
3369 (op0 != p0) ||
3370 (op1 != p1) ||
3371 (ofd0 != c0->fds[0]) ||
3372 (ofd1 != c1->fds[0]) ||
3373 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3374 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3375 (oc0 != p0->owner) ||
3376 (oc1 != p1->owner) ||
3377 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3378 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3379 (oi0 != i0) ||
3380 (oi1 != i1)) {
3381 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3382 op0->channel, oi0, op1->channel, oi1);
3383 res = AST_BRIDGE_RETRY;
3384 goto return_from_bridge;
3387 #ifdef PRI_2BCT
3388 q931c0 = p0->call;
3389 q931c1 = p1->call;
3390 if (p0->transfer && p1->transfer
3391 && q931c0 && q931c1
3392 && !triedtopribridge) {
3393 pri_channel_bridge(q931c0, q931c1);
3394 triedtopribridge = 1;
3396 #endif
3398 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3399 if (!who) {
3400 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3401 continue;
3403 f = ast_read(who);
3404 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3405 *fo = f;
3406 *rc = who;
3407 res = AST_BRIDGE_COMPLETE;
3408 goto return_from_bridge;
3410 if (f->frametype == AST_FRAME_DTMF) {
3411 if ((who == c0) && p0->pulsedial) {
3412 ast_write(c1, f);
3413 } else if ((who == c1) && p1->pulsedial) {
3414 ast_write(c0, f);
3415 } else {
3416 *fo = f;
3417 *rc = who;
3418 res = AST_BRIDGE_COMPLETE;
3419 goto return_from_bridge;
3422 ast_frfree(f);
3424 /* Swap who gets priority */
3425 priority = !priority;
3428 return_from_bridge:
3429 if (op0 == p0)
3430 dahdi_enable_ec(p0);
3432 if (op1 == p1)
3433 dahdi_enable_ec(p1);
3435 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3436 enable_dtmf_detect(op0);
3438 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3439 enable_dtmf_detect(op1);
3441 dahdi_unlink(slave, master, 1);
3443 return res;
3446 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3448 struct dahdi_pvt *p = newchan->tech_pvt;
3449 int x;
3450 ast_mutex_lock(&p->lock);
3451 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3452 if (p->owner == oldchan) {
3453 p->owner = newchan;
3455 for (x = 0; x < 3; x++)
3456 if (p->subs[x].owner == oldchan) {
3457 if (!x)
3458 dahdi_unlink(NULL, p, 0);
3459 p->subs[x].owner = newchan;
3461 if (newchan->_state == AST_STATE_RINGING)
3462 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3463 update_conf(p);
3464 ast_mutex_unlock(&p->lock);
3465 return 0;
3468 static int dahdi_ring_phone(struct dahdi_pvt *p)
3470 int x;
3471 int res;
3472 /* Make sure our transmit state is on hook */
3473 x = 0;
3474 x = DAHDI_ONHOOK;
3475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3476 do {
3477 x = DAHDI_RING;
3478 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3479 if (res) {
3480 switch (errno) {
3481 case EBUSY:
3482 case EINTR:
3483 /* Wait just in case */
3484 usleep(10000);
3485 continue;
3486 case EINPROGRESS:
3487 res = 0;
3488 break;
3489 default:
3490 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3491 res = 0;
3494 } while (res);
3495 return res;
3498 static void *ss_thread(void *data);
3500 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3502 static int attempt_transfer(struct dahdi_pvt *p)
3504 /* In order to transfer, we need at least one of the channels to
3505 actually be in a call bridge. We can't conference two applications
3506 together (but then, why would we want to?) */
3507 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3508 /* The three-way person we're about to transfer to could still be in MOH, so
3509 stop if now if appropriate */
3510 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3511 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3512 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3513 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3515 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3516 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3518 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3519 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3520 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3521 return -1;
3523 /* Orphan the channel after releasing the lock */
3524 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3525 unalloc_sub(p, SUB_THREEWAY);
3526 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3527 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3528 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3529 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3531 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3532 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3534 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3535 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3536 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3537 return -1;
3539 /* Three-way is now the REAL */
3540 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3541 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3542 unalloc_sub(p, SUB_THREEWAY);
3543 /* Tell the caller not to hangup */
3544 return 1;
3545 } else {
3546 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3547 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3548 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3549 return -1;
3551 return 0;
3554 static int check_for_conference(struct dahdi_pvt *p)
3556 DAHDI_CONFINFO ci;
3557 /* Fine if we already have a master, etc */
3558 if (p->master || (p->confno > -1))
3559 return 0;
3560 memset(&ci, 0, sizeof(ci));
3561 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3562 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3563 return 0;
3565 /* If we have no master and don't have a confno, then
3566 if we're in a conference, it's probably a MeetMe room or
3567 some such, so don't let us 3-way out! */
3568 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3569 if (option_verbose > 2)
3570 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3571 return 1;
3573 return 0;
3576 static int get_alarms(struct dahdi_pvt *p)
3578 int res;
3579 DAHDI_SPANINFO zi;
3580 memset(&zi, 0, sizeof(zi));
3581 zi.spanno = p->span;
3582 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi);
3583 if (res < 0) {
3584 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3585 return 0;
3587 return zi.alarms;
3590 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3592 struct dahdi_pvt *p = ast->tech_pvt;
3593 struct ast_frame *f = *dest;
3595 if (option_debug)
3596 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3598 if (p->confirmanswer) {
3599 if (option_debug)
3600 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3601 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3602 of a DTMF digit */
3603 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3604 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3605 *dest = &p->subs[index].f;
3606 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3607 p->confirmanswer = 0;
3608 } else if (p->callwaitcas) {
3609 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3610 if (option_debug)
3611 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3612 if (p->cidspill)
3613 free(p->cidspill);
3614 send_cwcidspill(p);
3616 if ((f->subclass != 'm') && (f->subclass != 'u'))
3617 p->callwaitcas = 0;
3618 p->subs[index].f.frametype = AST_FRAME_NULL;
3619 p->subs[index].f.subclass = 0;
3620 *dest = &p->subs[index].f;
3621 } else if (f->subclass == 'f') {
3622 /* Fax tone -- Handle and return NULL */
3623 if ((p->callprogress & 0x6) && !p->faxhandled) {
3624 p->faxhandled++;
3625 if (strcmp(ast->exten, "fax")) {
3626 const char *target_context = S_OR(ast->macrocontext, ast->context);
3628 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3629 if (option_verbose > 2)
3630 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3631 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3632 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3633 if (ast_async_goto(ast, target_context, "fax", 1))
3634 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3635 } else
3636 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3637 } else if (option_debug)
3638 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3639 } else if (option_debug)
3640 ast_log(LOG_DEBUG, "Fax already handled\n");
3641 dahdi_confmute(p, 0);
3642 p->subs[index].f.frametype = AST_FRAME_NULL;
3643 p->subs[index].f.subclass = 0;
3644 *dest = &p->subs[index].f;
3645 } else if (f->subclass == 'm') {
3646 /* Confmute request */
3647 dahdi_confmute(p, 1);
3648 p->subs[index].f.frametype = AST_FRAME_NULL;
3649 p->subs[index].f.subclass = 0;
3650 *dest = &p->subs[index].f;
3651 } else if (f->subclass == 'u') {
3652 /* Unmute */
3653 dahdi_confmute(p, 0);
3654 p->subs[index].f.frametype = AST_FRAME_NULL;
3655 p->subs[index].f.subclass = 0;
3656 *dest = &p->subs[index].f;
3657 } else
3658 dahdi_confmute(p, 0);
3661 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
3663 int res, x;
3664 int index, mysig;
3665 char *c;
3666 struct dahdi_pvt *p = ast->tech_pvt;
3667 pthread_t threadid;
3668 pthread_attr_t attr;
3669 struct ast_channel *chan;
3670 struct ast_frame *f;
3672 index = dahdi_get_index(ast, p, 0);
3673 mysig = p->sig;
3674 if (p->outsigmod > -1)
3675 mysig = p->outsigmod;
3676 p->subs[index].f.frametype = AST_FRAME_NULL;
3677 p->subs[index].f.subclass = 0;
3678 p->subs[index].f.datalen = 0;
3679 p->subs[index].f.samples = 0;
3680 p->subs[index].f.mallocd = 0;
3681 p->subs[index].f.offset = 0;
3682 p->subs[index].f.src = "dahdi_handle_event";
3683 p->subs[index].f.data = NULL;
3684 f = &p->subs[index].f;
3686 if (index < 0)
3687 return &p->subs[index].f;
3688 if (p->fake_event) {
3689 res = p->fake_event;
3690 p->fake_event = 0;
3691 } else
3692 res = dahdi_get_event(p->subs[index].dfd);
3694 if (option_debug)
3695 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
3697 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
3698 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
3700 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
3701 #ifdef HAVE_PRI
3702 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
3703 /* absorb event */
3704 } else {
3705 #endif
3706 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
3707 p->subs[index].f.subclass = res & 0xff;
3708 #ifdef HAVE_PRI
3710 #endif
3711 dahdi_handle_dtmfup(ast, index, &f);
3712 return f;
3715 if (res & DAHDI_EVENT_DTMFDOWN) {
3716 if (option_debug)
3717 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
3718 /* Mute conference */
3719 dahdi_confmute(p, 1);
3720 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
3721 p->subs[index].f.subclass = res & 0xff;
3722 return &p->subs[index].f;
3725 switch (res) {
3726 #ifdef DAHDI_EVENT_EC_DISABLED
3727 case DAHDI_EVENT_EC_DISABLED:
3728 if (option_verbose > 2)
3729 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
3730 p->echocanon = 0;
3731 break;
3732 #endif
3733 case DAHDI_EVENT_BITSCHANGED:
3734 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
3735 case DAHDI_EVENT_PULSE_START:
3736 /* Stop tone if there's a pulse start and the PBX isn't started */
3737 if (!ast->pbx)
3738 tone_zone_play_tone(p->subs[index].dfd, -1);
3739 break;
3740 case DAHDI_EVENT_DIALCOMPLETE:
3741 if (p->inalarm) break;
3742 if ((p->radio || (p->oprmode < 0))) break;
3743 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
3744 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
3745 return NULL;
3747 if (!x) { /* if not still dialing in driver */
3748 dahdi_enable_ec(p);
3749 if (p->echobreak) {
3750 dahdi_train_ec(p);
3751 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
3752 p->dop.op = DAHDI_DIAL_OP_REPLACE;
3753 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
3754 p->echobreak = 0;
3755 } else {
3756 p->dialing = 0;
3757 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
3758 /* if thru with dialing after offhook */
3759 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
3760 ast_setstate(ast, AST_STATE_UP);
3761 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3762 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3763 break;
3764 } else { /* if to state wait for offhook to dial rest */
3765 /* we now wait for off hook */
3766 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
3769 if (ast->_state == AST_STATE_DIALING) {
3770 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3771 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
3772 } 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)))) {
3773 ast_setstate(ast, AST_STATE_RINGING);
3774 } else if (!p->answeronpolarityswitch) {
3775 ast_setstate(ast, AST_STATE_UP);
3776 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3777 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3778 /* If aops=0 and hops=1, this is necessary */
3779 p->polarity = POLARITY_REV;
3780 } else {
3781 /* Start clean, so we can catch the change to REV polarity when party answers */
3782 p->polarity = POLARITY_IDLE;
3787 break;
3788 case DAHDI_EVENT_ALARM:
3789 #ifdef HAVE_PRI
3790 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
3791 /* T309 is not enabled : hangup calls when alarm occurs */
3792 if (p->call) {
3793 if (p->pri && p->pri->pri) {
3794 if (!pri_grab(p, p->pri)) {
3795 pri_hangup(p->pri->pri, p->call, -1);
3796 pri_destroycall(p->pri->pri, p->call);
3797 p->call = NULL;
3798 pri_rel(p->pri);
3799 } else
3800 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3801 } else
3802 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
3804 if (p->owner)
3805 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3807 if (p->bearer)
3808 p->bearer->inalarm = 1;
3809 else
3810 #endif
3811 p->inalarm = 1;
3812 res = get_alarms(p);
3813 do {
3814 const char *alarm_str = alarm2str(res);
3816 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
3817 * doesn't know what to do with it. Don't confuse users with log messages. */
3818 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3819 p->unknown_alarm = 1;
3820 break;
3821 } else {
3822 p->unknown_alarm = 0;
3825 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3826 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3827 "Alarm: %s\r\n"
3828 "Channel: %d\r\n",
3829 alarm_str, p->channel);
3830 } while (0);
3831 #ifdef HAVE_LIBPRI
3832 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3833 /* fall through intentionally */
3834 } else {
3835 break;
3837 #endif
3838 case DAHDI_EVENT_ONHOOK:
3839 if (p->radio) {
3840 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3841 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
3842 break;
3844 if (p->oprmode < 0)
3846 if (p->oprmode != -1) break;
3847 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3849 /* Make sure it starts ringing */
3850 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3851 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
3852 save_conference(p->oprpeer);
3853 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3855 break;
3857 switch (p->sig) {
3858 case SIG_FXOLS:
3859 case SIG_FXOGS:
3860 case SIG_FXOKS:
3861 p->onhooktime = time(NULL);
3862 p->msgstate = -1;
3863 /* Check for some special conditions regarding call waiting */
3864 if (index == SUB_REAL) {
3865 /* The normal line was hung up */
3866 if (p->subs[SUB_CALLWAIT].owner) {
3867 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3868 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3869 if (option_verbose > 2)
3870 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
3871 unalloc_sub(p, SUB_CALLWAIT);
3872 #if 0
3873 p->subs[index].needanswer = 0;
3874 p->subs[index].needringing = 0;
3875 #endif
3876 p->callwaitingrepeat = 0;
3877 p->cidcwexpire = 0;
3878 p->owner = NULL;
3879 /* Don't start streaming audio yet if the incoming call isn't up yet */
3880 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
3881 p->dialing = 1;
3882 dahdi_ring_phone(p);
3883 } else if (p->subs[SUB_THREEWAY].owner) {
3884 unsigned int mssinceflash;
3885 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3886 the private structure -- not especially easy or clean */
3887 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
3888 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3889 ast_mutex_unlock(&p->lock);
3890 DEADLOCK_AVOIDANCE(&ast->lock);
3891 /* We can grab ast and p in that order, without worry. We should make sure
3892 nothing seriously bad has happened though like some sort of bizarre double
3893 masquerade! */
3894 ast_mutex_lock(&p->lock);
3895 if (p->owner != ast) {
3896 ast_log(LOG_WARNING, "This isn't good...\n");
3897 return NULL;
3900 if (!p->subs[SUB_THREEWAY].owner) {
3901 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
3902 return NULL;
3904 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
3905 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
3906 if (mssinceflash < MIN_MS_SINCE_FLASH) {
3907 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3908 hanging up. Hangup both channels now */
3909 if (p->subs[SUB_THREEWAY].owner)
3910 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
3911 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3912 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
3913 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3914 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
3915 if (p->transfer) {
3916 /* In any case this isn't a threeway call anymore */
3917 p->subs[SUB_REAL].inthreeway = 0;
3918 p->subs[SUB_THREEWAY].inthreeway = 0;
3919 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
3920 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
3921 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3922 /* Swap subs and dis-own channel */
3923 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3924 p->owner = NULL;
3925 /* Ring the phone */
3926 dahdi_ring_phone(p);
3927 } else {
3928 if ((res = attempt_transfer(p)) < 0) {
3929 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3930 if (p->subs[SUB_THREEWAY].owner)
3931 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3932 } else if (res) {
3933 /* Don't actually hang up at this point */
3934 if (p->subs[SUB_THREEWAY].owner)
3935 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3936 break;
3939 } else {
3940 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3941 if (p->subs[SUB_THREEWAY].owner)
3942 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3944 } else {
3945 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3946 /* Swap subs and dis-own channel */
3947 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3948 p->owner = NULL;
3949 /* Ring the phone */
3950 dahdi_ring_phone(p);
3953 } else {
3954 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
3956 /* Fall through */
3957 default:
3958 dahdi_disable_ec(p);
3959 return NULL;
3961 break;
3962 case DAHDI_EVENT_RINGOFFHOOK:
3963 if (p->inalarm) break;
3964 if (p->oprmode < 0)
3966 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3968 /* Make sure it stops ringing */
3969 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3970 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
3971 restore_conference(p->oprpeer);
3973 break;
3975 if (p->radio)
3977 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3978 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
3979 break;
3981 /* for E911, its supposed to wait for offhook then dial
3982 the second half of the dial string */
3983 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
3984 c = strchr(p->dialdest, '/');
3985 if (c)
3986 c++;
3987 else
3988 c = p->dialdest;
3989 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
3990 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
3991 if (strlen(p->dop.dialstr) > 4) {
3992 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
3993 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
3994 p->echorest[sizeof(p->echorest) - 1] = '\0';
3995 p->echobreak = 1;
3996 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
3997 } else
3998 p->echobreak = 0;
3999 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
4000 int saveerr = errno;
4002 x = DAHDI_ONHOOK;
4003 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4004 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4005 return NULL;
4007 p->dialing = 1;
4008 return &p->subs[index].f;
4010 switch (p->sig) {
4011 case SIG_FXOLS:
4012 case SIG_FXOGS:
4013 case SIG_FXOKS:
4014 switch (ast->_state) {
4015 case AST_STATE_RINGING:
4016 dahdi_enable_ec(p);
4017 dahdi_train_ec(p);
4018 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4019 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4020 /* Make sure it stops ringing */
4021 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4022 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4023 if (p->cidspill) {
4024 /* Cancel any running CallerID spill */
4025 free(p->cidspill);
4026 p->cidspill = NULL;
4028 p->dialing = 0;
4029 p->callwaitcas = 0;
4030 if (p->confirmanswer) {
4031 /* Ignore answer if "confirm answer" is enabled */
4032 p->subs[index].f.frametype = AST_FRAME_NULL;
4033 p->subs[index].f.subclass = 0;
4034 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4035 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4036 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4037 if (res < 0) {
4038 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4039 p->dop.dialstr[0] = '\0';
4040 return NULL;
4041 } else {
4042 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4043 p->subs[index].f.frametype = AST_FRAME_NULL;
4044 p->subs[index].f.subclass = 0;
4045 p->dialing = 1;
4047 p->dop.dialstr[0] = '\0';
4048 ast_setstate(ast, AST_STATE_DIALING);
4049 } else
4050 ast_setstate(ast, AST_STATE_UP);
4051 return &p->subs[index].f;
4052 case AST_STATE_DOWN:
4053 ast_setstate(ast, AST_STATE_RING);
4054 ast->rings = 1;
4055 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4056 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4057 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4058 return &p->subs[index].f;
4059 case AST_STATE_UP:
4060 /* Make sure it stops ringing */
4061 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4062 /* Okay -- probably call waiting*/
4063 if (ast_bridged_channel(p->owner))
4064 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4065 p->subs[index].needunhold = 1;
4066 break;
4067 case AST_STATE_RESERVED:
4068 /* Start up dialtone */
4069 if (has_voicemail(p))
4070 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4071 else
4072 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4073 break;
4074 default:
4075 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4077 break;
4078 case SIG_FXSLS:
4079 case SIG_FXSGS:
4080 case SIG_FXSKS:
4081 if (ast->_state == AST_STATE_RING) {
4082 p->ringt = p->ringt_base;
4085 /* Fall through */
4086 case SIG_EM:
4087 case SIG_EM_E1:
4088 case SIG_EMWINK:
4089 case SIG_FEATD:
4090 case SIG_FEATDMF:
4091 case SIG_FEATDMF_TA:
4092 case SIG_E911:
4093 case SIG_FGC_CAMA:
4094 case SIG_FGC_CAMAMF:
4095 case SIG_FEATB:
4096 case SIG_SF:
4097 case SIG_SFWINK:
4098 case SIG_SF_FEATD:
4099 case SIG_SF_FEATDMF:
4100 case SIG_SF_FEATB:
4101 if (ast->_state == AST_STATE_PRERING)
4102 ast_setstate(ast, AST_STATE_RING);
4103 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4104 if (option_debug)
4105 ast_log(LOG_DEBUG, "Ring detected\n");
4106 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4107 p->subs[index].f.subclass = AST_CONTROL_RING;
4108 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4109 if (option_debug)
4110 ast_log(LOG_DEBUG, "Line answered\n");
4111 if (p->confirmanswer) {
4112 p->subs[index].f.frametype = AST_FRAME_NULL;
4113 p->subs[index].f.subclass = 0;
4114 } else {
4115 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4116 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4117 ast_setstate(ast, AST_STATE_UP);
4119 } else if (ast->_state != AST_STATE_RING)
4120 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4121 break;
4122 default:
4123 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4125 break;
4126 #ifdef DAHDI_EVENT_RINGBEGIN
4127 case DAHDI_EVENT_RINGBEGIN:
4128 switch (p->sig) {
4129 case SIG_FXSLS:
4130 case SIG_FXSGS:
4131 case SIG_FXSKS:
4132 if (ast->_state == AST_STATE_RING) {
4133 p->ringt = p->ringt_base;
4135 break;
4137 break;
4138 #endif
4139 case DAHDI_EVENT_RINGEROFF:
4140 if (p->inalarm) break;
4141 if ((p->radio || (p->oprmode < 0))) break;
4142 ast->rings++;
4143 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4144 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4145 free(p->cidspill);
4146 p->cidspill = NULL;
4147 p->callwaitcas = 0;
4149 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4150 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4151 break;
4152 case DAHDI_EVENT_RINGERON:
4153 break;
4154 case DAHDI_EVENT_NOALARM:
4155 p->inalarm = 0;
4156 #ifdef HAVE_PRI
4157 /* Extremely unlikely but just in case */
4158 if (p->bearer)
4159 p->bearer->inalarm = 0;
4160 #endif
4161 if (!p->unknown_alarm) {
4162 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4163 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4164 "Channel: %d\r\n", p->channel);
4165 } else {
4166 p->unknown_alarm = 0;
4168 break;
4169 case DAHDI_EVENT_WINKFLASH:
4170 if (p->inalarm) break;
4171 if (p->radio) break;
4172 if (p->oprmode < 0) break;
4173 if (p->oprmode > 1)
4175 DAHDI_PARAMS par;
4177 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4179 if (!par.rxisoffhook)
4181 /* Make sure it stops ringing */
4182 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4183 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4184 save_conference(p);
4185 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4188 break;
4190 /* Remember last time we got a flash-hook */
4191 gettimeofday(&p->flashtime, NULL);
4192 switch (mysig) {
4193 case SIG_FXOLS:
4194 case SIG_FXOGS:
4195 case SIG_FXOKS:
4196 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4197 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4198 p->callwaitcas = 0;
4200 if (index != SUB_REAL) {
4201 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4202 goto winkflashdone;
4205 if (p->subs[SUB_CALLWAIT].owner) {
4206 /* Swap to call-wait */
4207 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4208 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4209 p->owner = p->subs[SUB_REAL].owner;
4210 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4211 if (p->owner->_state == AST_STATE_RINGING) {
4212 ast_setstate(p->owner, AST_STATE_UP);
4213 p->subs[SUB_REAL].needanswer = 1;
4215 p->callwaitingrepeat = 0;
4216 p->cidcwexpire = 0;
4217 /* Start music on hold if appropriate */
4218 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4219 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4220 S_OR(p->mohsuggest, NULL),
4221 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4223 p->subs[SUB_CALLWAIT].needhold = 1;
4224 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4225 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4226 S_OR(p->mohsuggest, NULL),
4227 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4229 p->subs[SUB_REAL].needunhold = 1;
4230 } else if (!p->subs[SUB_THREEWAY].owner) {
4231 char cid_num[256];
4232 char cid_name[256];
4234 if (!p->threewaycalling) {
4235 /* Just send a flash if no 3-way calling */
4236 p->subs[SUB_REAL].needflash = 1;
4237 goto winkflashdone;
4238 } else if (!check_for_conference(p)) {
4239 if (p->dahditrcallerid && p->owner) {
4240 if (p->owner->cid.cid_num)
4241 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4242 if (p->owner->cid.cid_name)
4243 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4245 /* XXX This section needs much more error checking!!! XXX */
4246 /* Start a 3-way call if feasible */
4247 if (!((ast->pbx) ||
4248 (ast->_state == AST_STATE_UP) ||
4249 (ast->_state == AST_STATE_RING))) {
4250 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4251 goto winkflashdone;
4253 if (alloc_sub(p, SUB_THREEWAY)) {
4254 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4255 goto winkflashdone;
4257 /* Make new channel */
4258 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4259 if (p->dahditrcallerid) {
4260 if (!p->origcid_num)
4261 p->origcid_num = ast_strdup(p->cid_num);
4262 if (!p->origcid_name)
4263 p->origcid_name = ast_strdup(p->cid_name);
4264 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4265 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4267 /* Swap things around between the three-way and real call */
4268 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4269 /* Disable echo canceller for better dialing */
4270 dahdi_disable_ec(p);
4271 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4272 if (res)
4273 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4274 p->owner = chan;
4275 pthread_attr_init(&attr);
4276 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4277 if (!chan) {
4278 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4279 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4280 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4281 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4282 dahdi_enable_ec(p);
4283 ast_hangup(chan);
4284 } else {
4285 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4286 int way3bridge = 0, cdr3way = 0;
4288 if (!other) {
4289 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4290 } else
4291 way3bridge = 1;
4293 if (p->subs[SUB_THREEWAY].owner->cdr)
4294 cdr3way = 1;
4296 if (option_verbose > 2)
4297 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4298 /* Start music on hold if appropriate */
4299 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4300 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4301 S_OR(p->mohsuggest, NULL),
4302 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4304 p->subs[SUB_THREEWAY].needhold = 1;
4306 pthread_attr_destroy(&attr);
4308 } else {
4309 /* Already have a 3 way call */
4310 if (p->subs[SUB_THREEWAY].inthreeway) {
4311 /* Call is already up, drop the last person */
4312 if (option_debug)
4313 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4314 /* If the primary call isn't answered yet, use it */
4315 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4316 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4317 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4318 p->owner = p->subs[SUB_REAL].owner;
4320 /* Drop the last call and stop the conference */
4321 if (option_verbose > 2)
4322 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4323 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4324 p->subs[SUB_REAL].inthreeway = 0;
4325 p->subs[SUB_THREEWAY].inthreeway = 0;
4326 } else {
4327 /* Lets see what we're up to */
4328 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4329 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4330 int otherindex = SUB_THREEWAY;
4331 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4332 int way3bridge = 0, cdr3way = 0;
4334 if (!other) {
4335 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4336 } else
4337 way3bridge = 1;
4339 if (p->subs[SUB_THREEWAY].owner->cdr)
4340 cdr3way = 1;
4342 if (option_verbose > 2)
4343 ast_verbose(VERBOSE_PREFIX_3 "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
4344 /* Put them in the threeway, and flip */
4345 p->subs[SUB_THREEWAY].inthreeway = 1;
4346 p->subs[SUB_REAL].inthreeway = 1;
4347 if (ast->_state == AST_STATE_UP) {
4348 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4349 otherindex = SUB_REAL;
4351 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4352 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4353 p->subs[otherindex].needunhold = 1;
4354 p->owner = p->subs[SUB_REAL].owner;
4355 if (ast->_state == AST_STATE_RINGING) {
4356 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4357 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4358 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4360 } else {
4361 if (option_verbose > 2)
4362 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4363 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4364 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4365 p->owner = p->subs[SUB_REAL].owner;
4366 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4367 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4368 p->subs[SUB_REAL].needunhold = 1;
4369 dahdi_enable_ec(p);
4374 winkflashdone:
4375 update_conf(p);
4376 break;
4377 case SIG_EM:
4378 case SIG_EM_E1:
4379 case SIG_EMWINK:
4380 case SIG_FEATD:
4381 case SIG_SF:
4382 case SIG_SFWINK:
4383 case SIG_SF_FEATD:
4384 case SIG_FXSLS:
4385 case SIG_FXSGS:
4386 if (p->dialing)
4387 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4388 else
4389 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4390 break;
4391 case SIG_FEATDMF_TA:
4392 switch (p->whichwink) {
4393 case 0:
4394 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4395 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4396 break;
4397 case 1:
4398 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4399 break;
4400 case 2:
4401 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4402 return NULL;
4404 p->whichwink++;
4405 /* Fall through */
4406 case SIG_FEATDMF:
4407 case SIG_E911:
4408 case SIG_FGC_CAMAMF:
4409 case SIG_FGC_CAMA:
4410 case SIG_FEATB:
4411 case SIG_SF_FEATDMF:
4412 case SIG_SF_FEATB:
4413 /* FGD MF *Must* wait for wink */
4414 if (!ast_strlen_zero(p->dop.dialstr)) {
4415 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4416 if (res < 0) {
4417 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4418 p->dop.dialstr[0] = '\0';
4419 return NULL;
4420 } else
4421 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4423 p->dop.dialstr[0] = '\0';
4424 break;
4425 default:
4426 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4428 break;
4429 case DAHDI_EVENT_HOOKCOMPLETE:
4430 if (p->inalarm) break;
4431 if ((p->radio || (p->oprmode < 0))) break;
4432 switch (mysig) {
4433 case SIG_FXSLS: /* only interesting for FXS */
4434 case SIG_FXSGS:
4435 case SIG_FXSKS:
4436 case SIG_EM:
4437 case SIG_EM_E1:
4438 case SIG_EMWINK:
4439 case SIG_FEATD:
4440 case SIG_SF:
4441 case SIG_SFWINK:
4442 case SIG_SF_FEATD:
4443 if (!ast_strlen_zero(p->dop.dialstr)) {
4444 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4445 if (res < 0) {
4446 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4447 p->dop.dialstr[0] = '\0';
4448 return NULL;
4449 } else
4450 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4452 p->dop.dialstr[0] = '\0';
4453 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4454 break;
4455 case SIG_FEATDMF:
4456 case SIG_FEATDMF_TA:
4457 case SIG_E911:
4458 case SIG_FGC_CAMA:
4459 case SIG_FGC_CAMAMF:
4460 case SIG_FEATB:
4461 case SIG_SF_FEATDMF:
4462 case SIG_SF_FEATB:
4463 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4464 break;
4465 default:
4466 break;
4468 break;
4469 case DAHDI_EVENT_POLARITY:
4471 * If we get a Polarity Switch event, check to see
4472 * if we should change the polarity state and
4473 * mark the channel as UP or if this is an indication
4474 * of remote end disconnect.
4476 if (p->polarity == POLARITY_IDLE) {
4477 p->polarity = POLARITY_REV;
4478 if (p->answeronpolarityswitch &&
4479 ((ast->_state == AST_STATE_DIALING) ||
4480 (ast->_state == AST_STATE_RINGING))) {
4481 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4482 ast_setstate(p->owner, AST_STATE_UP);
4483 if (p->hanguponpolarityswitch) {
4484 gettimeofday(&p->polaritydelaytv, NULL);
4486 } else
4487 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4489 /* Removed else statement from here as it was preventing hangups from ever happening*/
4490 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4491 if (p->hanguponpolarityswitch &&
4492 (p->polarityonanswerdelay > 0) &&
4493 (p->polarity == POLARITY_REV) &&
4494 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4495 /* Added log_debug information below to provide a better indication of what is going on */
4496 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
4498 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4499 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4500 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4501 p->polarity = POLARITY_IDLE;
4502 } else {
4503 ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
4505 } else {
4506 p->polarity = POLARITY_IDLE;
4507 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4509 /* Added more log_debug information below to provide a better indication of what is going on */
4510 ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
4511 break;
4512 default:
4513 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4515 return &p->subs[index].f;
4518 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4520 struct dahdi_pvt *p = ast->tech_pvt;
4521 int res;
4522 int usedindex=-1;
4523 int index;
4524 struct ast_frame *f;
4527 index = dahdi_get_index(ast, p, 1);
4529 p->subs[index].f.frametype = AST_FRAME_NULL;
4530 p->subs[index].f.datalen = 0;
4531 p->subs[index].f.samples = 0;
4532 p->subs[index].f.mallocd = 0;
4533 p->subs[index].f.offset = 0;
4534 p->subs[index].f.subclass = 0;
4535 p->subs[index].f.delivery = ast_tv(0,0);
4536 p->subs[index].f.src = "dahdi_exception";
4537 p->subs[index].f.data = NULL;
4540 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4541 /* If nobody owns us, absorb the event appropriately, otherwise
4542 we loop indefinitely. This occurs when, during call waiting, the
4543 other end hangs up our channel so that it no longer exists, but we
4544 have neither FLASH'd nor ONHOOK'd to signify our desire to
4545 change to the other channel. */
4546 if (p->fake_event) {
4547 res = p->fake_event;
4548 p->fake_event = 0;
4549 } else
4550 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4551 /* Switch to real if there is one and this isn't something really silly... */
4552 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4553 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4554 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4555 p->owner = p->subs[SUB_REAL].owner;
4556 if (p->owner && ast_bridged_channel(p->owner))
4557 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4558 p->subs[SUB_REAL].needunhold = 1;
4560 switch (res) {
4561 case DAHDI_EVENT_ONHOOK:
4562 dahdi_disable_ec(p);
4563 if (p->owner) {
4564 if (option_verbose > 2)
4565 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4566 dahdi_ring_phone(p);
4567 p->callwaitingrepeat = 0;
4568 p->cidcwexpire = 0;
4569 } else
4570 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4571 update_conf(p);
4572 break;
4573 case DAHDI_EVENT_RINGOFFHOOK:
4574 dahdi_enable_ec(p);
4575 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4576 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4577 p->subs[SUB_REAL].needanswer = 1;
4578 p->dialing = 0;
4580 break;
4581 case DAHDI_EVENT_HOOKCOMPLETE:
4582 case DAHDI_EVENT_RINGERON:
4583 case DAHDI_EVENT_RINGEROFF:
4584 /* Do nothing */
4585 break;
4586 case DAHDI_EVENT_WINKFLASH:
4587 gettimeofday(&p->flashtime, NULL);
4588 if (p->owner) {
4589 if (option_verbose > 2)
4590 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4591 if (p->owner->_state != AST_STATE_UP) {
4592 /* Answer if necessary */
4593 usedindex = dahdi_get_index(p->owner, p, 0);
4594 if (usedindex > -1) {
4595 p->subs[usedindex].needanswer = 1;
4597 ast_setstate(p->owner, AST_STATE_UP);
4599 p->callwaitingrepeat = 0;
4600 p->cidcwexpire = 0;
4601 if (ast_bridged_channel(p->owner))
4602 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4603 p->subs[SUB_REAL].needunhold = 1;
4604 } else
4605 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4606 update_conf(p);
4607 break;
4608 default:
4609 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4611 f = &p->subs[index].f;
4612 return f;
4614 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4615 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4616 /* If it's not us, return NULL immediately */
4617 if (ast != p->owner) {
4618 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4619 f = &p->subs[index].f;
4620 return f;
4622 f = dahdi_handle_event(ast);
4623 return f;
4626 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4628 struct dahdi_pvt *p = ast->tech_pvt;
4629 struct ast_frame *f;
4630 ast_mutex_lock(&p->lock);
4631 f = __dahdi_exception(ast);
4632 ast_mutex_unlock(&p->lock);
4633 return f;
4636 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4638 struct dahdi_pvt *p = ast->tech_pvt;
4639 int res;
4640 int index;
4641 void *readbuf;
4642 struct ast_frame *f;
4644 while (ast_mutex_trylock(&p->lock)) {
4645 DEADLOCK_AVOIDANCE(&ast->lock);
4648 index = dahdi_get_index(ast, p, 0);
4650 /* Hang up if we don't really exist */
4651 if (index < 0) {
4652 ast_log(LOG_WARNING, "We dont exist?\n");
4653 ast_mutex_unlock(&p->lock);
4654 return NULL;
4657 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4659 p->subs[index].f.frametype = AST_FRAME_NULL;
4660 p->subs[index].f.datalen = 0;
4661 p->subs[index].f.samples = 0;
4662 p->subs[index].f.mallocd = 0;
4663 p->subs[index].f.offset = 0;
4664 p->subs[index].f.subclass = 0;
4665 p->subs[index].f.delivery = ast_tv(0,0);
4666 p->subs[index].f.src = "dahdi_read";
4667 p->subs[index].f.data = NULL;
4669 /* make sure it sends initial key state as first frame */
4670 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4672 DAHDI_PARAMS ps;
4674 ps.channo = p->channel;
4675 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4676 ast_mutex_unlock(&p->lock);
4677 return NULL;
4679 p->firstradio = 1;
4680 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4681 if (ps.rxisoffhook)
4683 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4685 else
4687 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4689 ast_mutex_unlock(&p->lock);
4690 return &p->subs[index].f;
4692 if (p->ringt == 1) {
4693 ast_mutex_unlock(&p->lock);
4694 return NULL;
4696 else if (p->ringt > 0)
4697 p->ringt--;
4699 if (p->subs[index].needringing) {
4700 /* Send ringing frame if requested */
4701 p->subs[index].needringing = 0;
4702 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4703 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4704 ast_setstate(ast, AST_STATE_RINGING);
4705 ast_mutex_unlock(&p->lock);
4706 return &p->subs[index].f;
4709 if (p->subs[index].needbusy) {
4710 /* Send busy frame if requested */
4711 p->subs[index].needbusy = 0;
4712 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4713 p->subs[index].f.subclass = AST_CONTROL_BUSY;
4714 ast_mutex_unlock(&p->lock);
4715 return &p->subs[index].f;
4718 if (p->subs[index].needcongestion) {
4719 /* Send congestion frame if requested */
4720 p->subs[index].needcongestion = 0;
4721 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4722 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
4723 ast_mutex_unlock(&p->lock);
4724 return &p->subs[index].f;
4727 if (p->subs[index].needcallerid) {
4728 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
4729 S_OR(p->lastcid_name, NULL),
4730 S_OR(p->lastcid_num, NULL)
4732 p->subs[index].needcallerid = 0;
4735 if (p->subs[index].needanswer) {
4736 /* Send answer frame if requested */
4737 p->subs[index].needanswer = 0;
4738 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4739 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4740 ast_mutex_unlock(&p->lock);
4741 return &p->subs[index].f;
4744 if (p->subs[index].needflash) {
4745 /* Send answer frame if requested */
4746 p->subs[index].needflash = 0;
4747 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4748 p->subs[index].f.subclass = AST_CONTROL_FLASH;
4749 ast_mutex_unlock(&p->lock);
4750 return &p->subs[index].f;
4753 if (p->subs[index].needhold) {
4754 /* Send answer frame if requested */
4755 p->subs[index].needhold = 0;
4756 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4757 p->subs[index].f.subclass = AST_CONTROL_HOLD;
4758 ast_mutex_unlock(&p->lock);
4759 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
4760 return &p->subs[index].f;
4763 if (p->subs[index].needunhold) {
4764 /* Send answer frame if requested */
4765 p->subs[index].needunhold = 0;
4766 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4767 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
4768 ast_mutex_unlock(&p->lock);
4769 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
4770 return &p->subs[index].f;
4773 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
4774 if (!p->subs[index].linear) {
4775 p->subs[index].linear = 1;
4776 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4777 if (res)
4778 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
4780 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
4781 (ast->rawreadformat == AST_FORMAT_ALAW)) {
4782 if (p->subs[index].linear) {
4783 p->subs[index].linear = 0;
4784 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4785 if (res)
4786 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
4788 } else {
4789 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
4790 ast_mutex_unlock(&p->lock);
4791 return NULL;
4793 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
4794 CHECK_BLOCKING(ast);
4795 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4796 ast_clear_flag(ast, AST_FLAG_BLOCKING);
4797 /* Check for hangup */
4798 if (res < 0) {
4799 f = NULL;
4800 if (res == -1) {
4801 if (errno == EAGAIN) {
4802 /* Return "NULL" frame if there is nobody there */
4803 ast_mutex_unlock(&p->lock);
4804 return &p->subs[index].f;
4805 } else if (errno == ELAST) {
4806 f = __dahdi_exception(ast);
4807 } else
4808 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
4810 ast_mutex_unlock(&p->lock);
4811 return f;
4813 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
4814 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4815 f = __dahdi_exception(ast);
4816 ast_mutex_unlock(&p->lock);
4817 return f;
4819 if (p->tdd) { /* if in TDD mode, see if we receive that */
4820 int c;
4822 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
4823 if (c < 0) {
4824 ast_log(LOG_DEBUG,"tdd_feed failed\n");
4825 ast_mutex_unlock(&p->lock);
4826 return NULL;
4828 if (c) { /* if a char to return */
4829 p->subs[index].f.subclass = 0;
4830 p->subs[index].f.frametype = AST_FRAME_TEXT;
4831 p->subs[index].f.mallocd = 0;
4832 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4833 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
4834 p->subs[index].f.datalen = 1;
4835 *((char *) p->subs[index].f.data) = c;
4836 ast_mutex_unlock(&p->lock);
4837 return &p->subs[index].f;
4840 /* Ensure the CW timer decrements only on a single subchannel */
4841 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
4842 p->callwaitingrepeat--;
4844 if (p->cidcwexpire)
4845 p->cidcwexpire--;
4846 /* Repeat callwaiting */
4847 if (p->callwaitingrepeat == 1) {
4848 p->callwaitrings++;
4849 dahdi_callwait(ast);
4851 /* Expire CID/CW */
4852 if (p->cidcwexpire == 1) {
4853 if (option_verbose > 2)
4854 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
4855 restore_conference(p);
4857 if (p->subs[index].linear) {
4858 p->subs[index].f.datalen = READ_SIZE * 2;
4859 } else
4860 p->subs[index].f.datalen = READ_SIZE;
4862 /* Handle CallerID Transmission */
4863 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
4864 send_callerid(p);
4867 p->subs[index].f.frametype = AST_FRAME_VOICE;
4868 p->subs[index].f.subclass = ast->rawreadformat;
4869 p->subs[index].f.samples = READ_SIZE;
4870 p->subs[index].f.mallocd = 0;
4871 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4872 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
4873 #if 0
4874 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
4875 #endif
4876 if (p->dialing || /* Transmitting something */
4877 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
4878 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
4880 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4881 don't send anything */
4882 p->subs[index].f.frametype = AST_FRAME_NULL;
4883 p->subs[index].f.subclass = 0;
4884 p->subs[index].f.samples = 0;
4885 p->subs[index].f.mallocd = 0;
4886 p->subs[index].f.offset = 0;
4887 p->subs[index].f.data = NULL;
4888 p->subs[index].f.datalen= 0;
4890 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
4891 /* Perform busy detection. etc on the dahdi line */
4892 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
4893 if (f) {
4894 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
4895 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
4896 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4897 a busy */
4898 f = NULL;
4900 } else if (f->frametype == AST_FRAME_DTMF) {
4901 #ifdef HAVE_PRI
4902 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
4903 /* Don't accept in-band DTMF when in overlap dial mode */
4904 f->frametype = AST_FRAME_NULL;
4905 f->subclass = 0;
4907 #endif
4908 /* DSP clears us of being pulse */
4909 p->pulsedial = 0;
4912 } else
4913 f = &p->subs[index].f;
4915 if (f && (f->frametype == AST_FRAME_DTMF))
4916 dahdi_handle_dtmfup(ast, index, &f);
4918 /* If we have a fake_event, trigger exception to handle it */
4919 if (p->fake_event)
4920 ast_set_flag(ast, AST_FLAG_EXCEPTION);
4922 ast_mutex_unlock(&p->lock);
4923 return f;
4926 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
4928 int sent=0;
4929 int size;
4930 int res;
4931 int fd;
4932 fd = p->subs[index].dfd;
4933 while (len) {
4934 size = len;
4935 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
4936 size = (linear ? READ_SIZE * 2 : READ_SIZE);
4937 res = write(fd, buf, size);
4938 if (res != size) {
4939 if (option_debug)
4940 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
4941 return sent;
4943 len -= size;
4944 buf += size;
4946 return sent;
4949 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
4951 struct dahdi_pvt *p = ast->tech_pvt;
4952 int res;
4953 int index;
4954 index = dahdi_get_index(ast, p, 0);
4955 if (index < 0) {
4956 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
4957 return -1;
4960 #if 0
4961 #ifdef HAVE_PRI
4962 ast_mutex_lock(&p->lock);
4963 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
4964 if (p->pri->pri) {
4965 if (!pri_grab(p, p->pri)) {
4966 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
4967 pri_rel(p->pri);
4968 } else
4969 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
4971 p->proceeding=1;
4973 ast_mutex_unlock(&p->lock);
4974 #endif
4975 #endif
4976 /* Write a frame of (presumably voice) data */
4977 if (frame->frametype != AST_FRAME_VOICE) {
4978 if (frame->frametype != AST_FRAME_IMAGE)
4979 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
4980 return 0;
4982 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
4983 (frame->subclass != AST_FORMAT_ULAW) &&
4984 (frame->subclass != AST_FORMAT_ALAW)) {
4985 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
4986 return -1;
4988 if (p->dialing) {
4989 if (option_debug)
4990 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
4991 return 0;
4993 if (!p->owner) {
4994 if (option_debug)
4995 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
4996 return 0;
4998 if (p->cidspill) {
4999 if (option_debug)
5000 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5001 return 0;
5003 /* Return if it's not valid data */
5004 if (!frame->data || !frame->datalen)
5005 return 0;
5007 if (frame->subclass == AST_FORMAT_SLINEAR) {
5008 if (!p->subs[index].linear) {
5009 p->subs[index].linear = 1;
5010 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5011 if (res)
5012 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5014 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5015 } else {
5016 /* x-law already */
5017 if (p->subs[index].linear) {
5018 p->subs[index].linear = 0;
5019 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5020 if (res)
5021 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5023 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5025 if (res < 0) {
5026 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5027 return -1;
5029 return 0;
5032 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5034 struct dahdi_pvt *p = chan->tech_pvt;
5035 int res=-1;
5036 int index;
5037 int func = DAHDI_FLASH;
5038 ast_mutex_lock(&p->lock);
5039 index = dahdi_get_index(chan, p, 0);
5040 if (option_debug)
5041 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5042 if (index == SUB_REAL) {
5043 switch (condition) {
5044 case AST_CONTROL_BUSY:
5045 #ifdef HAVE_PRI
5046 if (p->priindication_oob && p->sig == SIG_PRI) {
5047 chan->hangupcause = AST_CAUSE_USER_BUSY;
5048 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5049 res = 0;
5050 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5051 if (p->pri->pri) {
5052 if (!pri_grab(p, p->pri)) {
5053 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5054 pri_rel(p->pri);
5056 else
5057 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5059 p->progress = 1;
5060 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5061 } else
5062 #endif
5063 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5064 break;
5065 case AST_CONTROL_RINGING:
5066 #ifdef HAVE_PRI
5067 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5068 if (p->pri->pri) {
5069 if (!pri_grab(p, p->pri)) {
5070 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5071 pri_rel(p->pri);
5073 else
5074 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5076 p->alerting = 1;
5078 #endif
5079 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5080 if (chan->_state != AST_STATE_UP) {
5081 if ((chan->_state != AST_STATE_RING) ||
5082 ((p->sig != SIG_FXSKS) &&
5083 (p->sig != SIG_FXSLS) &&
5084 (p->sig != SIG_FXSGS)))
5085 ast_setstate(chan, AST_STATE_RINGING);
5087 break;
5088 case AST_CONTROL_PROCEEDING:
5089 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5090 #ifdef HAVE_PRI
5091 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5092 if (p->pri->pri) {
5093 if (!pri_grab(p, p->pri)) {
5094 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5095 pri_rel(p->pri);
5097 else
5098 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5100 p->proceeding = 1;
5102 #endif
5103 /* don't continue in ast_indicate */
5104 res = 0;
5105 break;
5106 case AST_CONTROL_PROGRESS:
5107 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5108 #ifdef HAVE_PRI
5109 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5110 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5111 if (p->pri->pri) {
5112 if (!pri_grab(p, p->pri)) {
5113 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5114 pri_rel(p->pri);
5116 else
5117 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5119 p->progress = 1;
5121 #endif
5122 /* don't continue in ast_indicate */
5123 res = 0;
5124 break;
5125 case AST_CONTROL_CONGESTION:
5126 chan->hangupcause = AST_CAUSE_CONGESTION;
5127 #ifdef HAVE_PRI
5128 if (p->priindication_oob && p->sig == SIG_PRI) {
5129 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5130 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5131 res = 0;
5132 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5133 if (p->pri) {
5134 if (!pri_grab(p, p->pri)) {
5135 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5136 pri_rel(p->pri);
5137 } else
5138 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5140 p->progress = 1;
5141 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5142 } else
5143 #endif
5144 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5145 break;
5146 case AST_CONTROL_HOLD:
5147 #ifdef HAVE_PRI
5148 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5149 if (!pri_grab(p, p->pri)) {
5150 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5151 pri_rel(p->pri);
5152 } else
5153 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5154 } else
5155 #endif
5156 ast_moh_start(chan, data, p->mohinterpret);
5157 break;
5158 case AST_CONTROL_UNHOLD:
5159 #ifdef HAVE_PRI
5160 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5161 if (!pri_grab(p, p->pri)) {
5162 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5163 pri_rel(p->pri);
5164 } else
5165 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5166 } else
5167 #endif
5168 ast_moh_stop(chan);
5169 break;
5170 case AST_CONTROL_RADIO_KEY:
5171 if (p->radio)
5172 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5173 res = 0;
5174 break;
5175 case AST_CONTROL_RADIO_UNKEY:
5176 if (p->radio)
5177 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5178 res = 0;
5179 break;
5180 case AST_CONTROL_FLASH:
5181 /* flash hookswitch */
5182 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5183 /* Clear out the dial buffer */
5184 p->dop.dialstr[0] = '\0';
5185 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5186 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5187 chan->name, strerror(errno));
5188 } else
5189 res = 0;
5190 } else
5191 res = 0;
5192 break;
5193 case AST_CONTROL_SRCUPDATE:
5194 res = 0;
5195 break;
5196 case -1:
5197 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5198 break;
5200 } else
5201 res = 0;
5202 ast_mutex_unlock(&p->lock);
5203 return res;
5206 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5208 struct ast_channel *tmp;
5209 int deflaw;
5210 int res;
5211 int x,y;
5212 int features;
5213 char *b2 = NULL;
5214 DAHDI_PARAMS ps;
5215 if (i->subs[index].owner) {
5216 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5217 return NULL;
5219 y = 1;
5220 do {
5221 if (b2)
5222 free(b2);
5223 #ifdef HAVE_PRI
5224 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5225 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5226 else
5227 #endif
5228 if (i->channel == CHAN_PSEUDO)
5229 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5230 else
5231 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5232 for (x = 0; x < 3; x++) {
5233 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
5234 break;
5236 y++;
5237 } while (x < 3);
5238 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", b2);
5239 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5240 free(b2);
5241 if (!tmp)
5242 return NULL;
5243 tmp->tech = &dahdi_tech;
5244 ps.channo = i->channel;
5245 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5246 if (res) {
5247 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5248 ps.curlaw = DAHDI_LAW_MULAW;
5250 if (ps.curlaw == DAHDI_LAW_ALAW)
5251 deflaw = AST_FORMAT_ALAW;
5252 else
5253 deflaw = AST_FORMAT_ULAW;
5254 if (law) {
5255 if (law == DAHDI_LAW_ALAW)
5256 deflaw = AST_FORMAT_ALAW;
5257 else
5258 deflaw = AST_FORMAT_ULAW;
5260 tmp->fds[0] = i->subs[index].dfd;
5261 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5262 /* Start out assuming ulaw since it's smaller :) */
5263 tmp->rawreadformat = deflaw;
5264 tmp->readformat = deflaw;
5265 tmp->rawwriteformat = deflaw;
5266 tmp->writeformat = deflaw;
5267 i->subs[index].linear = 0;
5268 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5269 features = 0;
5270 if (index == SUB_REAL) {
5271 if (i->busydetect && CANBUSYDETECT(i))
5272 features |= DSP_FEATURE_BUSY_DETECT;
5273 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5274 features |= DSP_FEATURE_CALL_PROGRESS;
5275 if ((!i->outgoing && (i->callprogress & 4)) ||
5276 (i->outgoing && (i->callprogress & 2))) {
5277 features |= DSP_FEATURE_FAX_DETECT;
5279 #ifdef DAHDI_TONEDETECT
5280 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5281 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5282 #endif
5283 i->hardwaredtmf = 0;
5284 features |= DSP_FEATURE_DTMF_DETECT;
5285 #ifdef DAHDI_TONEDETECT
5286 } else if (NEED_MFDETECT(i)) {
5287 i->hardwaredtmf = 1;
5288 features |= DSP_FEATURE_DTMF_DETECT;
5290 #endif
5292 if (features) {
5293 if (i->dsp) {
5294 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5295 } else {
5296 if (i->channel != CHAN_PSEUDO)
5297 i->dsp = ast_dsp_new();
5298 else
5299 i->dsp = NULL;
5300 if (i->dsp) {
5301 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5302 #ifdef HAVE_PRI
5303 /* We cannot do progress detection until receives PROGRESS message */
5304 if (i->outgoing && (i->sig == SIG_PRI)) {
5305 /* Remember requested DSP features, don't treat
5306 talking as ANSWER */
5307 features = 0;
5309 #endif
5310 ast_dsp_set_features(i->dsp, features);
5311 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5312 if (!ast_strlen_zero(progzone))
5313 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5314 if (i->busydetect && CANBUSYDETECT(i)) {
5315 ast_dsp_set_busy_count(i->dsp, i->busycount);
5316 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5322 if (state == AST_STATE_RING)
5323 tmp->rings = 1;
5324 tmp->tech_pvt = i;
5325 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5326 /* Only FXO signalled stuff can be picked up */
5327 tmp->callgroup = i->callgroup;
5328 tmp->pickupgroup = i->pickupgroup;
5330 if (!ast_strlen_zero(i->language))
5331 ast_string_field_set(tmp, language, i->language);
5332 if (!i->owner)
5333 i->owner = tmp;
5334 if (!ast_strlen_zero(i->accountcode))
5335 ast_string_field_set(tmp, accountcode, i->accountcode);
5336 if (i->amaflags)
5337 tmp->amaflags = i->amaflags;
5338 i->subs[index].owner = tmp;
5339 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5340 ast_string_field_set(tmp, call_forward, i->call_forward);
5341 /* If we've been told "no ADSI" then enforce it */
5342 if (!i->adsi)
5343 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5344 if (!ast_strlen_zero(i->exten))
5345 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5346 if (!ast_strlen_zero(i->rdnis))
5347 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5348 if (!ast_strlen_zero(i->dnid))
5349 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5351 /* Don't use ast_set_callerid() here because it will
5352 * generate a needless NewCallerID event */
5353 #ifdef PRI_ANI
5354 if (!ast_strlen_zero(i->cid_ani))
5355 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5356 else
5357 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5358 #else
5359 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5360 #endif
5361 tmp->cid.cid_pres = i->callingpres;
5362 tmp->cid.cid_ton = i->cid_ton;
5363 #ifdef HAVE_PRI
5364 tmp->transfercapability = transfercapability;
5365 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5366 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5367 i->digital = 1;
5368 /* Assume calls are not idle calls unless we're told differently */
5369 i->isidlecall = 0;
5370 i->alreadyhungup = 0;
5371 #endif
5372 /* clear the fake event in case we posted one before we had ast_channel */
5373 i->fake_event = 0;
5374 /* Assure there is no confmute on this channel */
5375 dahdi_confmute(i, 0);
5376 /* Configure the new channel jb */
5377 ast_jb_configure(tmp, &global_jbconf);
5378 if (startpbx) {
5379 if (ast_pbx_start(tmp)) {
5380 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5381 ast_hangup(tmp);
5382 i->owner = NULL;
5383 return NULL;
5387 ast_module_ref(ast_module_info->self);
5389 return tmp;
5393 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5395 char c;
5397 *str = 0; /* start with empty output buffer */
5398 for (;;)
5400 /* Wait for the first digit (up to specified ms). */
5401 c = ast_waitfordigit(chan, ms);
5402 /* if timeout, hangup or error, return as such */
5403 if (c < 1)
5404 return c;
5405 *str++ = c;
5406 *str = 0;
5407 if (strchr(term, c))
5408 return 1;
5412 static int dahdi_wink(struct dahdi_pvt *p, int index)
5414 int j;
5415 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5416 for (;;)
5418 /* set bits of interest */
5419 j = DAHDI_IOMUX_SIGEVENT;
5420 /* wait for some happening */
5421 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5422 /* exit loop if we have it */
5423 if (j & DAHDI_IOMUX_SIGEVENT) break;
5425 /* get the event info */
5426 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5427 return 0;
5430 static void *ss_thread(void *data)
5432 struct ast_channel *chan = data;
5433 struct dahdi_pvt *p = chan->tech_pvt;
5434 char exten[AST_MAX_EXTENSION] = "";
5435 char exten2[AST_MAX_EXTENSION] = "";
5436 unsigned char buf[256];
5437 char dtmfcid[300];
5438 char dtmfbuf[300];
5439 struct callerid_state *cs = NULL;
5440 char *name = NULL, *number = NULL;
5441 int distMatches;
5442 int curRingData[3];
5443 int receivedRingT;
5444 int counter1;
5445 int counter;
5446 int samples = 0;
5447 struct ast_smdi_md_message *smdi_msg = NULL;
5448 int flags;
5449 int i;
5450 int timeout;
5451 int getforward = 0;
5452 char *s1, *s2;
5453 int len = 0;
5454 int res;
5455 int index;
5457 /* in the bizarre case where the channel has become a zombie before we
5458 even get started here, abort safely
5460 if (!p) {
5461 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5462 ast_hangup(chan);
5463 return NULL;
5466 if (option_verbose > 2)
5467 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5468 index = dahdi_get_index(chan, p, 1);
5469 if (index < 0) {
5470 ast_log(LOG_WARNING, "Huh?\n");
5471 ast_hangup(chan);
5472 return NULL;
5474 if (p->dsp)
5475 ast_dsp_digitreset(p->dsp);
5476 switch (p->sig) {
5477 #ifdef HAVE_PRI
5478 case SIG_PRI:
5479 /* Now loop looking for an extension */
5480 ast_copy_string(exten, p->exten, sizeof(exten));
5481 len = strlen(exten);
5482 res = 0;
5483 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5484 if (len && !ast_ignore_pattern(chan->context, exten))
5485 tone_zone_play_tone(p->subs[index].dfd, -1);
5486 else
5487 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5488 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5489 timeout = matchdigittimeout;
5490 else
5491 timeout = gendigittimeout;
5492 res = ast_waitfordigit(chan, timeout);
5493 if (res < 0) {
5494 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5495 ast_hangup(chan);
5496 return NULL;
5497 } else if (res) {
5498 exten[len++] = res;
5499 exten[len] = '\0';
5500 } else
5501 break;
5503 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5504 if (ast_strlen_zero(exten)) {
5505 if (option_verbose > 2)
5506 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5507 exten[0] = 's';
5508 exten[1] = '\0';
5510 tone_zone_play_tone(p->subs[index].dfd, -1);
5511 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5512 /* Start the real PBX */
5513 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5514 if (p->dsp) ast_dsp_digitreset(p->dsp);
5515 dahdi_enable_ec(p);
5516 ast_setstate(chan, AST_STATE_RING);
5517 res = ast_pbx_run(chan);
5518 if (res) {
5519 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5521 } else {
5522 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5523 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5524 ast_hangup(chan);
5525 p->exten[0] = '\0';
5526 /* Since we send release complete here, we won't get one */
5527 p->call = NULL;
5529 return NULL;
5530 break;
5531 #endif
5532 case SIG_FEATD:
5533 case SIG_FEATDMF:
5534 case SIG_FEATDMF_TA:
5535 case SIG_E911:
5536 case SIG_FGC_CAMAMF:
5537 case SIG_FEATB:
5538 case SIG_EMWINK:
5539 case SIG_SF_FEATD:
5540 case SIG_SF_FEATDMF:
5541 case SIG_SF_FEATB:
5542 case SIG_SFWINK:
5543 if (dahdi_wink(p, index))
5544 return NULL;
5545 /* Fall through */
5546 case SIG_EM:
5547 case SIG_EM_E1:
5548 case SIG_SF:
5549 case SIG_FGC_CAMA:
5550 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5551 if (p->dsp)
5552 ast_dsp_digitreset(p->dsp);
5553 /* set digit mode appropriately */
5554 if (p->dsp) {
5555 if (NEED_MFDETECT(p))
5556 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5557 else
5558 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5560 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5561 /* Wait for the first digit only if immediate=no */
5562 if (!p->immediate)
5563 /* Wait for the first digit (up to 5 seconds). */
5564 res = ast_waitfordigit(chan, 5000);
5565 else
5566 res = 0;
5567 if (res > 0) {
5568 /* save first char */
5569 dtmfbuf[0] = res;
5570 switch (p->sig) {
5571 case SIG_FEATD:
5572 case SIG_SF_FEATD:
5573 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5574 if (res > 0)
5575 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5576 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5577 break;
5578 case SIG_FEATDMF_TA:
5579 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5580 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5581 if (dahdi_wink(p, index)) return NULL;
5582 dtmfbuf[0] = 0;
5583 /* Wait for the first digit (up to 5 seconds). */
5584 res = ast_waitfordigit(chan, 5000);
5585 if (res <= 0) break;
5586 dtmfbuf[0] = res;
5587 /* fall through intentionally */
5588 case SIG_FEATDMF:
5589 case SIG_E911:
5590 case SIG_FGC_CAMAMF:
5591 case SIG_SF_FEATDMF:
5592 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5593 /* if international caca, do it again to get real ANO */
5594 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5596 if (dahdi_wink(p, index)) return NULL;
5597 dtmfbuf[0] = 0;
5598 /* Wait for the first digit (up to 5 seconds). */
5599 res = ast_waitfordigit(chan, 5000);
5600 if (res <= 0) break;
5601 dtmfbuf[0] = res;
5602 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5604 if (res > 0) {
5605 /* if E911, take off hook */
5606 if (p->sig == SIG_E911)
5607 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5608 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5610 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5611 break;
5612 case SIG_FEATB:
5613 case SIG_SF_FEATB:
5614 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5615 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5616 break;
5617 case SIG_EMWINK:
5618 /* if we received a '*', we are actually receiving Feature Group D
5619 dial syntax, so use that mode; otherwise, fall through to normal
5620 mode
5622 if (res == '*') {
5623 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5624 if (res > 0)
5625 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5626 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5627 break;
5629 default:
5630 /* If we got the first digit, get the rest */
5631 len = 1;
5632 dtmfbuf[len] = '\0';
5633 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5634 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5635 timeout = matchdigittimeout;
5636 } else {
5637 timeout = gendigittimeout;
5639 res = ast_waitfordigit(chan, timeout);
5640 if (res < 0) {
5641 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5642 ast_hangup(chan);
5643 return NULL;
5644 } else if (res) {
5645 dtmfbuf[len++] = res;
5646 dtmfbuf[len] = '\0';
5647 } else {
5648 break;
5651 break;
5654 if (res == -1) {
5655 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5656 ast_hangup(chan);
5657 return NULL;
5658 } else if (res < 0) {
5659 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
5660 ast_hangup(chan);
5661 return NULL;
5664 if (p->sig == SIG_FGC_CAMA) {
5665 char anibuf[100];
5667 if (ast_safe_sleep(chan,1000) == -1) {
5668 ast_hangup(chan);
5669 return NULL;
5671 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5672 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5673 res = my_getsigstr(chan, anibuf, "#", 10000);
5674 if ((res > 0) && (strlen(anibuf) > 2)) {
5675 if (anibuf[strlen(anibuf) - 1] == '#')
5676 anibuf[strlen(anibuf) - 1] = 0;
5677 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
5679 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5682 ast_copy_string(exten, dtmfbuf, sizeof(exten));
5683 if (ast_strlen_zero(exten))
5684 ast_copy_string(exten, "s", sizeof(exten));
5685 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
5686 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5687 if (exten[0] == '*') {
5688 char *stringp=NULL;
5689 ast_copy_string(exten2, exten, sizeof(exten2));
5690 /* Parse out extension and callerid */
5691 stringp=exten2 +1;
5692 s1 = strsep(&stringp, "*");
5693 s2 = strsep(&stringp, "*");
5694 if (s2) {
5695 if (!ast_strlen_zero(p->cid_num))
5696 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5697 else
5698 ast_set_callerid(chan, s1, NULL, s1);
5699 ast_copy_string(exten, s2, sizeof(exten));
5700 } else
5701 ast_copy_string(exten, s1, sizeof(exten));
5702 } else if (p->sig == SIG_FEATD)
5703 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5705 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5706 if (exten[0] == '*') {
5707 char *stringp=NULL;
5708 ast_copy_string(exten2, exten, sizeof(exten2));
5709 /* Parse out extension and callerid */
5710 stringp=exten2 +1;
5711 s1 = strsep(&stringp, "#");
5712 s2 = strsep(&stringp, "#");
5713 if (s2) {
5714 if (!ast_strlen_zero(p->cid_num))
5715 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5716 else
5717 if (*(s1 + 2))
5718 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
5719 ast_copy_string(exten, s2 + 1, sizeof(exten));
5720 } else
5721 ast_copy_string(exten, s1 + 2, sizeof(exten));
5722 } else
5723 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5725 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
5726 if (exten[0] == '*') {
5727 char *stringp=NULL;
5728 ast_copy_string(exten2, exten, sizeof(exten2));
5729 /* Parse out extension and callerid */
5730 stringp=exten2 +1;
5731 s1 = strsep(&stringp, "#");
5732 s2 = strsep(&stringp, "#");
5733 if (s2 && (*(s2 + 1) == '0')) {
5734 if (*(s2 + 2))
5735 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
5737 if (s1) ast_copy_string(exten, s1, sizeof(exten));
5738 else ast_copy_string(exten, "911", sizeof(exten));
5739 } else
5740 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
5742 if (p->sig == SIG_FEATB) {
5743 if (exten[0] == '*') {
5744 char *stringp=NULL;
5745 ast_copy_string(exten2, exten, sizeof(exten2));
5746 /* Parse out extension and callerid */
5747 stringp=exten2 +1;
5748 s1 = strsep(&stringp, "#");
5749 ast_copy_string(exten, exten2 + 1, sizeof(exten));
5750 } else
5751 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
5753 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5754 dahdi_wink(p, index);
5755 /* some switches require a minimum guard time between
5756 the last FGD wink and something that answers
5757 immediately. This ensures it */
5758 if (ast_safe_sleep(chan,100)) return NULL;
5760 dahdi_enable_ec(p);
5761 if (NEED_MFDETECT(p)) {
5762 if (p->dsp) {
5763 if (!p->hardwaredtmf)
5764 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5765 else {
5766 ast_dsp_free(p->dsp);
5767 p->dsp = NULL;
5772 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
5773 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5774 if (p->dsp) ast_dsp_digitreset(p->dsp);
5775 res = ast_pbx_run(chan);
5776 if (res) {
5777 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5778 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5780 return NULL;
5781 } else {
5782 if (option_verbose > 2)
5783 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
5784 sleep(2);
5785 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
5786 if (res < 0)
5787 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
5788 else
5789 sleep(1);
5790 res = ast_streamfile(chan, "ss-noservice", chan->language);
5791 if (res >= 0)
5792 ast_waitstream(chan, "");
5793 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5794 ast_hangup(chan);
5795 return NULL;
5797 break;
5798 case SIG_FXOLS:
5799 case SIG_FXOGS:
5800 case SIG_FXOKS:
5801 /* Read the first digit */
5802 timeout = firstdigittimeout;
5803 /* If starting a threeway call, never timeout on the first digit so someone
5804 can use flash-hook as a "hold" feature */
5805 if (p->subs[SUB_THREEWAY].owner)
5806 timeout = 999999;
5807 while (len < AST_MAX_EXTENSION-1) {
5808 /* Read digit unless it's supposed to be immediate, in which case the
5809 only answer is 's' */
5810 if (p->immediate)
5811 res = 's';
5812 else
5813 res = ast_waitfordigit(chan, timeout);
5814 timeout = 0;
5815 if (res < 0) {
5816 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5817 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5818 ast_hangup(chan);
5819 return NULL;
5820 } else if (res) {
5821 exten[len++]=res;
5822 exten[len] = '\0';
5824 if (!ast_ignore_pattern(chan->context, exten))
5825 tone_zone_play_tone(p->subs[index].dfd, -1);
5826 else
5827 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5828 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
5829 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5830 if (getforward) {
5831 /* Record this as the forwarding extension */
5832 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
5833 if (option_verbose > 2)
5834 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
5835 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5836 if (res)
5837 break;
5838 usleep(500000);
5839 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5840 sleep(1);
5841 memset(exten, 0, sizeof(exten));
5842 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5843 len = 0;
5844 getforward = 0;
5845 } else {
5846 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5847 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5848 if (!ast_strlen_zero(p->cid_num)) {
5849 if (!p->hidecallerid)
5850 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5851 else
5852 ast_set_callerid(chan, NULL, NULL, p->cid_num);
5854 if (!ast_strlen_zero(p->cid_name)) {
5855 if (!p->hidecallerid)
5856 ast_set_callerid(chan, NULL, p->cid_name, NULL);
5858 ast_setstate(chan, AST_STATE_RING);
5859 dahdi_enable_ec(p);
5860 res = ast_pbx_run(chan);
5861 if (res) {
5862 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5863 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5865 return NULL;
5867 } else {
5868 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5869 so just set the timeout to matchdigittimeout and wait some more */
5870 timeout = matchdigittimeout;
5872 } else if (res == 0) {
5873 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
5874 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5875 dahdi_wait_event(p->subs[index].dfd);
5876 ast_hangup(chan);
5877 return NULL;
5878 } else if (p->callwaiting && !strcmp(exten, "*70")) {
5879 if (option_verbose > 2)
5880 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
5881 /* Disable call waiting if enabled */
5882 p->callwaiting = 0;
5883 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5884 if (res) {
5885 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5886 chan->name, strerror(errno));
5888 len = 0;
5889 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
5890 memset(exten, 0, sizeof(exten));
5891 timeout = firstdigittimeout;
5893 } else if (!strcmp(exten,ast_pickup_ext())) {
5894 /* Scan all channels and see if there are any
5895 * ringing channels that have call groups
5896 * that equal this channels pickup group
5898 if (index == SUB_REAL) {
5899 /* Switch us from Third call to Call Wait */
5900 if (p->subs[SUB_THREEWAY].owner) {
5901 /* If you make a threeway call and the *8# a call, it should actually
5902 look like a callwait */
5903 alloc_sub(p, SUB_CALLWAIT);
5904 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
5905 unalloc_sub(p, SUB_THREEWAY);
5907 dahdi_enable_ec(p);
5908 if (ast_pickup_call(chan)) {
5909 ast_log(LOG_DEBUG, "No call pickup possible...\n");
5910 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5911 dahdi_wait_event(p->subs[index].dfd);
5913 ast_hangup(chan);
5914 return NULL;
5915 } else {
5916 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
5917 ast_hangup(chan);
5918 return NULL;
5921 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
5922 if (option_verbose > 2)
5923 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
5924 /* Disable Caller*ID if enabled */
5925 p->hidecallerid = 1;
5926 if (chan->cid.cid_num)
5927 free(chan->cid.cid_num);
5928 chan->cid.cid_num = NULL;
5929 if (chan->cid.cid_name)
5930 free(chan->cid.cid_name);
5931 chan->cid.cid_name = NULL;
5932 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5933 if (res) {
5934 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5935 chan->name, strerror(errno));
5937 len = 0;
5938 memset(exten, 0, sizeof(exten));
5939 timeout = firstdigittimeout;
5940 } else if (p->callreturn && !strcmp(exten, "*69")) {
5941 res = 0;
5942 if (!ast_strlen_zero(p->lastcid_num)) {
5943 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
5945 if (!res)
5946 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5947 break;
5948 } else if (!strcmp(exten, "*78")) {
5949 /* Do not disturb */
5950 if (option_verbose > 2)
5951 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
5952 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5953 "Channel: DAHDI/%d\r\n"
5954 "Status: enabled\r\n", p->channel);
5955 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5956 p->dnd = 1;
5957 getforward = 0;
5958 memset(exten, 0, sizeof(exten));
5959 len = 0;
5960 } else if (!strcmp(exten, "*79")) {
5961 /* Do not disturb */
5962 if (option_verbose > 2)
5963 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
5964 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5965 "Channel: DAHDI/%d\r\n"
5966 "Status: disabled\r\n", p->channel);
5967 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5968 p->dnd = 0;
5969 getforward = 0;
5970 memset(exten, 0, sizeof(exten));
5971 len = 0;
5972 } else if (p->cancallforward && !strcmp(exten, "*72")) {
5973 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5974 getforward = 1;
5975 memset(exten, 0, sizeof(exten));
5976 len = 0;
5977 } else if (p->cancallforward && !strcmp(exten, "*73")) {
5978 if (option_verbose > 2)
5979 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
5980 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5981 memset(p->call_forward, 0, sizeof(p->call_forward));
5982 getforward = 0;
5983 memset(exten, 0, sizeof(exten));
5984 len = 0;
5985 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
5986 p->subs[SUB_THREEWAY].owner &&
5987 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
5988 /* This is a three way call, the main call being a real channel,
5989 and we're parking the first call. */
5990 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
5991 if (option_verbose > 2)
5992 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
5993 break;
5994 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
5995 if (option_verbose > 2)
5996 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
5997 res = ast_db_put("blacklist", p->lastcid_num, "1");
5998 if (!res) {
5999 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6000 memset(exten, 0, sizeof(exten));
6001 len = 0;
6003 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6004 if (option_verbose > 2)
6005 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6006 /* Enable Caller*ID if enabled */
6007 p->hidecallerid = 0;
6008 if (chan->cid.cid_num)
6009 free(chan->cid.cid_num);
6010 chan->cid.cid_num = NULL;
6011 if (chan->cid.cid_name)
6012 free(chan->cid.cid_name);
6013 chan->cid.cid_name = NULL;
6014 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6015 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6016 if (res) {
6017 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6018 chan->name, strerror(errno));
6020 len = 0;
6021 memset(exten, 0, sizeof(exten));
6022 timeout = firstdigittimeout;
6023 } else if (!strcmp(exten, "*0")) {
6024 struct ast_channel *nbridge =
6025 p->subs[SUB_THREEWAY].owner;
6026 struct dahdi_pvt *pbridge = NULL;
6027 /* set up the private struct of the bridged one, if any */
6028 if (nbridge && ast_bridged_channel(nbridge))
6029 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6030 if (nbridge && pbridge &&
6031 (nbridge->tech == &dahdi_tech) &&
6032 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
6033 ISTRUNK(pbridge)) {
6034 int func = DAHDI_FLASH;
6035 /* Clear out the dial buffer */
6036 p->dop.dialstr[0] = '\0';
6037 /* flash hookswitch */
6038 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6039 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6040 nbridge->name, strerror(errno));
6042 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6043 unalloc_sub(p, SUB_THREEWAY);
6044 p->owner = p->subs[SUB_REAL].owner;
6045 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6046 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6047 ast_hangup(chan);
6048 return NULL;
6049 } else {
6050 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6051 dahdi_wait_event(p->subs[index].dfd);
6052 tone_zone_play_tone(p->subs[index].dfd, -1);
6053 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6054 unalloc_sub(p, SUB_THREEWAY);
6055 p->owner = p->subs[SUB_REAL].owner;
6056 ast_hangup(chan);
6057 return NULL;
6059 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6060 ((exten[0] != '*') || (strlen(exten) > 2))) {
6061 if (option_debug)
6062 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
6063 break;
6065 if (!timeout)
6066 timeout = gendigittimeout;
6067 if (len && !ast_ignore_pattern(chan->context, exten))
6068 tone_zone_play_tone(p->subs[index].dfd, -1);
6070 break;
6071 case SIG_FXSLS:
6072 case SIG_FXSGS:
6073 case SIG_FXSKS:
6074 #ifdef HAVE_PRI
6075 if (p->pri) {
6076 /* This is a GR-303 trunk actually. Wait for the first ring... */
6077 struct ast_frame *f;
6078 int res;
6079 time_t start;
6081 time(&start);
6082 ast_setstate(chan, AST_STATE_RING);
6083 while (time(NULL) < start + 3) {
6084 res = ast_waitfor(chan, 1000);
6085 if (res) {
6086 f = ast_read(chan);
6087 if (!f) {
6088 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6089 ast_hangup(chan);
6090 return NULL;
6091 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6092 res = 1;
6093 } else
6094 res = 0;
6095 ast_frfree(f);
6096 if (res) {
6097 ast_log(LOG_DEBUG, "Got ring!\n");
6098 res = 0;
6099 break;
6104 #endif
6105 /* check for SMDI messages */
6106 if (p->use_smdi && p->smdi_iface) {
6107 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6109 if (smdi_msg != NULL) {
6110 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6112 if (smdi_msg->type == 'B')
6113 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6114 else if (smdi_msg->type == 'N')
6115 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6117 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6118 } else {
6119 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6123 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6124 number = smdi_msg->calling_st;
6126 /* If we want caller id, we're in a prering state due to a polarity reversal
6127 * and we're set to use a polarity reversal to trigger the start of caller id,
6128 * grab the caller id and wait for ringing to start... */
6129 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6130 /* If set to use DTMF CID signalling, listen for DTMF */
6131 if (p->cid_signalling == CID_SIG_DTMF) {
6132 int i = 0;
6133 cs = NULL;
6134 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6135 "channel %s\n", chan->name);
6136 dahdi_setlinear(p->subs[index].dfd, 0);
6137 res = 2000;
6138 for (;;) {
6139 struct ast_frame *f;
6140 res = ast_waitfor(chan, res);
6141 if (res <= 0) {
6142 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6143 "Exiting simple switch\n");
6144 ast_hangup(chan);
6145 return NULL;
6147 f = ast_read(chan);
6148 if (!f)
6149 break;
6150 if (f->frametype == AST_FRAME_DTMF) {
6151 dtmfbuf[i++] = f->subclass;
6152 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6153 res = 2000;
6155 ast_frfree(f);
6156 if (chan->_state == AST_STATE_RING ||
6157 chan->_state == AST_STATE_RINGING)
6158 break; /* Got ring */
6160 dtmfbuf[i] = '\0';
6161 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6162 /* Got cid and ring. */
6163 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6164 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6165 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6166 dtmfcid, flags);
6167 /* If first byte is NULL, we have no cid */
6168 if (!ast_strlen_zero(dtmfcid))
6169 number = dtmfcid;
6170 else
6171 number = NULL;
6172 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6173 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6174 cs = callerid_new(p->cid_signalling);
6175 if (cs) {
6176 samples = 0;
6177 #if 1
6178 bump_gains(p);
6179 #endif
6180 /* Take out of linear mode for Caller*ID processing */
6181 dahdi_setlinear(p->subs[index].dfd, 0);
6183 /* First we wait and listen for the Caller*ID */
6184 for (;;) {
6185 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6186 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6187 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6188 callerid_free(cs);
6189 ast_hangup(chan);
6190 return NULL;
6192 if (i & DAHDI_IOMUX_SIGEVENT) {
6193 res = dahdi_get_event(p->subs[index].dfd);
6194 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6196 if (p->cid_signalling == CID_SIG_V23_JP) {
6197 #ifdef DAHDI_EVENT_RINGBEGIN
6198 if (res == DAHDI_EVENT_RINGBEGIN) {
6199 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6200 usleep(1);
6202 #endif
6203 } else {
6204 res = 0;
6205 break;
6207 } else if (i & DAHDI_IOMUX_READ) {
6208 res = read(p->subs[index].dfd, buf, sizeof(buf));
6209 if (res < 0) {
6210 if (errno != ELAST) {
6211 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6212 callerid_free(cs);
6213 ast_hangup(chan);
6214 return NULL;
6216 break;
6218 samples += res;
6220 if (p->cid_signalling == CID_SIG_V23_JP) {
6221 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6222 } else {
6223 res = callerid_feed(cs, buf, res, AST_LAW(p));
6226 if (res < 0) {
6227 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6228 break;
6229 } else if (res)
6230 break;
6231 else if (samples > (8000 * 10))
6232 break;
6235 if (res == 1) {
6236 callerid_get(cs, &name, &number, &flags);
6237 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6240 if (p->cid_signalling == CID_SIG_V23_JP) {
6241 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6242 usleep(1);
6243 res = 4000;
6244 } else {
6246 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6247 res = 2000;
6250 for (;;) {
6251 struct ast_frame *f;
6252 res = ast_waitfor(chan, res);
6253 if (res <= 0) {
6254 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6255 "Exiting simple switch\n");
6256 ast_hangup(chan);
6257 return NULL;
6259 if (!(f = ast_read(chan))) {
6260 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6261 ast_hangup(chan);
6262 return NULL;
6264 ast_frfree(f);
6265 if (chan->_state == AST_STATE_RING ||
6266 chan->_state == AST_STATE_RINGING)
6267 break; /* Got ring */
6270 /* We must have a ring by now, so, if configured, lets try to listen for
6271 * distinctive ringing */
6272 if (p->usedistinctiveringdetection == 1) {
6273 len = 0;
6274 distMatches = 0;
6275 /* Clear the current ring data array so we dont have old data in it. */
6276 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6277 curRingData[receivedRingT] = 0;
6278 receivedRingT = 0;
6279 counter = 0;
6280 counter1 = 0;
6281 /* Check to see if context is what it should be, if not set to be. */
6282 if (strcmp(p->context,p->defcontext) != 0) {
6283 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6284 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6287 for (;;) {
6288 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6289 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6290 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6291 callerid_free(cs);
6292 ast_hangup(chan);
6293 return NULL;
6295 if (i & DAHDI_IOMUX_SIGEVENT) {
6296 res = dahdi_get_event(p->subs[index].dfd);
6297 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6298 res = 0;
6299 /* Let us detect distinctive ring */
6301 curRingData[receivedRingT] = p->ringt;
6303 if (p->ringt < p->ringt_base/2)
6304 break;
6305 /* Increment the ringT counter so we can match it against
6306 values in chan_dahdi.conf for distinctive ring */
6307 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6308 break;
6309 } else if (i & DAHDI_IOMUX_READ) {
6310 res = read(p->subs[index].dfd, buf, sizeof(buf));
6311 if (res < 0) {
6312 if (errno != ELAST) {
6313 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6314 callerid_free(cs);
6315 ast_hangup(chan);
6316 return NULL;
6318 break;
6320 if (p->ringt)
6321 p->ringt--;
6322 if (p->ringt == 1) {
6323 res = -1;
6324 break;
6328 if (option_verbose > 2)
6329 /* this only shows up if you have n of the dring patterns filled in */
6330 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6332 for (counter = 0; counter < 3; counter++) {
6333 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6334 channel */
6335 distMatches = 0;
6336 for (counter1 = 0; counter1 < 3; counter1++) {
6337 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6338 (p->drings.ringnum[counter].ring[counter1]-10)) {
6339 distMatches++;
6342 if (distMatches == 3) {
6343 /* The ring matches, set the context to whatever is for distinctive ring.. */
6344 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6345 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6346 if (option_verbose > 2)
6347 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6348 break;
6352 /* Restore linear mode (if appropriate) for Caller*ID processing */
6353 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6354 #if 1
6355 restore_gains(p);
6356 #endif
6357 } else
6358 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6359 } else {
6360 ast_log(LOG_WARNING, "Channel %s in prering "
6361 "state, but I have nothing to do. "
6362 "Terminating simple switch, should be "
6363 "restarted by the actual ring.\n",
6364 chan->name);
6365 ast_hangup(chan);
6366 return NULL;
6368 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6369 /* FSK Bell202 callerID */
6370 cs = callerid_new(p->cid_signalling);
6371 if (cs) {
6372 #if 1
6373 bump_gains(p);
6374 #endif
6375 samples = 0;
6376 len = 0;
6377 distMatches = 0;
6378 /* Clear the current ring data array so we dont have old data in it. */
6379 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6380 curRingData[receivedRingT] = 0;
6381 receivedRingT = 0;
6382 counter = 0;
6383 counter1 = 0;
6384 /* Check to see if context is what it should be, if not set to be. */
6385 if (strcmp(p->context,p->defcontext) != 0) {
6386 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6387 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6390 /* Take out of linear mode for Caller*ID processing */
6391 dahdi_setlinear(p->subs[index].dfd, 0);
6392 for (;;) {
6393 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6394 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6395 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6396 callerid_free(cs);
6397 ast_hangup(chan);
6398 return NULL;
6400 if (i & DAHDI_IOMUX_SIGEVENT) {
6401 res = dahdi_get_event(p->subs[index].dfd);
6402 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6403 /* If we get a PR event, they hung up while processing calerid */
6404 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6405 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6406 p->polarity = POLARITY_IDLE;
6407 callerid_free(cs);
6408 ast_hangup(chan);
6409 return NULL;
6411 res = 0;
6412 /* Let us detect callerid when the telco uses distinctive ring */
6414 curRingData[receivedRingT] = p->ringt;
6416 if (p->ringt < p->ringt_base/2)
6417 break;
6418 /* Increment the ringT counter so we can match it against
6419 values in chan_dahdi.conf for distinctive ring */
6420 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6421 break;
6422 } else if (i & DAHDI_IOMUX_READ) {
6423 res = read(p->subs[index].dfd, buf, sizeof(buf));
6424 if (res < 0) {
6425 if (errno != ELAST) {
6426 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6427 callerid_free(cs);
6428 ast_hangup(chan);
6429 return NULL;
6431 break;
6433 if (p->ringt)
6434 p->ringt--;
6435 if (p->ringt == 1) {
6436 res = -1;
6437 break;
6439 samples += res;
6440 res = callerid_feed(cs, buf, res, AST_LAW(p));
6441 if (res < 0) {
6442 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6443 break;
6444 } else if (res)
6445 break;
6446 else if (samples > (8000 * 10))
6447 break;
6450 if (res == 1) {
6451 callerid_get(cs, &name, &number, &flags);
6452 if (option_debug)
6453 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6455 if (distinctiveringaftercid == 1) {
6456 /* Clear the current ring data array so we dont have old data in it. */
6457 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6458 curRingData[receivedRingT] = 0;
6460 receivedRingT = 0;
6461 if (option_verbose > 2)
6462 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6463 for (;;) {
6464 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6465 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6466 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6467 callerid_free(cs);
6468 ast_hangup(chan);
6469 return NULL;
6471 if (i & DAHDI_IOMUX_SIGEVENT) {
6472 res = dahdi_get_event(p->subs[index].dfd);
6473 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6474 res = 0;
6475 /* Let us detect callerid when the telco uses distinctive ring */
6477 curRingData[receivedRingT] = p->ringt;
6479 if (p->ringt < p->ringt_base/2)
6480 break;
6481 /* Increment the ringT counter so we can match it against
6482 values in chan_dahdi.conf for distinctive ring */
6483 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6484 break;
6485 } else if (i & DAHDI_IOMUX_READ) {
6486 res = read(p->subs[index].dfd, buf, sizeof(buf));
6487 if (res < 0) {
6488 if (errno != ELAST) {
6489 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6490 callerid_free(cs);
6491 ast_hangup(chan);
6492 return NULL;
6494 break;
6496 if (p->ringt)
6497 p->ringt--;
6498 if (p->ringt == 1) {
6499 res = -1;
6500 break;
6505 if (p->usedistinctiveringdetection == 1) {
6506 if (option_verbose > 2)
6507 /* this only shows up if you have n of the dring patterns filled in */
6508 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6510 for (counter = 0; counter < 3; counter++) {
6511 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6512 channel */
6513 if (option_verbose > 2)
6514 /* this only shows up if you have n of the dring patterns filled in */
6515 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6516 p->drings.ringnum[counter].ring[0],
6517 p->drings.ringnum[counter].ring[1],
6518 p->drings.ringnum[counter].ring[2]);
6519 distMatches = 0;
6520 for (counter1 = 0; counter1 < 3; counter1++) {
6521 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6522 (p->drings.ringnum[counter].ring[counter1]-10)) {
6523 distMatches++;
6526 if (distMatches == 3) {
6527 /* The ring matches, set the context to whatever is for distinctive ring.. */
6528 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6529 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6530 if (option_verbose > 2)
6531 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6532 break;
6536 /* Restore linear mode (if appropriate) for Caller*ID processing */
6537 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6538 #if 1
6539 restore_gains(p);
6540 #endif
6541 if (res < 0) {
6542 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6544 } else
6545 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6547 else
6548 cs = NULL;
6550 if (number)
6551 ast_shrink_phone_number(number);
6552 ast_set_callerid(chan, number, name, number);
6554 if (smdi_msg)
6555 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6557 if (cs)
6558 callerid_free(cs);
6560 ast_setstate(chan, AST_STATE_RING);
6561 chan->rings = 1;
6562 p->ringt = p->ringt_base;
6563 res = ast_pbx_run(chan);
6564 if (res) {
6565 ast_hangup(chan);
6566 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6568 return NULL;
6569 default:
6570 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6571 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6572 if (res < 0)
6573 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6575 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6576 if (res < 0)
6577 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6578 ast_hangup(chan);
6579 return NULL;
6582 /* destroy a DAHDI channel, identified by its number */
6583 static int dahdi_destroy_channel_bynum(int channel)
6585 struct dahdi_pvt *tmp = NULL;
6586 struct dahdi_pvt *prev = NULL;
6588 tmp = iflist;
6589 while (tmp) {
6590 if (tmp->channel == channel) {
6591 destroy_channel(prev, tmp, 1);
6592 return RESULT_SUCCESS;
6594 prev = tmp;
6595 tmp = tmp->next;
6597 return RESULT_FAILURE;
6600 static int handle_init_event(struct dahdi_pvt *i, int event)
6602 int res;
6603 pthread_t threadid;
6604 pthread_attr_t attr;
6605 struct ast_channel *chan;
6606 pthread_attr_init(&attr);
6607 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6608 /* Handle an event on a given channel for the monitor thread. */
6609 switch (event) {
6610 case DAHDI_EVENT_NONE:
6611 case DAHDI_EVENT_BITSCHANGED:
6612 break;
6613 case DAHDI_EVENT_WINKFLASH:
6614 case DAHDI_EVENT_RINGOFFHOOK:
6615 if (i->inalarm) break;
6616 if (i->radio) break;
6617 /* Got a ring/answer. What kind of channel are we? */
6618 switch (i->sig) {
6619 case SIG_FXOLS:
6620 case SIG_FXOGS:
6621 case SIG_FXOKS:
6622 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6623 if (res && (errno == EBUSY))
6624 break;
6625 if (i->cidspill) {
6626 /* Cancel VMWI spill */
6627 free(i->cidspill);
6628 i->cidspill = NULL;
6630 if (i->immediate) {
6631 dahdi_enable_ec(i);
6632 /* The channel is immediately up. Start right away */
6633 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6634 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6635 if (!chan) {
6636 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6637 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6638 if (res < 0)
6639 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6641 } else {
6642 /* Check for callerid, digits, etc */
6643 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6644 if (chan) {
6645 if (has_voicemail(i))
6646 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6647 else
6648 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6649 if (res < 0)
6650 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
6651 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6652 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6653 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6654 if (res < 0)
6655 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6656 ast_hangup(chan);
6658 } else
6659 ast_log(LOG_WARNING, "Unable to create channel\n");
6661 break;
6662 case SIG_FXSLS:
6663 case SIG_FXSGS:
6664 case SIG_FXSKS:
6665 i->ringt = i->ringt_base;
6666 /* Fall through */
6667 case SIG_EMWINK:
6668 case SIG_FEATD:
6669 case SIG_FEATDMF:
6670 case SIG_FEATDMF_TA:
6671 case SIG_E911:
6672 case SIG_FGC_CAMA:
6673 case SIG_FGC_CAMAMF:
6674 case SIG_FEATB:
6675 case SIG_EM:
6676 case SIG_EM_E1:
6677 case SIG_SFWINK:
6678 case SIG_SF_FEATD:
6679 case SIG_SF_FEATDMF:
6680 case SIG_SF_FEATB:
6681 case SIG_SF:
6682 /* Check for callerid, digits, etc */
6683 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
6684 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6685 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6686 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6687 if (res < 0)
6688 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6689 ast_hangup(chan);
6690 } else if (!chan) {
6691 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
6693 break;
6694 default:
6695 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6696 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6697 if (res < 0)
6698 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6699 return -1;
6701 break;
6702 case DAHDI_EVENT_NOALARM:
6703 i->inalarm = 0;
6704 if (!i->unknown_alarm) {
6705 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
6706 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6707 "Channel: %d\r\n", i->channel);
6708 } else {
6709 i->unknown_alarm = 0;
6711 break;
6712 case DAHDI_EVENT_ALARM:
6713 i->inalarm = 1;
6714 res = get_alarms(i);
6715 do {
6716 const char *alarm_str = alarm2str(res);
6718 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
6719 * doesn't know what to do with it. Don't confuse users with log messages. */
6720 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
6721 i->unknown_alarm = 1;
6722 break;
6723 } else {
6724 i->unknown_alarm = 0;
6727 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm_str);
6728 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
6729 "Alarm: %s\r\n"
6730 "Channel: %d\r\n",
6731 alarm_str, i->channel);
6732 } while (0);
6733 /* fall thru intentionally */
6734 case DAHDI_EVENT_ONHOOK:
6735 if (i->radio)
6736 break;
6737 /* Back on hook. Hang up. */
6738 switch (i->sig) {
6739 case SIG_FXOLS:
6740 case SIG_FXOGS:
6741 case SIG_FEATD:
6742 case SIG_FEATDMF:
6743 case SIG_FEATDMF_TA:
6744 case SIG_E911:
6745 case SIG_FGC_CAMA:
6746 case SIG_FGC_CAMAMF:
6747 case SIG_FEATB:
6748 case SIG_EM:
6749 case SIG_EM_E1:
6750 case SIG_EMWINK:
6751 case SIG_SF_FEATD:
6752 case SIG_SF_FEATDMF:
6753 case SIG_SF_FEATB:
6754 case SIG_SF:
6755 case SIG_SFWINK:
6756 case SIG_FXSLS:
6757 case SIG_FXSGS:
6758 case SIG_FXSKS:
6759 case SIG_GR303FXSKS:
6760 dahdi_disable_ec(i);
6761 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6762 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6763 break;
6764 case SIG_GR303FXOKS:
6765 case SIG_FXOKS:
6766 dahdi_disable_ec(i);
6767 /* Diddle the battery for the zhone */
6768 #ifdef ZHONE_HACK
6769 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6770 usleep(1);
6771 #endif
6772 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6773 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6774 break;
6775 case SIG_PRI:
6776 dahdi_disable_ec(i);
6777 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6778 break;
6779 default:
6780 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6781 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6782 return -1;
6784 break;
6785 case DAHDI_EVENT_POLARITY:
6786 switch (i->sig) {
6787 case SIG_FXSLS:
6788 case SIG_FXSKS:
6789 case SIG_FXSGS:
6790 /* We have already got a PR before the channel was
6791 created, but it wasn't handled. We need polarity
6792 to be REV for remote hangup detection to work.
6793 At least in Spain */
6794 if (i->hanguponpolarityswitch)
6795 i->polarity = POLARITY_REV;
6797 if (i->cid_start == CID_START_POLARITY) {
6798 i->polarity = POLARITY_REV;
6799 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
6800 "CID detection on channel %d\n",
6801 i->channel);
6802 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
6803 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6804 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6807 break;
6808 default:
6809 ast_log(LOG_WARNING, "handle_init_event detected "
6810 "polarity reversal on non-FXO (SIG_FXS) "
6811 "interface %d\n", i->channel);
6813 break;
6814 case DAHDI_EVENT_REMOVED: /* destroy channel */
6815 ast_log(LOG_NOTICE,
6816 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6817 i->channel);
6818 dahdi_destroy_channel_bynum(i->channel);
6819 break;
6821 pthread_attr_destroy(&attr);
6822 return 0;
6825 static void *do_monitor(void *data)
6827 int count, res, res2, spoint, pollres=0;
6828 struct dahdi_pvt *i;
6829 struct dahdi_pvt *last = NULL;
6830 time_t thispass = 0, lastpass = 0;
6831 int found;
6832 char buf[1024];
6833 struct pollfd *pfds=NULL;
6834 int lastalloc = -1;
6835 /* This thread monitors all the frame relay interfaces which are not yet in use
6836 (and thus do not have a separate thread) indefinitely */
6837 /* From here on out, we die whenever asked */
6838 #if 0
6839 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
6840 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
6841 return NULL;
6843 ast_log(LOG_DEBUG, "Monitor starting...\n");
6844 #endif
6845 for (;;) {
6846 /* Lock the interface list */
6847 ast_mutex_lock(&iflock);
6848 if (!pfds || (lastalloc != ifcount)) {
6849 if (pfds) {
6850 free(pfds);
6851 pfds = NULL;
6853 if (ifcount) {
6854 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
6855 ast_mutex_unlock(&iflock);
6856 return NULL;
6859 lastalloc = ifcount;
6861 /* Build the stuff we're going to poll on, that is the socket of every
6862 dahdi_pvt that does not have an associated owner channel */
6863 count = 0;
6864 i = iflist;
6865 while (i) {
6866 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
6867 if (!i->owner && !i->subs[SUB_REAL].owner) {
6868 /* This needs to be watched, as it lacks an owner */
6869 pfds[count].fd = i->subs[SUB_REAL].dfd;
6870 pfds[count].events = POLLPRI;
6871 pfds[count].revents = 0;
6872 /* Message waiting or r2 channels also get watched for reading */
6873 if (i->cidspill)
6874 pfds[count].events |= POLLIN;
6875 count++;
6878 i = i->next;
6880 /* Okay, now that we know what to do, release the interface lock */
6881 ast_mutex_unlock(&iflock);
6883 pthread_testcancel();
6884 /* Wait at least a second for something to happen */
6885 res = poll(pfds, count, 1000);
6886 pthread_testcancel();
6887 /* Okay, poll has finished. Let's see what happened. */
6888 if (res < 0) {
6889 if ((errno != EAGAIN) && (errno != EINTR))
6890 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
6891 continue;
6893 /* Alright, lock the interface list again, and let's look and see what has
6894 happened */
6895 ast_mutex_lock(&iflock);
6896 found = 0;
6897 spoint = 0;
6898 lastpass = thispass;
6899 thispass = time(NULL);
6900 i = iflist;
6901 while (i) {
6902 if (thispass != lastpass) {
6903 if (!found && ((i == last) || ((i == iflist) && !last))) {
6904 last = i;
6905 if (last) {
6906 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
6907 (last->sig & __DAHDI_SIG_FXO)) {
6908 res = ast_app_has_voicemail(last->mailbox, NULL);
6909 if (last->msgstate != res) {
6910 int x;
6911 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
6912 x = DAHDI_FLUSH_BOTH;
6913 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
6914 if (res2)
6915 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
6916 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
6917 /* Turn on on hook transfer for 4 seconds */
6918 x = 4000;
6919 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
6920 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
6921 last->cidpos = 0;
6922 last->msgstate = res;
6923 last->onhooktime = thispass;
6925 found ++;
6928 last = last->next;
6932 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
6933 if (i->radio && !i->owner)
6935 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
6936 if (res)
6938 if (option_debug)
6939 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
6940 /* Don't hold iflock while handling init events */
6941 ast_mutex_unlock(&iflock);
6942 handle_init_event(i, res);
6943 ast_mutex_lock(&iflock);
6945 i = i->next;
6946 continue;
6948 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
6949 if (pollres & POLLIN) {
6950 if (i->owner || i->subs[SUB_REAL].owner) {
6951 #ifdef HAVE_PRI
6952 if (!i->pri)
6953 #endif
6954 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
6955 i = i->next;
6956 continue;
6958 if (!i->cidspill) {
6959 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
6960 i = i->next;
6961 continue;
6963 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
6964 if (res > 0) {
6965 /* We read some number of bytes. Write an equal amount of data */
6966 if (res > i->cidlen - i->cidpos)
6967 res = i->cidlen - i->cidpos;
6968 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
6969 if (res2 > 0) {
6970 i->cidpos += res2;
6971 if (i->cidpos >= i->cidlen) {
6972 free(i->cidspill);
6973 i->cidspill = 0;
6974 i->cidpos = 0;
6975 i->cidlen = 0;
6977 } else {
6978 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
6979 i->msgstate = -1;
6981 } else {
6982 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
6985 if (pollres & POLLPRI) {
6986 if (i->owner || i->subs[SUB_REAL].owner) {
6987 #ifdef HAVE_PRI
6988 if (!i->pri)
6989 #endif
6990 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
6991 i = i->next;
6992 continue;
6994 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
6995 if (option_debug)
6996 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
6997 /* Don't hold iflock while handling init events */
6998 ast_mutex_unlock(&iflock);
6999 handle_init_event(i, res);
7000 ast_mutex_lock(&iflock);
7003 i=i->next;
7005 ast_mutex_unlock(&iflock);
7007 /* Never reached */
7008 return NULL;
7012 static int restart_monitor(void)
7014 pthread_attr_t attr;
7015 pthread_attr_init(&attr);
7016 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7017 /* If we're supposed to be stopped -- stay stopped */
7018 if (monitor_thread == AST_PTHREADT_STOP)
7019 return 0;
7020 ast_mutex_lock(&monlock);
7021 if (monitor_thread == pthread_self()) {
7022 ast_mutex_unlock(&monlock);
7023 ast_log(LOG_WARNING, "Cannot kill myself\n");
7024 return -1;
7026 if (monitor_thread != AST_PTHREADT_NULL) {
7027 /* Wake up the thread */
7028 pthread_kill(monitor_thread, SIGURG);
7029 } else {
7030 /* Start a new monitor */
7031 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7032 ast_mutex_unlock(&monlock);
7033 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7034 pthread_attr_destroy(&attr);
7035 return -1;
7038 ast_mutex_unlock(&monlock);
7039 pthread_attr_destroy(&attr);
7040 return 0;
7043 #ifdef HAVE_PRI
7044 static int pri_resolve_span(int *span, int channel, int offset, DAHDI_SPANINFO *si)
7046 int x;
7047 int trunkgroup;
7048 /* Get appropriate trunk group if there is one */
7049 trunkgroup = pris[*span].mastertrunkgroup;
7050 if (trunkgroup) {
7051 /* Select a specific trunk group */
7052 for (x = 0; x < NUM_SPANS; x++) {
7053 if (pris[x].trunkgroup == trunkgroup) {
7054 *span = x;
7055 return 0;
7058 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7059 *span = -1;
7060 } else {
7061 if (pris[*span].trunkgroup) {
7062 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7063 *span = -1;
7064 } else if (pris[*span].mastertrunkgroup) {
7065 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7066 *span = -1;
7067 } else {
7068 if (si->totalchans == 31) { /* if it's an E1 */
7069 pris[*span].dchannels[0] = 16 + offset;
7070 } else {
7071 pris[*span].dchannels[0] = 24 + offset;
7073 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7074 pris[*span].offset = offset;
7075 pris[*span].span = *span + 1;
7078 return 0;
7081 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7083 DAHDI_SPANINFO si;
7084 DAHDI_PARAMS p;
7085 int fd;
7086 int span;
7087 int ospan=0;
7088 int x,y;
7089 for (x = 0; x < NUM_SPANS; x++) {
7090 if (pris[x].trunkgroup == trunkgroup) {
7091 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7092 return -1;
7095 for (y = 0; y < NUM_DCHANS; y++) {
7096 if (!channels[y])
7097 break;
7098 memset(&si, 0, sizeof(si));
7099 memset(&p, 0, sizeof(p));
7100 #ifdef HAVE_ZAPTEL
7101 fd = open("/dev/zap/channel", O_RDWR);
7102 #else
7103 fd = open("/dev/dahdi/channel", O_RDWR);
7104 #endif
7105 if (fd < 0) {
7106 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7107 return -1;
7109 x = channels[y];
7110 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7111 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7112 dahdi_close(fd);
7113 return -1;
7115 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7116 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7117 return -1;
7119 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7120 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7121 dahdi_close(fd);
7122 return -1;
7124 span = p.spanno - 1;
7125 if (pris[span].trunkgroup) {
7126 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7127 dahdi_close(fd);
7128 return -1;
7130 if (pris[span].pvts[0]) {
7131 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7132 dahdi_close(fd);
7133 return -1;
7135 if (!y) {
7136 pris[span].trunkgroup = trunkgroup;
7137 pris[span].offset = channels[y] - p.chanpos;
7138 ospan = span;
7140 pris[ospan].dchannels[y] = channels[y];
7141 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7142 pris[span].span = span + 1;
7143 dahdi_close(fd);
7145 return 0;
7148 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7150 if (pris[span].mastertrunkgroup) {
7151 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);
7152 return -1;
7154 pris[span].mastertrunkgroup = trunkgroup;
7155 pris[span].prilogicalspan = logicalspan;
7156 return 0;
7159 #endif
7161 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7163 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7164 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7165 char fn[80];
7166 #if 1
7167 DAHDI_BUFFERINFO bi;
7168 #endif
7169 DAHDI_SPANINFO si;
7170 int res;
7171 int span=0;
7172 int here = 0;
7173 int x;
7174 struct dahdi_pvt **wlist;
7175 struct dahdi_pvt **wend;
7176 DAHDI_PARAMS p;
7178 wlist = &iflist;
7179 wend = &ifend;
7181 #ifdef HAVE_PRI
7182 if (pri) {
7183 wlist = &pri->crvs;
7184 wend = &pri->crvend;
7186 #endif
7188 tmp2 = *wlist;
7189 prev = NULL;
7191 while (tmp2) {
7192 if (!tmp2->destroy) {
7193 if (tmp2->channel == channel) {
7194 tmp = tmp2;
7195 here = 1;
7196 break;
7198 if (tmp2->channel > channel) {
7199 break;
7202 prev = tmp2;
7203 tmp2 = tmp2->next;
7206 if (!here && !reloading) {
7207 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7208 destroy_dahdi_pvt(&tmp);
7209 return NULL;
7211 ast_mutex_init(&tmp->lock);
7212 ifcount++;
7213 for (x = 0; x < 3; x++)
7214 tmp->subs[x].dfd = -1;
7215 tmp->channel = channel;
7218 if (tmp) {
7219 int chan_sig = conf->chan.sig;
7220 if (!here) {
7221 if ((channel != CHAN_PSEUDO) && !pri) {
7222 snprintf(fn, sizeof(fn), "%d", channel);
7223 /* Open non-blocking */
7224 if (!here)
7225 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7226 /* Allocate a DAHDI structure */
7227 if (tmp->subs[SUB_REAL].dfd < 0) {
7228 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);
7229 destroy_dahdi_pvt(&tmp);
7230 return NULL;
7232 memset(&p, 0, sizeof(p));
7233 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7234 if (res < 0) {
7235 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7236 destroy_dahdi_pvt(&tmp);
7237 return NULL;
7239 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7240 ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
7241 destroy_dahdi_pvt(&tmp);
7242 return NULL;
7244 tmp->law = p.curlaw;
7245 tmp->span = p.spanno;
7246 span = p.spanno - 1;
7247 } else {
7248 if (channel == CHAN_PSEUDO)
7249 chan_sig = 0;
7250 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7251 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7252 return NULL;
7255 #ifdef HAVE_PRI
7256 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7257 int offset;
7258 int myswitchtype;
7259 int matchesdchan;
7260 int x,y;
7261 offset = 0;
7262 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7263 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7264 destroy_dahdi_pvt(&tmp);
7265 return NULL;
7267 if (span >= NUM_SPANS) {
7268 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7269 destroy_dahdi_pvt(&tmp);
7270 return NULL;
7271 } else {
7272 si.spanno = 0;
7273 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7274 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7275 destroy_dahdi_pvt(&tmp);
7276 return NULL;
7278 /* Store the logical span first based upon the real span */
7279 tmp->logicalspan = pris[span].prilogicalspan;
7280 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7281 if (span < 0) {
7282 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7283 destroy_dahdi_pvt(&tmp);
7284 return NULL;
7286 if (chan_sig == SIG_PRI)
7287 myswitchtype = conf->pri.switchtype;
7288 else
7289 myswitchtype = PRI_SWITCH_GR303_TMC;
7290 /* Make sure this isn't a d-channel */
7291 matchesdchan=0;
7292 for (x = 0; x < NUM_SPANS; x++) {
7293 for (y = 0; y < NUM_DCHANS; y++) {
7294 if (pris[x].dchannels[y] == tmp->channel) {
7295 matchesdchan = 1;
7296 break;
7300 offset = p.chanpos;
7301 if (!matchesdchan) {
7302 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7303 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7304 destroy_dahdi_pvt(&tmp);
7305 return NULL;
7307 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7308 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7309 destroy_dahdi_pvt(&tmp);
7310 return NULL;
7312 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7313 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7314 destroy_dahdi_pvt(&tmp);
7315 return NULL;
7317 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7318 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7319 destroy_dahdi_pvt(&tmp);
7320 return NULL;
7322 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7323 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7324 destroy_dahdi_pvt(&tmp);
7325 return NULL;
7327 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7328 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7329 destroy_dahdi_pvt(&tmp);
7330 return NULL;
7332 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7333 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7334 destroy_dahdi_pvt(&tmp);
7335 return NULL;
7337 if (pris[span].numchans >= MAX_CHANNELS) {
7338 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7339 pris[span].trunkgroup);
7340 destroy_dahdi_pvt(&tmp);
7341 return NULL;
7343 pris[span].nodetype = conf->pri.nodetype;
7344 pris[span].switchtype = myswitchtype;
7345 pris[span].nsf = conf->pri.nsf;
7346 pris[span].dialplan = conf->pri.dialplan;
7347 pris[span].localdialplan = conf->pri.localdialplan;
7348 pris[span].pvts[pris[span].numchans++] = tmp;
7349 pris[span].minunused = conf->pri.minunused;
7350 pris[span].minidle = conf->pri.minidle;
7351 pris[span].overlapdial = conf->pri.overlapdial;
7352 #ifdef HAVE_PRI_INBANDRELEASE
7353 pris[span].inbandrelease = conf->pri.inbandrelease;
7354 #endif
7355 pris[span].facilityenable = conf->pri.facilityenable;
7356 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7357 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7358 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7359 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7360 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7361 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7362 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7363 pris[span].resetinterval = conf->pri.resetinterval;
7365 tmp->pri = &pris[span];
7366 tmp->prioffset = offset;
7367 tmp->call = NULL;
7368 } else {
7369 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7370 destroy_dahdi_pvt(&tmp);
7371 return NULL;
7374 } else {
7375 tmp->prioffset = 0;
7377 #endif
7378 } else {
7379 chan_sig = tmp->sig;
7380 memset(&p, 0, sizeof(p));
7381 if (tmp->subs[SUB_REAL].dfd > -1)
7382 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7384 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7385 switch (chan_sig) {
7386 case SIG_FXSKS:
7387 case SIG_FXSLS:
7388 case SIG_EM:
7389 case SIG_EM_E1:
7390 case SIG_EMWINK:
7391 case SIG_FEATD:
7392 case SIG_FEATDMF:
7393 case SIG_FEATDMF_TA:
7394 case SIG_FEATB:
7395 case SIG_E911:
7396 case SIG_SF:
7397 case SIG_SFWINK:
7398 case SIG_FGC_CAMA:
7399 case SIG_FGC_CAMAMF:
7400 case SIG_SF_FEATD:
7401 case SIG_SF_FEATDMF:
7402 case SIG_SF_FEATB:
7403 p.starttime = 250;
7404 break;
7407 if (tmp->radio) {
7408 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7409 p.channo = channel;
7410 p.rxwinktime = 1;
7411 p.rxflashtime = 1;
7412 p.starttime = 1;
7413 p.debouncetime = 5;
7415 if (!tmp->radio) {
7416 p.channo = channel;
7417 /* Override timing settings based on config file */
7418 if (conf->timing.prewinktime >= 0)
7419 p.prewinktime = conf->timing.prewinktime;
7420 if (conf->timing.preflashtime >= 0)
7421 p.preflashtime = conf->timing.preflashtime;
7422 if (conf->timing.winktime >= 0)
7423 p.winktime = conf->timing.winktime;
7424 if (conf->timing.flashtime >= 0)
7425 p.flashtime = conf->timing.flashtime;
7426 if (conf->timing.starttime >= 0)
7427 p.starttime = conf->timing.starttime;
7428 if (conf->timing.rxwinktime >= 0)
7429 p.rxwinktime = conf->timing.rxwinktime;
7430 if (conf->timing.rxflashtime >= 0)
7431 p.rxflashtime = conf->timing.rxflashtime;
7432 if (conf->timing.debouncetime >= 0)
7433 p.debouncetime = conf->timing.debouncetime;
7436 /* dont set parms on a pseudo-channel (or CRV) */
7437 if (tmp->subs[SUB_REAL].dfd >= 0)
7439 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7440 if (res < 0) {
7441 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7442 destroy_dahdi_pvt(&tmp);
7443 return NULL;
7446 #if 1
7447 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7448 memset(&bi, 0, sizeof(bi));
7449 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7450 if (!res) {
7451 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7452 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7453 bi.numbufs = numbufs;
7454 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7455 if (res < 0) {
7456 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7458 } else
7459 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7461 #endif
7462 tmp->immediate = conf->chan.immediate;
7463 tmp->transfertobusy = conf->chan.transfertobusy;
7464 tmp->sig = chan_sig;
7465 tmp->outsigmod = conf->chan.outsigmod;
7466 tmp->ringt_base = ringt_base;
7467 tmp->firstradio = 0;
7468 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7469 tmp->permcallwaiting = conf->chan.callwaiting;
7470 else
7471 tmp->permcallwaiting = 0;
7472 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7473 tmp->destroy = 0;
7474 tmp->drings = drings;
7475 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7476 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7477 tmp->threewaycalling = conf->chan.threewaycalling;
7478 tmp->adsi = conf->chan.adsi;
7479 tmp->use_smdi = conf->chan.use_smdi;
7480 tmp->permhidecallerid = conf->chan.hidecallerid;
7481 tmp->callreturn = conf->chan.callreturn;
7482 tmp->echocancel = conf->chan.echocancel;
7483 tmp->echotraining = conf->chan.echotraining;
7484 tmp->pulse = conf->chan.pulse;
7485 if (tmp->echocancel)
7486 tmp->echocanbridged = conf->chan.echocanbridged;
7487 else {
7488 if (conf->chan.echocanbridged)
7489 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7490 tmp->echocanbridged = 0;
7492 tmp->busydetect = conf->chan.busydetect;
7493 tmp->busycount = conf->chan.busycount;
7494 tmp->busy_tonelength = conf->chan.busy_tonelength;
7495 tmp->busy_quietlength = conf->chan.busy_quietlength;
7496 tmp->callprogress = conf->chan.callprogress;
7497 tmp->cancallforward = conf->chan.cancallforward;
7498 tmp->dtmfrelax = conf->chan.dtmfrelax;
7499 tmp->callwaiting = tmp->permcallwaiting;
7500 tmp->hidecallerid = tmp->permhidecallerid;
7501 tmp->channel = channel;
7502 tmp->stripmsd = conf->chan.stripmsd;
7503 tmp->use_callerid = conf->chan.use_callerid;
7504 tmp->cid_signalling = conf->chan.cid_signalling;
7505 tmp->cid_start = conf->chan.cid_start;
7506 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7507 tmp->restrictcid = conf->chan.restrictcid;
7508 tmp->use_callingpres = conf->chan.use_callingpres;
7509 tmp->priindication_oob = conf->chan.priindication_oob;
7510 tmp->priexclusive = conf->chan.priexclusive;
7511 if (tmp->usedistinctiveringdetection) {
7512 if (!tmp->use_callerid) {
7513 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7514 tmp->use_callerid = 1;
7518 if (tmp->cid_signalling == CID_SIG_SMDI) {
7519 if (!tmp->use_smdi) {
7520 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7521 tmp->use_smdi = 1;
7524 if (tmp->use_smdi) {
7525 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7526 if (!(tmp->smdi_iface)) {
7527 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7528 tmp->use_smdi = 0;
7532 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7533 tmp->amaflags = conf->chan.amaflags;
7534 if (!here) {
7535 tmp->confno = -1;
7536 tmp->propconfno = -1;
7538 tmp->canpark = conf->chan.canpark;
7539 tmp->transfer = conf->chan.transfer;
7540 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7541 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7542 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7543 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7544 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7545 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7546 tmp->cid_ton = 0;
7547 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7548 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7549 tmp->msgstate = -1;
7550 tmp->group = conf->chan.group;
7551 tmp->callgroup = conf->chan.callgroup;
7552 tmp->pickupgroup= conf->chan.pickupgroup;
7553 tmp->rxgain = conf->chan.rxgain;
7554 tmp->txgain = conf->chan.txgain;
7555 tmp->tonezone = conf->chan.tonezone;
7556 tmp->onhooktime = time(NULL);
7557 if (tmp->subs[SUB_REAL].dfd > -1) {
7558 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7559 if (tmp->dsp)
7560 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7561 update_conf(tmp);
7562 if (!here) {
7563 if (chan_sig != SIG_PRI)
7564 /* Hang it up to be sure it's good */
7565 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7567 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7568 #ifdef HAVE_PRI
7569 /* the dchannel is down so put the channel in alarm */
7570 if (tmp->pri && !pri_is_up(tmp->pri))
7571 tmp->inalarm = 1;
7572 else
7573 tmp->inalarm = 0;
7574 #endif
7575 memset(&si, 0, sizeof(si));
7576 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7577 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7578 destroy_dahdi_pvt(&tmp);
7579 return NULL;
7581 if (si.alarms) tmp->inalarm = 1;
7584 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
7585 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
7586 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
7587 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
7590 if (tmp && !here) {
7591 /* nothing on the iflist */
7592 if (!*wlist) {
7593 *wlist = tmp;
7594 tmp->prev = NULL;
7595 tmp->next = NULL;
7596 *wend = tmp;
7597 } else {
7598 /* at least one member on the iflist */
7599 struct dahdi_pvt *working = *wlist;
7601 /* check if we maybe have to put it on the begining */
7602 if (working->channel > tmp->channel) {
7603 tmp->next = *wlist;
7604 tmp->prev = NULL;
7605 (*wlist)->prev = tmp;
7606 *wlist = tmp;
7607 } else {
7608 /* go through all the members and put the member in the right place */
7609 while (working) {
7610 /* in the middle */
7611 if (working->next) {
7612 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
7613 tmp->next = working->next;
7614 tmp->prev = working;
7615 working->next->prev = tmp;
7616 working->next = tmp;
7617 break;
7619 } else {
7620 /* the last */
7621 if (working->channel < tmp->channel) {
7622 working->next = tmp;
7623 tmp->next = NULL;
7624 tmp->prev = working;
7625 *wend = tmp;
7626 break;
7629 working = working->next;
7634 return tmp;
7637 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
7639 int res;
7640 DAHDI_PARAMS par;
7642 /* First, check group matching */
7643 if (groupmatch) {
7644 if ((p->group & groupmatch) != groupmatch)
7645 return 0;
7646 *groupmatched = 1;
7648 /* Check to see if we have a channel match */
7649 if (channelmatch != -1) {
7650 if (p->channel != channelmatch)
7651 return 0;
7652 *channelmatched = 1;
7654 /* We're at least busy at this point */
7655 if (busy) {
7656 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
7657 *busy = 1;
7659 /* If do not disturb, definitely not */
7660 if (p->dnd)
7661 return 0;
7662 /* If guard time, definitely not */
7663 if (p->guardtime && (time(NULL) < p->guardtime))
7664 return 0;
7666 /* If no owner definitely available */
7667 if (!p->owner) {
7668 #ifdef HAVE_PRI
7669 /* Trust PRI */
7670 if (p->pri) {
7671 if (p->resetting || p->call)
7672 return 0;
7673 else
7674 return 1;
7676 #endif
7677 if (!(p->radio || (p->oprmode < 0)))
7679 if (!p->sig || (p->sig == SIG_FXSLS))
7680 return 1;
7681 /* Check hook state */
7682 if (p->subs[SUB_REAL].dfd > -1)
7683 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
7684 else {
7685 /* Assume not off hook on CVRS */
7686 res = 0;
7687 par.rxisoffhook = 0;
7689 if (res) {
7690 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
7691 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
7692 /* When "onhook" that means no battery on the line, and thus
7693 it is out of service..., if it's on a TDM card... If it's a channel
7694 bank, there is no telling... */
7695 if (par.rxbits > -1)
7696 return 1;
7697 if (par.rxisoffhook)
7698 return 1;
7699 else
7700 #ifdef DAHDI_CHECK_HOOKSTATE
7701 return 0;
7702 #else
7703 return 1;
7704 #endif
7705 } else if (par.rxisoffhook) {
7706 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
7707 /* Not available when the other end is off hook */
7708 return 0;
7711 return 1;
7714 /* If it's not an FXO, forget about call wait */
7715 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
7716 return 0;
7718 if (!p->callwaiting) {
7719 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7720 return 0;
7723 if (p->subs[SUB_CALLWAIT].dfd > -1) {
7724 /* If there is already a call waiting call, then we can't take a second one */
7725 return 0;
7728 if ((p->owner->_state != AST_STATE_UP) &&
7729 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
7730 /* If the current call is not up, then don't allow the call */
7731 return 0;
7733 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
7734 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7735 return 0;
7737 /* We're cool */
7738 return 1;
7741 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
7743 struct dahdi_pvt *p;
7744 DAHDI_BUFFERINFO bi;
7745 int res;
7747 if ((p = ast_malloc(sizeof(*p)))) {
7748 memcpy(p, src, sizeof(struct dahdi_pvt));
7749 ast_mutex_init(&p->lock);
7750 #ifdef HAVE_ZAPTEL
7751 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
7752 #else
7753 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
7754 #endif
7755 /* Allocate a DAHDI structure */
7756 if (p->subs[SUB_REAL].dfd < 0) {
7757 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
7758 destroy_dahdi_pvt(&p);
7759 return NULL;
7761 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7762 if (!res) {
7763 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7764 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7765 bi.numbufs = numbufs;
7766 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7767 if (res < 0) {
7768 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
7770 } else
7771 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
7773 p->destroy = 1;
7774 p->next = iflist;
7775 p->prev = NULL;
7776 iflist = p;
7777 if (iflist->next)
7778 iflist->next->prev = p;
7779 return p;
7783 #ifdef HAVE_PRI
7784 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
7786 int x;
7787 if (backwards)
7788 x = pri->numchans;
7789 else
7790 x = 0;
7791 for (;;) {
7792 if (backwards && (x < 0))
7793 break;
7794 if (!backwards && (x >= pri->numchans))
7795 break;
7796 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7797 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7798 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7799 return x;
7801 if (backwards)
7802 x--;
7803 else
7804 x++;
7806 return -1;
7808 #endif
7810 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
7812 ast_group_t groupmatch = 0;
7813 int channelmatch = -1;
7814 int roundrobin = 0;
7815 int callwait = 0;
7816 int busy = 0;
7817 struct dahdi_pvt *p;
7818 struct ast_channel *tmp = NULL;
7819 char *dest=NULL;
7820 int x;
7821 char *s;
7822 char opt=0;
7823 int res=0, y=0;
7824 int backwards = 0;
7825 #ifdef HAVE_PRI
7826 int crv;
7827 int bearer = -1;
7828 int trunkgroup;
7829 struct dahdi_pri *pri=NULL;
7830 #endif
7831 struct dahdi_pvt *exit, *start, *end;
7832 ast_mutex_t *lock;
7833 int channelmatched = 0;
7834 int groupmatched = 0;
7836 /* Assume we're locking the iflock */
7837 lock = &iflock;
7838 start = iflist;
7839 end = ifend;
7840 if (data) {
7841 dest = ast_strdupa((char *)data);
7842 } else {
7843 ast_log(LOG_WARNING, "Channel requested with no data\n");
7844 return NULL;
7846 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
7847 /* Retrieve the group number */
7848 char *stringp=NULL;
7849 stringp=dest + 1;
7850 s = strsep(&stringp, "/");
7851 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7852 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
7853 return NULL;
7855 groupmatch = ((ast_group_t) 1 << x);
7856 if (toupper(dest[0]) == 'G') {
7857 if (dest[0] == 'G') {
7858 backwards = 1;
7859 p = ifend;
7860 } else
7861 p = iflist;
7862 } else {
7863 if (dest[0] == 'R') {
7864 backwards = 1;
7865 p = round_robin[x]?round_robin[x]->prev:ifend;
7866 if (!p)
7867 p = ifend;
7868 } else {
7869 p = round_robin[x]?round_robin[x]->next:iflist;
7870 if (!p)
7871 p = iflist;
7873 roundrobin = 1;
7875 } else {
7876 char *stringp=NULL;
7877 stringp=dest;
7878 s = strsep(&stringp, "/");
7879 p = iflist;
7880 if (!strcasecmp(s, "pseudo")) {
7881 /* Special case for pseudo */
7882 x = CHAN_PSEUDO;
7883 channelmatch = x;
7885 #ifdef HAVE_PRI
7886 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
7887 if ((trunkgroup < 1) || (crv < 1)) {
7888 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
7889 return NULL;
7891 res--;
7892 for (x = 0; x < NUM_SPANS; x++) {
7893 if (pris[x].trunkgroup == trunkgroup) {
7894 pri = pris + x;
7895 lock = &pri->lock;
7896 start = pri->crvs;
7897 end = pri->crvend;
7898 break;
7901 if (!pri) {
7902 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
7903 return NULL;
7905 channelmatch = crv;
7906 p = pris[x].crvs;
7908 #endif
7909 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7910 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
7911 return NULL;
7912 } else {
7913 channelmatch = x;
7916 /* Search for an unowned channel */
7917 ast_mutex_lock(lock);
7918 exit = p;
7919 while (p && !tmp) {
7920 if (roundrobin)
7921 round_robin[x] = p;
7922 #if 0
7923 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
7924 #endif
7926 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
7927 if (option_debug)
7928 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
7929 if (p->inalarm)
7930 goto next;
7932 callwait = (p->owner != NULL);
7933 #ifdef HAVE_PRI
7934 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
7935 if (p->sig != SIG_FXSKS) {
7936 /* Gotta find an actual channel to use for this
7937 CRV if this isn't a callwait */
7938 bearer = pri_find_empty_chan(pri, 0);
7939 if (bearer < 0) {
7940 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
7941 p = NULL;
7942 break;
7944 pri_assign_bearer(p, pri, pri->pvts[bearer]);
7945 } else {
7946 if (alloc_sub(p, 0)) {
7947 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
7948 p = NULL;
7949 break;
7950 } else
7951 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
7952 p->pri = pri;
7955 #endif
7956 if (p->channel == CHAN_PSEUDO) {
7957 p = chandup(p);
7958 if (!p) {
7959 break;
7962 if (p->owner) {
7963 if (alloc_sub(p, SUB_CALLWAIT)) {
7964 p = NULL;
7965 break;
7968 p->outgoing = 1;
7969 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
7970 #ifdef HAVE_PRI
7971 if (p->bearer) {
7972 /* Log owner to bearer channel, too */
7973 p->bearer->owner = tmp;
7975 #endif
7976 /* Make special notes */
7977 if (res > 1) {
7978 if (opt == 'c') {
7979 /* Confirm answer */
7980 p->confirmanswer = 1;
7981 } else if (opt == 'r') {
7982 /* Distinctive ring */
7983 if (res < 3)
7984 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
7985 else
7986 p->distinctivering = y;
7987 } else if (opt == 'd') {
7988 /* If this is an ISDN call, make it digital */
7989 p->digital = 1;
7990 if (tmp)
7991 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
7992 } else {
7993 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
7996 /* Note if the call is a call waiting call */
7997 if (tmp && callwait)
7998 tmp->cdrflags |= AST_CDR_CALLWAIT;
7999 break;
8001 next:
8002 if (backwards) {
8003 p = p->prev;
8004 if (!p)
8005 p = end;
8006 } else {
8007 p = p->next;
8008 if (!p)
8009 p = start;
8011 /* stop when you roll to the one that we started from */
8012 if (p == exit)
8013 break;
8015 ast_mutex_unlock(lock);
8016 restart_monitor();
8017 if (callwait)
8018 *cause = AST_CAUSE_BUSY;
8019 else if (!tmp) {
8020 if (channelmatched) {
8021 if (busy)
8022 *cause = AST_CAUSE_BUSY;
8023 } else if (groupmatched) {
8024 *cause = AST_CAUSE_CONGESTION;
8028 return tmp;
8032 #ifdef HAVE_PRI
8033 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8035 struct dahdi_pvt *p;
8036 p = pri->crvs;
8037 while (p) {
8038 if (p->channel == crv)
8039 return p;
8040 p = p->next;
8042 return NULL;
8046 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8048 int x;
8049 int span = PRI_SPAN(channel);
8050 int spanfd;
8051 DAHDI_PARAMS param;
8052 int principle = -1;
8053 int explicit = PRI_EXPLICIT(channel);
8054 channel = PRI_CHANNEL(channel);
8056 if (!explicit) {
8057 spanfd = pri_active_dchan_fd(pri);
8058 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8059 return -1;
8060 span = pris[param.spanno - 1].prilogicalspan;
8063 for (x = 0; x < pri->numchans; x++) {
8064 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8065 principle = x;
8066 break;
8070 return principle;
8073 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8075 int x;
8076 struct dahdi_pvt *crv;
8077 if (!c) {
8078 if (principle < 0)
8079 return -1;
8080 return principle;
8082 if ((principle > -1) &&
8083 (principle < pri->numchans) &&
8084 (pri->pvts[principle]) &&
8085 (pri->pvts[principle]->call == c))
8086 return principle;
8087 /* First, check for other bearers */
8088 for (x = 0; x < pri->numchans; x++) {
8089 if (!pri->pvts[x])
8090 continue;
8091 if (pri->pvts[x]->call == c) {
8092 /* Found our call */
8093 if (principle != x) {
8094 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8096 if (option_verbose > 2)
8097 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8098 old->channel, new->channel);
8099 if (new->owner) {
8100 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8101 old->channel, new->channel, new->channel);
8102 return -1;
8104 /* Fix it all up now */
8105 new->owner = old->owner;
8106 old->owner = NULL;
8107 if (new->owner) {
8108 ast_string_field_build(new->owner, name,
8109 "DAHDI/%d:%d-%d", pri->trunkgroup,
8110 new->channel, 1);
8111 new->owner->tech_pvt = new;
8112 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8113 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8114 old->subs[SUB_REAL].owner = NULL;
8115 } else
8116 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);
8117 new->call = old->call;
8118 old->call = NULL;
8120 /* Copy any DSP that may be present */
8121 new->dsp = old->dsp;
8122 new->dsp_features = old->dsp_features;
8123 old->dsp = NULL;
8124 old->dsp_features = 0;
8126 return principle;
8129 /* Now check for a CRV with no bearer */
8130 crv = pri->crvs;
8131 while (crv) {
8132 if (crv->call == c) {
8133 /* This is our match... Perform some basic checks */
8134 if (crv->bearer)
8135 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8136 else if (pri->pvts[principle]->owner)
8137 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8138 else {
8139 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8140 wakeup the potential sleeper */
8141 dahdi_close(crv->subs[SUB_REAL].dfd);
8142 pri->pvts[principle]->call = crv->call;
8143 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8144 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8145 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8146 pri->trunkgroup, crv->channel);
8147 wakeup_sub(crv, SUB_REAL, pri);
8149 return principle;
8151 crv = crv->next;
8153 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8154 return -1;
8157 static void *do_idle_thread(void *vchan)
8159 struct ast_channel *chan = vchan;
8160 struct dahdi_pvt *pvt = chan->tech_pvt;
8161 struct ast_frame *f;
8162 char ex[80];
8163 /* Wait up to 30 seconds for an answer */
8164 int newms, ms = 30000;
8165 if (option_verbose > 2)
8166 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8167 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8168 if (ast_call(chan, ex, 0)) {
8169 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8170 ast_hangup(chan);
8171 return NULL;
8173 while ((newms = ast_waitfor(chan, ms)) > 0) {
8174 f = ast_read(chan);
8175 if (!f) {
8176 /* Got hangup */
8177 break;
8179 if (f->frametype == AST_FRAME_CONTROL) {
8180 switch (f->subclass) {
8181 case AST_CONTROL_ANSWER:
8182 /* Launch the PBX */
8183 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8184 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8185 chan->priority = 1;
8186 if (option_verbose > 3)
8187 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8188 ast_pbx_run(chan);
8189 /* It's already hungup, return immediately */
8190 return NULL;
8191 case AST_CONTROL_BUSY:
8192 if (option_verbose > 3)
8193 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8194 break;
8195 case AST_CONTROL_CONGESTION:
8196 if (option_verbose > 3)
8197 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8198 break;
8201 ast_frfree(f);
8202 ms = newms;
8204 /* Hangup the channel since nothing happend */
8205 ast_hangup(chan);
8206 return NULL;
8209 #ifndef PRI_RESTART
8210 #error "Upgrade your libpri"
8211 #endif
8212 static void dahdi_pri_message(struct pri *pri, char *s)
8214 int x, y;
8215 int dchan = -1, span = -1;
8216 int dchancount = 0;
8218 if (pri) {
8219 for (x = 0; x < NUM_SPANS; x++) {
8220 for (y = 0; y < NUM_DCHANS; y++) {
8221 if (pris[x].dchans[y])
8222 dchancount++;
8224 if (pris[x].dchans[y] == pri)
8225 dchan = y;
8227 if (dchan >= 0) {
8228 span = x;
8229 break;
8231 dchancount = 0;
8233 if ((dchan >= 0) && (span >= 0)) {
8234 if (dchancount > 1)
8235 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
8236 else
8237 ast_verbose("%s", s);
8238 } else
8239 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8240 } else
8241 ast_verbose("%s", s);
8243 ast_mutex_lock(&pridebugfdlock);
8245 if (pridebugfd >= 0)
8246 write(pridebugfd, s, strlen(s));
8248 ast_mutex_unlock(&pridebugfdlock);
8251 static void dahdi_pri_error(struct pri *pri, char *s)
8253 int x, y;
8254 int dchan = -1, span = -1;
8255 int dchancount = 0;
8257 if (pri) {
8258 for (x = 0; x < NUM_SPANS; x++) {
8259 for (y = 0; y < NUM_DCHANS; y++) {
8260 if (pris[x].dchans[y])
8261 dchancount++;
8263 if (pris[x].dchans[y] == pri)
8264 dchan = y;
8266 if (dchan >= 0) {
8267 span = x;
8268 break;
8270 dchancount = 0;
8272 if ((dchan >= 0) && (span >= 0)) {
8273 if (dchancount > 1)
8274 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8275 else
8276 ast_log(LOG_ERROR, "%s", s);
8277 } else
8278 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8279 } else
8280 ast_log(LOG_ERROR, "%s", s);
8282 ast_mutex_lock(&pridebugfdlock);
8284 if (pridebugfd >= 0)
8285 write(pridebugfd, s, strlen(s));
8287 ast_mutex_unlock(&pridebugfdlock);
8290 static int pri_check_restart(struct dahdi_pri *pri)
8292 do {
8293 pri->resetpos++;
8294 } while ((pri->resetpos < pri->numchans) &&
8295 (!pri->pvts[pri->resetpos] ||
8296 pri->pvts[pri->resetpos]->call ||
8297 pri->pvts[pri->resetpos]->resetting));
8298 if (pri->resetpos < pri->numchans) {
8299 /* Mark the channel as resetting and restart it */
8300 pri->pvts[pri->resetpos]->resetting = 1;
8301 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8302 } else {
8303 pri->resetting = 0;
8304 time(&pri->lastreset);
8306 return 0;
8309 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
8311 int x;
8312 int redo;
8313 ast_mutex_unlock(&pri->lock);
8314 ast_mutex_lock(&p->lock);
8315 do {
8316 redo = 0;
8317 for (x = 0; x < 3; x++) {
8318 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
8319 redo++;
8320 DEADLOCK_AVOIDANCE(&p->lock);
8322 if (p->subs[x].owner) {
8323 ast_queue_hangup(p->subs[x].owner);
8324 ast_mutex_unlock(&p->subs[x].owner->lock);
8327 } while (redo);
8328 ast_mutex_unlock(&p->lock);
8329 ast_mutex_lock(&pri->lock);
8330 return 0;
8333 static char * redirectingreason2str(int redirectingreason)
8335 switch (redirectingreason) {
8336 case 0:
8337 return "UNKNOWN";
8338 case 1:
8339 return "BUSY";
8340 case 2:
8341 return "NO_REPLY";
8342 case 0xF:
8343 return "UNCONDITIONAL";
8344 default:
8345 return "NOREDIRECT";
8349 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
8351 switch (plan) {
8352 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8353 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
8354 break;
8355 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8356 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
8357 break;
8358 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8359 snprintf(buf, size, "%s%s", pri->localprefix, number);
8360 break;
8361 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8362 snprintf(buf, size, "%s%s", pri->privateprefix, number);
8363 break;
8364 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8365 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
8366 break;
8367 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8368 snprintf(buf, size, "%s", number);
8369 break;
8373 static int dahdi_setlaw(int dfd, int law)
8375 int res;
8376 res = ioctl(dfd, DAHDI_SETLAW, &law);
8377 if (res)
8378 return res;
8379 return 0;
8382 static void *pri_dchannel(void *vpri)
8384 struct dahdi_pri *pri = vpri;
8385 pri_event *e;
8386 struct pollfd fds[NUM_DCHANS];
8387 int res;
8388 int chanpos = 0;
8389 int x;
8390 int haveidles;
8391 int activeidles;
8392 int nextidle = -1;
8393 struct ast_channel *c;
8394 struct timeval tv, lowest, *next;
8395 struct timeval lastidle = { 0, 0 };
8396 int doidling=0;
8397 char *cc;
8398 char idlen[80];
8399 struct ast_channel *idle;
8400 pthread_t p;
8401 time_t t;
8402 int i, which=-1;
8403 int numdchans;
8404 int cause=0;
8405 struct dahdi_pvt *crv;
8406 pthread_t threadid;
8407 pthread_attr_t attr;
8408 char ani2str[6];
8409 char plancallingnum[256];
8410 char plancallingani[256];
8411 char calledtonstr[10];
8413 gettimeofday(&lastidle, NULL);
8414 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
8415 /* Need to do idle dialing, check to be sure though */
8416 cc = strchr(pri->idleext, '@');
8417 if (cc) {
8418 *cc = '\0';
8419 cc++;
8420 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
8421 #if 0
8422 /* Extensions may not be loaded yet */
8423 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
8424 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
8425 else
8426 #endif
8427 doidling = 1;
8428 } else
8429 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
8431 for (;;) {
8432 for (i = 0; i < NUM_DCHANS; i++) {
8433 if (!pri->dchannels[i])
8434 break;
8435 fds[i].fd = pri->fds[i];
8436 fds[i].events = POLLIN | POLLPRI;
8437 fds[i].revents = 0;
8439 numdchans = i;
8440 time(&t);
8441 ast_mutex_lock(&pri->lock);
8442 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
8443 if (pri->resetting && pri_is_up(pri)) {
8444 if (pri->resetpos < 0)
8445 pri_check_restart(pri);
8446 } else {
8447 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
8448 pri->resetting = 1;
8449 pri->resetpos = -1;
8453 /* Look for any idle channels if appropriate */
8454 if (doidling && pri_is_up(pri)) {
8455 nextidle = -1;
8456 haveidles = 0;
8457 activeidles = 0;
8458 for (x = pri->numchans; x >= 0; x--) {
8459 if (pri->pvts[x] && !pri->pvts[x]->owner &&
8460 !pri->pvts[x]->call) {
8461 if (haveidles < pri->minunused) {
8462 haveidles++;
8463 } else if (!pri->pvts[x]->resetting) {
8464 nextidle = x;
8465 break;
8467 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
8468 activeidles++;
8470 if (nextidle > -1) {
8471 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
8472 /* Don't create a new idle call more than once per second */
8473 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
8474 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
8475 if (idle) {
8476 pri->pvts[nextidle]->isidlecall = 1;
8477 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
8478 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
8479 dahdi_hangup(idle);
8481 } else
8482 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
8483 gettimeofday(&lastidle, NULL);
8485 } else if ((haveidles < pri->minunused) &&
8486 (activeidles > pri->minidle)) {
8487 /* Mark something for hangup if there is something
8488 that can be hungup */
8489 for (x = pri->numchans; x >= 0; x--) {
8490 /* find a candidate channel */
8491 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
8492 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8493 haveidles++;
8494 /* Stop if we have enough idle channels or
8495 can't spare any more active idle ones */
8496 if ((haveidles >= pri->minunused) ||
8497 (activeidles <= pri->minidle))
8498 break;
8503 /* Start with reasonable max */
8504 lowest = ast_tv(60, 0);
8505 for (i = 0; i < NUM_DCHANS; i++) {
8506 /* Find lowest available d-channel */
8507 if (!pri->dchannels[i])
8508 break;
8509 if ((next = pri_schedule_next(pri->dchans[i]))) {
8510 /* We need relative time here */
8511 tv = ast_tvsub(*next, ast_tvnow());
8512 if (tv.tv_sec < 0) {
8513 tv = ast_tv(0,0);
8515 if (doidling || pri->resetting) {
8516 if (tv.tv_sec > 1) {
8517 tv = ast_tv(1, 0);
8519 } else {
8520 if (tv.tv_sec > 60) {
8521 tv = ast_tv(60, 0);
8524 } else if (doidling || pri->resetting) {
8525 /* Make sure we stop at least once per second if we're
8526 monitoring idle channels */
8527 tv = ast_tv(1,0);
8528 } else {
8529 /* Don't poll for more than 60 seconds */
8530 tv = ast_tv(60, 0);
8532 if (!i || ast_tvcmp(tv, lowest) < 0) {
8533 lowest = tv;
8536 ast_mutex_unlock(&pri->lock);
8538 e = NULL;
8539 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
8541 ast_mutex_lock(&pri->lock);
8542 if (!res) {
8543 for (which = 0; which < NUM_DCHANS; which++) {
8544 if (!pri->dchans[which])
8545 break;
8546 /* Just a timeout, run the scheduler */
8547 e = pri_schedule_run(pri->dchans[which]);
8548 if (e)
8549 break;
8551 } else if (res > -1) {
8552 for (which = 0; which < NUM_DCHANS; which++) {
8553 if (!pri->dchans[which])
8554 break;
8555 if (fds[which].revents & POLLPRI) {
8556 /* Check for an event */
8557 x = 0;
8558 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
8559 if (x)
8560 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);
8561 /* Keep track of alarm state */
8562 if (x == DAHDI_EVENT_ALARM) {
8563 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8564 pri_find_dchan(pri);
8565 } else if (x == DAHDI_EVENT_NOALARM) {
8566 pri->dchanavail[which] |= DCHAN_NOTINALARM;
8567 pri_restart(pri->dchans[which]);
8570 if (option_debug)
8571 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
8572 } else if (fds[which].revents & POLLIN) {
8573 e = pri_check_event(pri->dchans[which]);
8575 if (e)
8576 break;
8578 } else if (errno != EINTR)
8579 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8581 if (e) {
8582 if (pri->debug)
8583 pri_dump_event(pri->dchans[which], e);
8585 if (e->e != PRI_EVENT_DCHAN_DOWN) {
8586 if (!(pri->dchanavail[which] & DCHAN_UP)) {
8587 if (option_verbose > 1)
8588 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8590 pri->dchanavail[which] |= DCHAN_UP;
8591 } else {
8592 if (pri->dchanavail[which] & DCHAN_UP) {
8593 if (option_verbose > 1)
8594 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8596 pri->dchanavail[which] &= ~DCHAN_UP;
8599 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
8600 /* Must be an NFAS group that has the secondary dchan active */
8601 pri->pri = pri->dchans[which];
8603 switch (e->e) {
8604 case PRI_EVENT_DCHAN_UP:
8605 if (!pri->pri) pri_find_dchan(pri);
8607 /* Note presense of D-channel */
8608 time(&pri->lastreset);
8610 /* Restart in 5 seconds */
8611 if (pri->resetinterval > -1) {
8612 pri->lastreset -= pri->resetinterval;
8613 pri->lastreset += 5;
8615 pri->resetting = 0;
8616 /* Take the channels from inalarm condition */
8617 for (i = 0; i < pri->numchans; i++)
8618 if (pri->pvts[i]) {
8619 pri->pvts[i]->inalarm = 0;
8621 break;
8622 case PRI_EVENT_DCHAN_DOWN:
8623 pri_find_dchan(pri);
8624 if (!pri_is_up(pri)) {
8625 pri->resetting = 0;
8626 /* Hangup active channels and put them in alarm mode */
8627 for (i = 0; i < pri->numchans; i++) {
8628 struct dahdi_pvt *p = pri->pvts[i];
8629 if (p) {
8630 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8631 /* T309 is not enabled : hangup calls when alarm occurs */
8632 if (p->call) {
8633 if (p->pri && p->pri->pri) {
8634 pri_hangup(p->pri->pri, p->call, -1);
8635 pri_destroycall(p->pri->pri, p->call);
8636 p->call = NULL;
8637 } else
8638 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8640 if (p->realcall) {
8641 pri_hangup_all(p->realcall, pri);
8642 } else if (p->owner)
8643 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8645 p->inalarm = 1;
8649 break;
8650 case PRI_EVENT_RESTART:
8651 if (e->restart.channel > -1) {
8652 chanpos = pri_find_principle(pri, e->restart.channel);
8653 if (chanpos < 0)
8654 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8655 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8656 else {
8657 if (option_verbose > 2)
8658 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
8659 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8660 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8661 if (pri->pvts[chanpos]->call) {
8662 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
8663 pri->pvts[chanpos]->call = NULL;
8665 /* Force soft hangup if appropriate */
8666 if (pri->pvts[chanpos]->realcall)
8667 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8668 else if (pri->pvts[chanpos]->owner)
8669 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8670 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8672 } else {
8673 if (option_verbose > 2)
8674 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
8675 for (x = 0; x < pri->numchans; x++)
8676 if (pri->pvts[x]) {
8677 ast_mutex_lock(&pri->pvts[x]->lock);
8678 if (pri->pvts[x]->call) {
8679 pri_destroycall(pri->pri, pri->pvts[x]->call);
8680 pri->pvts[x]->call = NULL;
8682 if (pri->pvts[chanpos]->realcall)
8683 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8684 else if (pri->pvts[x]->owner)
8685 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8686 ast_mutex_unlock(&pri->pvts[x]->lock);
8689 break;
8690 case PRI_EVENT_KEYPAD_DIGIT:
8691 chanpos = pri_find_principle(pri, e->digit.channel);
8692 if (chanpos < 0) {
8693 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8694 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
8695 } else {
8696 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
8697 if (chanpos > -1) {
8698 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8699 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8700 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
8701 /* how to do that */
8702 int digitlen = strlen(e->digit.digits);
8703 char digit;
8704 int i;
8705 for (i = 0; i < digitlen; i++) {
8706 digit = e->digit.digits[i];
8708 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8709 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8713 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8716 break;
8718 case PRI_EVENT_INFO_RECEIVED:
8719 chanpos = pri_find_principle(pri, e->ring.channel);
8720 if (chanpos < 0) {
8721 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
8722 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8723 } else {
8724 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8725 if (chanpos > -1) {
8726 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8727 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8728 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8729 /* how to do that */
8730 int digitlen = strlen(e->ring.callednum);
8731 char digit;
8732 int i;
8733 for (i = 0; i < digitlen; i++) {
8734 digit = e->ring.callednum[i];
8736 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8737 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8741 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8744 break;
8745 case PRI_EVENT_RING:
8746 crv = NULL;
8747 if (e->ring.channel == -1)
8748 chanpos = pri_find_empty_chan(pri, 1);
8749 else
8750 chanpos = pri_find_principle(pri, e->ring.channel);
8751 /* if no channel specified find one empty */
8752 if (chanpos < 0) {
8753 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8754 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8755 } else {
8756 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8757 if (pri->pvts[chanpos]->owner) {
8758 if (pri->pvts[chanpos]->call == e->ring.call) {
8759 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8760 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8761 break;
8762 } else {
8763 /* This is where we handle initial glare */
8764 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8765 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8766 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8767 chanpos = -1;
8770 if (chanpos > -1)
8771 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8773 if ((chanpos < 0) && (e->ring.flexible))
8774 chanpos = pri_find_empty_chan(pri, 1);
8775 if (chanpos > -1) {
8776 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8777 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8778 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8779 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8780 if (crv)
8781 ast_mutex_lock(&crv->lock);
8782 if (!crv || crv->owner) {
8783 pri->pvts[chanpos]->call = NULL;
8784 if (crv) {
8785 if (crv->owner)
8786 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8787 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);
8788 } else
8789 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);
8790 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8791 if (crv)
8792 ast_mutex_unlock(&crv->lock);
8793 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8794 break;
8797 pri->pvts[chanpos]->call = e->ring.call;
8798 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8799 if (pri->pvts[chanpos]->use_callerid) {
8800 ast_shrink_phone_number(plancallingnum);
8801 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
8802 #ifdef PRI_ANI
8803 if (!ast_strlen_zero(e->ring.callingani)) {
8804 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
8805 ast_shrink_phone_number(plancallingani);
8806 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
8807 } else {
8808 pri->pvts[chanpos]->cid_ani[0] = '\0';
8810 #endif
8811 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
8812 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8813 } else {
8814 pri->pvts[chanpos]->cid_num[0] = '\0';
8815 pri->pvts[chanpos]->cid_ani[0] = '\0';
8816 pri->pvts[chanpos]->cid_name[0] = '\0';
8817 pri->pvts[chanpos]->cid_ton = 0;
8819 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8820 e->ring.redirectingnum, e->ring.callingplanrdnis);
8821 /* If immediate=yes go to s|1 */
8822 if (pri->pvts[chanpos]->immediate) {
8823 if (option_verbose > 2)
8824 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8825 pri->pvts[chanpos]->exten[0] = 's';
8826 pri->pvts[chanpos]->exten[1] = '\0';
8828 /* Get called number */
8829 else if (!ast_strlen_zero(e->ring.callednum)) {
8830 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8831 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8832 } else if (pri->overlapdial)
8833 pri->pvts[chanpos]->exten[0] = '\0';
8834 else {
8835 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8836 pri->pvts[chanpos]->exten[0] = 's';
8837 pri->pvts[chanpos]->exten[1] = '\0';
8839 /* Set DNID on all incoming calls -- even immediate */
8840 if (!ast_strlen_zero(e->ring.callednum))
8841 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8842 /* No number yet, but received "sending complete"? */
8843 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8844 if (option_verbose > 2)
8845 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8846 pri->pvts[chanpos]->exten[0] = 's';
8847 pri->pvts[chanpos]->exten[1] = '\0';
8849 /* Make sure extension exists (or in overlap dial mode, can exist) */
8850 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8851 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8852 /* Setup law */
8853 int law;
8854 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
8855 /* Set to audio mode at this point */
8856 law = 1;
8857 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
8858 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
8860 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
8861 law = DAHDI_LAW_ALAW;
8862 else
8863 law = DAHDI_LAW_MULAW;
8864 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
8865 if (res < 0)
8866 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
8867 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8868 if (res < 0)
8869 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
8870 if (e->ring.complete || !pri->overlapdial) {
8871 /* Just announce proceeding */
8872 pri->pvts[chanpos]->proceeding = 1;
8873 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8874 } else {
8875 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
8876 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8877 else
8878 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8880 /* Get the use_callingpres state */
8881 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
8883 /* Start PBX */
8884 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8885 /* Release the PRI lock while we create the channel */
8886 ast_mutex_unlock(&pri->lock);
8887 if (crv) {
8888 /* Set bearer and such */
8889 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
8890 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8891 pri->pvts[chanpos]->owner = &inuse;
8892 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
8893 } else {
8894 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8897 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8899 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
8900 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8902 if (e->ring.ani2 >= 0) {
8903 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
8904 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8907 #ifdef SUPPORT_USERUSER
8908 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8909 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8911 #endif
8913 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8914 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8915 if (e->ring.redirectingreason >= 0)
8916 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8918 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8919 ast_mutex_lock(&pri->lock);
8921 pthread_attr_init(&attr);
8922 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
8923 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
8924 if (option_verbose > 2)
8925 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8926 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
8927 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8928 } else {
8929 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8930 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8931 if (c)
8932 ast_hangup(c);
8933 else {
8934 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8935 pri->pvts[chanpos]->call = NULL;
8938 pthread_attr_destroy(&attr);
8939 } else {
8940 ast_mutex_unlock(&pri->lock);
8941 /* Release PRI lock while we create the channel */
8942 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
8943 if (c) {
8944 char calledtonstr[10];
8946 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8948 if (e->ring.ani2 >= 0) {
8949 snprintf(ani2str, 5, "%d", e->ring.ani2);
8950 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8953 #ifdef SUPPORT_USERUSER
8954 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8955 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8957 #endif
8959 if (e->ring.redirectingreason >= 0)
8960 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8962 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8963 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8965 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8966 ast_mutex_lock(&pri->lock);
8968 if (option_verbose > 2)
8969 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8970 plancallingnum, pri->pvts[chanpos]->exten,
8971 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8972 dahdi_enable_ec(pri->pvts[chanpos]);
8973 } else {
8975 ast_mutex_lock(&pri->lock);
8977 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8978 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8979 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8980 pri->pvts[chanpos]->call = NULL;
8983 } else {
8984 if (option_verbose > 2)
8985 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
8986 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
8987 pri->pvts[chanpos]->prioffset, pri->span);
8988 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
8989 pri->pvts[chanpos]->call = NULL;
8990 pri->pvts[chanpos]->exten[0] = '\0';
8992 if (crv)
8993 ast_mutex_unlock(&crv->lock);
8994 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8995 } else {
8996 if (e->ring.flexible)
8997 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
8998 else
8999 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
9001 break;
9002 case PRI_EVENT_RINGING:
9003 chanpos = pri_find_principle(pri, e->ringing.channel);
9004 if (chanpos < 0) {
9005 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9006 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9007 } else {
9008 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9009 if (chanpos < 0) {
9010 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9011 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9012 } else {
9013 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9014 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9015 dahdi_enable_ec(pri->pvts[chanpos]);
9016 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9017 pri->pvts[chanpos]->alerting = 1;
9018 } else
9019 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9020 #ifdef PRI_PROGRESS_MASK
9021 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9022 #else
9023 if (e->ringing.progress == 8) {
9024 #endif
9025 /* Now we can do call progress detection */
9026 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9027 /* RINGING detection isn't required because we got ALERTING signal */
9028 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9029 pri->pvts[chanpos]->dsp_features = 0;
9033 #ifdef SUPPORT_USERUSER
9034 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9035 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9036 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9037 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9038 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9040 #endif
9042 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9045 break;
9046 case PRI_EVENT_PROGRESS:
9047 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9048 chanpos = pri_find_principle(pri, e->proceeding.channel);
9049 if (chanpos > -1) {
9050 #ifdef PRI_PROGRESS_MASK
9051 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9052 #else
9053 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9054 #endif
9055 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9057 if (e->proceeding.cause > -1) {
9058 if (option_verbose > 2)
9059 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9061 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9062 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9063 if (pri->pvts[chanpos]->owner) {
9064 if (option_verbose > 2)
9065 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9067 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9068 f.subclass = AST_CONTROL_BUSY;
9073 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9074 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9075 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9076 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9077 #ifdef PRI_PROGRESS_MASK
9078 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9079 #else
9080 if (e->proceeding.progress == 8) {
9081 #endif
9082 /* Now we can do call progress detection */
9083 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9084 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9085 pri->pvts[chanpos]->dsp_features = 0;
9088 pri->pvts[chanpos]->progress = 1;
9089 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9092 break;
9093 case PRI_EVENT_PROCEEDING:
9094 chanpos = pri_find_principle(pri, e->proceeding.channel);
9095 if (chanpos > -1) {
9096 if (!pri->pvts[chanpos]->proceeding) {
9097 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9099 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9100 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9101 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9102 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9103 #ifdef PRI_PROGRESS_MASK
9104 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9105 #else
9106 if (e->proceeding.progress == 8) {
9107 #endif
9108 /* Now we can do call progress detection */
9109 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9110 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9111 pri->pvts[chanpos]->dsp_features = 0;
9113 /* Bring voice path up */
9114 f.subclass = AST_CONTROL_PROGRESS;
9115 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9117 pri->pvts[chanpos]->proceeding = 1;
9118 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9121 break;
9122 case PRI_EVENT_FACNAME:
9123 chanpos = pri_find_principle(pri, e->facname.channel);
9124 if (chanpos < 0) {
9125 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9126 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9127 } else {
9128 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
9129 if (chanpos < 0) {
9130 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
9131 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9132 } else {
9133 /* Re-use *69 field for PRI */
9134 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9135 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
9136 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
9137 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
9138 dahdi_enable_ec(pri->pvts[chanpos]);
9139 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9142 break;
9143 case PRI_EVENT_ANSWER:
9144 chanpos = pri_find_principle(pri, e->answer.channel);
9145 if (chanpos < 0) {
9146 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
9147 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9148 } else {
9149 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
9150 if (chanpos < 0) {
9151 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
9152 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9153 } else {
9154 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9155 /* Now we can do call progress detection */
9157 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9158 * By this time, we need DTMF detection and other features that were previously disabled
9159 * -- Matt F */
9160 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9161 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9162 pri->pvts[chanpos]->dsp_features = 0;
9164 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
9165 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
9166 x = DAHDI_START;
9167 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
9168 if (res < 0) {
9169 if (errno != EINPROGRESS) {
9170 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
9173 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9174 pri->pvts[chanpos]->dialing = 1;
9175 /* Send any "w" waited stuff */
9176 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
9177 if (res < 0) {
9178 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
9179 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9180 } else
9181 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9182 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9183 } else if (pri->pvts[chanpos]->confirmanswer) {
9184 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9185 } else {
9186 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9187 /* Enable echo cancellation if it's not on already */
9188 dahdi_enable_ec(pri->pvts[chanpos]);
9191 #ifdef SUPPORT_USERUSER
9192 if (!ast_strlen_zero(e->answer.useruserinfo)) {
9193 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9194 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9195 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
9196 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9198 #endif
9200 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9203 break;
9204 case PRI_EVENT_HANGUP:
9205 chanpos = pri_find_principle(pri, e->hangup.channel);
9206 if (chanpos < 0) {
9207 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
9208 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9209 } else {
9210 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9211 if (chanpos > -1) {
9212 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9213 if (!pri->pvts[chanpos]->alreadyhungup) {
9214 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9215 pri->pvts[chanpos]->alreadyhungup = 1;
9216 if (pri->pvts[chanpos]->realcall)
9217 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9218 else if (pri->pvts[chanpos]->owner) {
9219 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9220 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9221 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9222 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9223 else {
9224 switch (e->hangup.cause) {
9225 case PRI_CAUSE_USER_BUSY:
9226 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9227 break;
9228 case PRI_CAUSE_CALL_REJECTED:
9229 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9230 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9231 case PRI_CAUSE_SWITCH_CONGESTION:
9232 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9233 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9234 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9235 break;
9236 default:
9237 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9241 if (option_verbose > 2)
9242 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9243 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9244 } else {
9245 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9246 pri->pvts[chanpos]->call = NULL;
9248 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9249 if (option_verbose > 2)
9250 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9251 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9252 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9253 pri->pvts[chanpos]->resetting = 1;
9255 if (e->hangup.aoc_units > -1)
9256 if (option_verbose > 2)
9257 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9258 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9260 #ifdef SUPPORT_USERUSER
9261 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
9262 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9263 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9264 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9265 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9267 #endif
9269 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9270 } else {
9271 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9272 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9275 break;
9276 #ifndef PRI_EVENT_HANGUP_REQ
9277 #error please update libpri
9278 #endif
9279 case PRI_EVENT_HANGUP_REQ:
9280 chanpos = pri_find_principle(pri, e->hangup.channel);
9281 if (chanpos < 0) {
9282 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9283 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9284 } else {
9285 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9286 if (chanpos > -1) {
9287 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9288 if (pri->pvts[chanpos]->realcall)
9289 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9290 else if (pri->pvts[chanpos]->owner) {
9291 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9292 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9293 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9294 else {
9295 switch (e->hangup.cause) {
9296 case PRI_CAUSE_USER_BUSY:
9297 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9298 break;
9299 case PRI_CAUSE_CALL_REJECTED:
9300 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9301 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9302 case PRI_CAUSE_SWITCH_CONGESTION:
9303 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9304 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9305 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9306 break;
9307 default:
9308 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9311 if (option_verbose > 2)
9312 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
9313 if (e->hangup.aoc_units > -1)
9314 if (option_verbose > 2)
9315 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9316 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9317 } else {
9318 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9319 pri->pvts[chanpos]->call = NULL;
9321 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9322 if (option_verbose > 2)
9323 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9324 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9325 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9326 pri->pvts[chanpos]->resetting = 1;
9329 #ifdef SUPPORT_USERUSER
9330 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9331 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9332 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9333 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9334 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9336 #endif
9338 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9339 } else {
9340 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);
9343 break;
9344 case PRI_EVENT_HANGUP_ACK:
9345 chanpos = pri_find_principle(pri, e->hangup.channel);
9346 if (chanpos < 0) {
9347 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9348 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9349 } else {
9350 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9351 if (chanpos > -1) {
9352 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9353 pri->pvts[chanpos]->call = NULL;
9354 pri->pvts[chanpos]->resetting = 0;
9355 if (pri->pvts[chanpos]->owner) {
9356 if (option_verbose > 2)
9357 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9360 #ifdef SUPPORT_USERUSER
9361 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9362 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9363 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9364 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9365 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9367 #endif
9369 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9372 break;
9373 case PRI_EVENT_CONFIG_ERR:
9374 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
9375 break;
9376 case PRI_EVENT_RESTART_ACK:
9377 chanpos = pri_find_principle(pri, e->restartack.channel);
9378 if (chanpos < 0) {
9379 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9380 channel number, so we have to figure it out... This must be why
9381 everybody resets exactly a channel at a time. */
9382 for (x = 0; x < pri->numchans; x++) {
9383 if (pri->pvts[x] && pri->pvts[x]->resetting) {
9384 chanpos = x;
9385 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9386 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
9387 pri->pvts[chanpos]->prioffset, pri->span);
9388 if (pri->pvts[chanpos]->realcall)
9389 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9390 else if (pri->pvts[chanpos]->owner) {
9391 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
9392 pri->pvts[chanpos]->prioffset, pri->span);
9393 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9395 pri->pvts[chanpos]->resetting = 0;
9396 if (option_verbose > 2)
9397 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9398 pri->pvts[chanpos]->prioffset, pri->span);
9399 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9400 if (pri->resetting)
9401 pri_check_restart(pri);
9402 break;
9405 if (chanpos < 0) {
9406 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
9407 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9409 } else {
9410 if (pri->pvts[chanpos]) {
9411 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9412 if (pri->pvts[chanpos]->realcall)
9413 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9414 else if (pri->pvts[chanpos]->owner) {
9415 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
9416 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9417 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9419 pri->pvts[chanpos]->resetting = 0;
9420 if (option_verbose > 2)
9421 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9422 pri->pvts[chanpos]->prioffset, pri->span);
9423 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9424 if (pri->resetting)
9425 pri_check_restart(pri);
9428 break;
9429 case PRI_EVENT_SETUP_ACK:
9430 chanpos = pri_find_principle(pri, e->setup_ack.channel);
9431 if (chanpos < 0) {
9432 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9433 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
9434 } else {
9435 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
9436 if (chanpos > -1) {
9437 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9438 pri->pvts[chanpos]->setup_ack = 1;
9439 /* Send any queued digits */
9440 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
9441 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
9442 pri_information(pri->pri, pri->pvts[chanpos]->call,
9443 pri->pvts[chanpos]->dialdest[x]);
9445 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9446 } else
9447 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
9449 break;
9450 case PRI_EVENT_NOTIFY:
9451 chanpos = pri_find_principle(pri, e->notify.channel);
9452 if (chanpos < 0) {
9453 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9454 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
9455 } else {
9456 struct ast_frame f = { AST_FRAME_CONTROL, };
9457 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9458 switch (e->notify.info) {
9459 case PRI_NOTIFY_REMOTE_HOLD:
9460 f.subclass = AST_CONTROL_HOLD;
9461 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9462 break;
9463 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9464 f.subclass = AST_CONTROL_UNHOLD;
9465 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9466 break;
9468 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9470 break;
9471 default:
9472 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9475 ast_mutex_unlock(&pri->lock);
9477 /* Never reached */
9478 return NULL;
9481 static int start_pri(struct dahdi_pri *pri)
9483 int res, x;
9484 DAHDI_PARAMS p;
9485 DAHDI_BUFFERINFO bi;
9486 DAHDI_SPANINFO si;
9487 int i;
9489 for (i = 0; i < NUM_DCHANS; i++) {
9490 if (!pri->dchannels[i])
9491 break;
9492 #ifdef HAVE_ZAPTEL
9493 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
9494 #else
9495 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
9496 #endif
9497 x = pri->dchannels[i];
9498 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
9499 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
9500 return -1;
9502 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
9503 if (res) {
9504 dahdi_close(pri->fds[i]);
9505 pri->fds[i] = -1;
9506 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
9507 return -1;
9509 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
9510 dahdi_close(pri->fds[i]);
9511 pri->fds[i] = -1;
9512 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x);
9513 return -1;
9515 memset(&si, 0, sizeof(si));
9516 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
9517 if (res) {
9518 dahdi_close(pri->fds[i]);
9519 pri->fds[i] = -1;
9520 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
9522 if (!si.alarms)
9523 pri->dchanavail[i] |= DCHAN_NOTINALARM;
9524 else
9525 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
9526 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
9527 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
9528 bi.numbufs = 32;
9529 bi.bufsize = 1024;
9530 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
9531 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
9532 dahdi_close(pri->fds[i]);
9533 pri->fds[i] = -1;
9534 return -1;
9536 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9537 /* Force overlap dial if we're doing GR-303! */
9538 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9539 pri->overlapdial = 1;
9540 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
9541 #ifdef HAVE_PRI_INBANDRELEASE
9542 pri_set_inbandrelease(pri->dchans[i], pri->inbandrelease);
9543 #endif
9544 /* Enslave to master if appropriate */
9545 if (i)
9546 pri_enslave(pri->dchans[0], pri->dchans[i]);
9547 if (!pri->dchans[i]) {
9548 dahdi_close(pri->fds[i]);
9549 pri->fds[i] = -1;
9550 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
9551 return -1;
9553 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
9554 pri_set_nsf(pri->dchans[i], pri->nsf);
9555 #ifdef PRI_GETSET_TIMERS
9556 for (x = 0; x < PRI_MAX_TIMERS; x++) {
9557 if (pritimers[x] != 0)
9558 pri_set_timer(pri->dchans[i], x, pritimers[x]);
9560 #endif
9562 /* Assume primary is the one we use */
9563 pri->pri = pri->dchans[0];
9564 pri->resetpos = -1;
9565 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
9566 for (i = 0; i < NUM_DCHANS; i++) {
9567 if (!pri->dchannels[i])
9568 break;
9569 dahdi_close(pri->fds[i]);
9570 pri->fds[i] = -1;
9572 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
9573 return -1;
9575 return 0;
9578 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
9580 int which, span;
9581 char *ret = NULL;
9583 if (pos != rpos)
9584 return ret;
9586 for (which = span = 0; span < NUM_SPANS; span++) {
9587 if (pris[span].pri && ++which > state) {
9588 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
9589 break;
9592 return ret;
9595 static char *complete_span_4(const char *line, const char *word, int pos, int state)
9597 return complete_span_helper(line,word,pos,state,3);
9600 static char *complete_span_5(const char *line, const char *word, int pos, int state)
9602 return complete_span_helper(line,word,pos,state,4);
9605 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9607 int myfd;
9609 if (!strncasecmp(argv[1], "set", 3)) {
9610 if (argc < 5)
9611 return RESULT_SHOWUSAGE;
9613 if (ast_strlen_zero(argv[4]))
9614 return RESULT_SHOWUSAGE;
9616 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
9617 if (myfd < 0) {
9618 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9619 return RESULT_SUCCESS;
9622 ast_mutex_lock(&pridebugfdlock);
9624 if (pridebugfd >= 0)
9625 close(pridebugfd);
9627 pridebugfd = myfd;
9628 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9630 ast_mutex_unlock(&pridebugfdlock);
9632 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9633 } else {
9634 /* Assume it is unset */
9635 ast_mutex_lock(&pridebugfdlock);
9636 close(pridebugfd);
9637 pridebugfd = -1;
9638 ast_cli(fd, "PRI debug output to file disabled\n");
9639 ast_mutex_unlock(&pridebugfdlock);
9642 return RESULT_SUCCESS;
9645 #ifdef HAVE_PRI_VERSION
9646 static int handle_pri_version(int fd, int agc, char *argv[]) {
9647 ast_cli(fd, "libpri version: %s\n", pri_get_version());
9648 return RESULT_SUCCESS;
9650 #endif
9652 static int handle_pri_debug(int fd, int argc, char *argv[])
9654 int span;
9655 int x;
9656 if (argc < 4) {
9657 return RESULT_SHOWUSAGE;
9659 span = atoi(argv[3]);
9660 if ((span < 1) || (span > NUM_SPANS)) {
9661 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
9662 return RESULT_SUCCESS;
9664 if (!pris[span-1].pri) {
9665 ast_cli(fd, "No PRI running on span %d\n", span);
9666 return RESULT_SUCCESS;
9668 for (x = 0; x < NUM_DCHANS; x++) {
9669 if (pris[span-1].dchans[x])
9670 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9671 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9672 PRI_DEBUG_Q921_STATE);
9674 ast_cli(fd, "Enabled debugging on span %d\n", span);
9675 return RESULT_SUCCESS;
9680 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9682 int span;
9683 int x;
9684 if (argc < 5)
9685 return RESULT_SHOWUSAGE;
9686 span = atoi(argv[4]);
9687 if ((span < 1) || (span > NUM_SPANS)) {
9688 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9689 return RESULT_SUCCESS;
9691 if (!pris[span-1].pri) {
9692 ast_cli(fd, "No PRI running on span %d\n", span);
9693 return RESULT_SUCCESS;
9695 for (x = 0; x < NUM_DCHANS; x++) {
9696 if (pris[span-1].dchans[x])
9697 pri_set_debug(pris[span-1].dchans[x], 0);
9699 ast_cli(fd, "Disabled debugging on span %d\n", span);
9700 return RESULT_SUCCESS;
9703 static int handle_pri_really_debug(int fd, int argc, char *argv[])
9705 int span;
9706 int x;
9707 if (argc < 5)
9708 return RESULT_SHOWUSAGE;
9709 span = atoi(argv[4]);
9710 if ((span < 1) || (span > NUM_SPANS)) {
9711 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9712 return RESULT_SUCCESS;
9714 if (!pris[span-1].pri) {
9715 ast_cli(fd, "No PRI running on span %d\n", span);
9716 return RESULT_SUCCESS;
9718 for (x = 0; x < NUM_DCHANS; x++) {
9719 if (pris[span-1].dchans[x])
9720 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9721 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9722 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
9724 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
9725 return RESULT_SUCCESS;
9728 static void build_status(char *s, size_t len, int status, int active)
9730 if (!s || len < 1) {
9731 return;
9733 s[0] = '\0';
9734 if (status & DCHAN_PROVISIONED)
9735 strncat(s, "Provisioned, ", len - strlen(s) - 1);
9736 if (!(status & DCHAN_NOTINALARM))
9737 strncat(s, "In Alarm, ", len - strlen(s) - 1);
9738 if (status & DCHAN_UP)
9739 strncat(s, "Up", len - strlen(s) - 1);
9740 else
9741 strncat(s, "Down", len - strlen(s) - 1);
9742 if (active)
9743 strncat(s, ", Active", len - strlen(s) - 1);
9744 else
9745 strncat(s, ", Standby", len - strlen(s) - 1);
9746 s[len - 1] = '\0';
9749 static int handle_pri_show_spans(int fd, int argc, char *argv[])
9751 int span;
9752 int x;
9753 char status[256];
9754 if (argc != 3)
9755 return RESULT_SHOWUSAGE;
9757 for (span = 0; span < NUM_SPANS; span++) {
9758 if (pris[span].pri) {
9759 for (x = 0; x < NUM_DCHANS; x++) {
9760 if (pris[span].dchannels[x]) {
9761 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
9762 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
9767 return RESULT_SUCCESS;
9770 static int handle_pri_show_span(int fd, int argc, char *argv[])
9772 int span;
9773 int x;
9774 char status[256];
9775 if (argc < 4)
9776 return RESULT_SHOWUSAGE;
9777 span = atoi(argv[3]);
9778 if ((span < 1) || (span > NUM_SPANS)) {
9779 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
9780 return RESULT_SUCCESS;
9782 if (!pris[span-1].pri) {
9783 ast_cli(fd, "No PRI running on span %d\n", span);
9784 return RESULT_SUCCESS;
9786 for (x = 0; x < NUM_DCHANS; x++) {
9787 if (pris[span-1].dchannels[x]) {
9788 #ifdef PRI_DUMP_INFO_STR
9789 char *info_str = NULL;
9790 #endif
9791 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
9792 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
9793 ast_cli(fd, "Status: %s\n", status);
9794 #ifdef PRI_DUMP_INFO_STR
9795 info_str = pri_dump_info_str(pris[span-1].pri);
9796 if (info_str) {
9797 ast_cli(fd, "%s", info_str);
9798 free(info_str);
9800 #else
9801 pri_dump_info(pris[span-1].pri);
9802 #endif
9803 ast_cli(fd, "\n");
9806 return RESULT_SUCCESS;
9809 static int handle_pri_show_debug(int fd, int argc, char *argv[])
9811 int x;
9812 int span;
9813 int count=0;
9814 int debug=0;
9816 for (span = 0; span < NUM_SPANS; span++) {
9817 if (pris[span].pri) {
9818 for (x = 0; x < NUM_DCHANS; x++) {
9819 debug = 0;
9820 if (pris[span].dchans[x]) {
9821 debug = pri_get_debug(pris[span].dchans[x]);
9822 ast_cli(fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
9823 count++;
9829 ast_mutex_lock(&pridebugfdlock);
9830 if (pridebugfd >= 0)
9831 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9832 ast_mutex_unlock(&pridebugfdlock);
9834 if (!count)
9835 ast_cli(fd, "No debug set or no PRI running\n");
9836 return RESULT_SUCCESS;
9839 static const char pri_debug_help[] =
9840 "Usage: pri debug span <span>\n"
9841 " Enables debugging on a given PRI span\n";
9843 static const char pri_no_debug_help[] =
9844 "Usage: pri no debug span <span>\n"
9845 " Disables debugging on a given PRI span\n";
9847 static const char pri_really_debug_help[] =
9848 "Usage: pri intensive debug span <span>\n"
9849 " Enables debugging down to the Q.921 level\n";
9851 static const char pri_show_span_help[] =
9852 "Usage: pri show span <span>\n"
9853 " Displays PRI Information on a given PRI span\n";
9855 static const char pri_show_spans_help[] =
9856 "Usage: pri show spans\n"
9857 " Displays PRI Information\n";
9859 static struct ast_cli_entry dahdi_pri_cli[] = {
9860 { { "pri", "debug", "span", NULL },
9861 handle_pri_debug, "Enables PRI debugging on a span",
9862 pri_debug_help, complete_span_4 },
9864 { { "pri", "no", "debug", "span", NULL },
9865 handle_pri_no_debug, "Disables PRI debugging on a span",
9866 pri_no_debug_help, complete_span_5 },
9868 { { "pri", "intense", "debug", "span", NULL },
9869 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
9870 pri_really_debug_help, complete_span_5 },
9872 { { "pri", "show", "spans", NULL },
9873 handle_pri_show_spans, "Displays PRI Information",
9874 pri_show_spans_help },
9876 { { "pri", "show", "span", NULL },
9877 handle_pri_show_span, "Displays PRI Information",
9878 pri_show_span_help, complete_span_4 },
9880 { { "pri", "show", "debug", NULL },
9881 handle_pri_show_debug, "Displays current PRI debug settings" },
9883 { { "pri", "set", "debug", "file", NULL },
9884 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
9886 { { "pri", "unset", "debug", "file", NULL },
9887 handle_pri_set_debug_file, "Ends PRI debug output to file" },
9889 #ifdef HAVE_PRI_VERSION
9890 { { "pri", "show", "version", NULL },
9891 handle_pri_version, "Displays version of libpri" },
9892 #endif
9895 #endif /* HAVE_PRI */
9897 static int dahdi_destroy_channel(int fd, int argc, char **argv)
9899 int channel;
9901 if (argc != 4)
9902 return RESULT_SHOWUSAGE;
9904 channel = atoi(argv[3]);
9906 return dahdi_destroy_channel_bynum(channel);
9909 static int setup_dahdi(int reload);
9910 static int dahdi_restart(void)
9912 if (option_verbose > 0)
9913 ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading DAHDI configuration.\n");
9914 while (iflist) {
9915 if (option_debug)
9916 ast_log(LOG_DEBUG, "Destroying DAHDI channel no. %d\n", iflist->channel);
9917 /* Also updates iflist: */
9918 destroy_channel(NULL, iflist, 1);
9920 if (option_debug)
9921 ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
9922 if (setup_dahdi(0) != 0) {
9923 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
9924 return 1;
9926 return 0;
9929 static int dahdi_restart_cmd(int fd, int argc, char **argv)
9931 if (argc != 2) {
9932 return RESULT_SHOWUSAGE;
9935 if (dahdi_restart() != 0)
9936 return RESULT_FAILURE;
9937 return RESULT_SUCCESS;
9940 static int action_dahdirestart(struct mansession *s, const struct message *m)
9942 if (dahdi_restart() != 0) {
9943 astman_send_error(s, m, "Failed rereading DAHDI configuration");
9944 return 1;
9946 astman_send_ack(s, m, "DAHDIRestart: Success");
9947 return 0;
9950 static int dahdi_show_channels(int fd, int argc, char **argv)
9952 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9953 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9954 struct dahdi_pvt *tmp = NULL;
9955 char tmps[20] = "";
9956 ast_mutex_t *lock;
9957 struct dahdi_pvt *start;
9958 #ifdef HAVE_PRI
9959 int trunkgroup;
9960 struct dahdi_pri *pri = NULL;
9961 int x;
9962 #endif
9964 lock = &iflock;
9965 start = iflist;
9967 #ifdef HAVE_PRI
9968 if (argc == 4) {
9969 if ((trunkgroup = atoi(argv[3])) < 1)
9970 return RESULT_SHOWUSAGE;
9971 for (x = 0; x < NUM_SPANS; x++) {
9972 if (pris[x].trunkgroup == trunkgroup) {
9973 pri = pris + x;
9974 break;
9977 if (pri) {
9978 start = pri->crvs;
9979 lock = &pri->lock;
9980 } else {
9981 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
9982 return RESULT_FAILURE;
9984 } else
9985 #endif
9986 if (argc != 3)
9987 return RESULT_SHOWUSAGE;
9989 ast_mutex_lock(lock);
9990 #ifdef HAVE_PRI
9991 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
9992 #else
9993 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
9994 #endif
9996 tmp = start;
9997 while (tmp) {
9998 if (tmp->channel > 0) {
9999 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10000 } else
10001 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10002 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10003 tmp = tmp->next;
10005 ast_mutex_unlock(lock);
10006 return RESULT_SUCCESS;
10007 #undef FORMAT
10008 #undef FORMAT2
10011 static int dahdi_show_channel(int fd, int argc, char **argv)
10013 int channel;
10014 struct dahdi_pvt *tmp = NULL;
10015 DAHDI_CONFINFO ci;
10016 DAHDI_PARAMS ps;
10017 int x;
10018 ast_mutex_t *lock;
10019 struct dahdi_pvt *start;
10020 #ifdef HAVE_PRI
10021 char *c;
10022 int trunkgroup;
10023 struct dahdi_pri *pri=NULL;
10024 #endif
10026 lock = &iflock;
10027 start = iflist;
10029 if (argc != 4)
10030 return RESULT_SHOWUSAGE;
10031 #ifdef HAVE_PRI
10032 if ((c = strchr(argv[3], ':'))) {
10033 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10034 return RESULT_SHOWUSAGE;
10035 if ((trunkgroup < 1) || (channel < 1))
10036 return RESULT_SHOWUSAGE;
10037 for (x = 0; x < NUM_SPANS; x++) {
10038 if (pris[x].trunkgroup == trunkgroup) {
10039 pri = pris + x;
10040 break;
10043 if (pri) {
10044 start = pri->crvs;
10045 lock = &pri->lock;
10046 } else {
10047 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10048 return RESULT_FAILURE;
10050 } else
10051 #endif
10052 channel = atoi(argv[3]);
10054 ast_mutex_lock(lock);
10055 tmp = start;
10056 while (tmp) {
10057 if (tmp->channel == channel) {
10058 #ifdef HAVE_PRI
10059 if (pri)
10060 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10061 else
10062 #endif
10063 ast_cli(fd, "Channel: %d\n", tmp->channel);
10064 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10065 ast_cli(fd, "Span: %d\n", tmp->span);
10066 ast_cli(fd, "Extension: %s\n", tmp->exten);
10067 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10068 ast_cli(fd, "Context: %s\n", tmp->context);
10069 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10070 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10071 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10072 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10073 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10074 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10075 ast_cli(fd, "Radio: %d\n", tmp->radio);
10076 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10077 ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");
10078 ast_cli(fd, "Callwait: %s%s%s\n", tmp->subs[SUB_CALLWAIT].owner ? tmp->subs[SUB_CALLWAIT].owner->name : "<None>", tmp->subs[SUB_CALLWAIT].inthreeway ? " (Confed)" : "", tmp->subs[SUB_CALLWAIT].linear ? " (Linear)" : "");
10079 ast_cli(fd, "Threeway: %s%s%s\n", tmp->subs[SUB_THREEWAY].owner ? tmp->subs[SUB_THREEWAY].owner->name : "<None>", tmp->subs[SUB_THREEWAY].inthreeway ? " (Confed)" : "", tmp->subs[SUB_THREEWAY].linear ? " (Linear)" : "");
10080 ast_cli(fd, "Confno: %d\n", tmp->confno);
10081 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10082 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10083 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10084 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10085 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10086 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10087 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10088 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10089 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10090 if (tmp->master)
10091 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10092 for (x = 0; x < MAX_SLAVES; x++) {
10093 if (tmp->slaves[x])
10094 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10096 #ifdef HAVE_PRI
10097 if (tmp->pri) {
10098 ast_cli(fd, "PRI Flags: ");
10099 if (tmp->resetting)
10100 ast_cli(fd, "Resetting ");
10101 if (tmp->call)
10102 ast_cli(fd, "Call ");
10103 if (tmp->bearer)
10104 ast_cli(fd, "Bearer ");
10105 ast_cli(fd, "\n");
10106 if (tmp->logicalspan)
10107 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10108 else
10109 ast_cli(fd, "PRI Logical Span: Implicit\n");
10112 #endif
10113 memset(&ci, 0, sizeof(ci));
10114 ps.channo = tmp->channel;
10115 if (tmp->subs[SUB_REAL].dfd > -1) {
10116 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10117 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10119 #ifdef DAHDI_GETCONFMUTE
10120 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10121 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10123 #endif
10124 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10125 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10126 } else {
10127 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10130 ast_mutex_unlock(lock);
10131 return RESULT_SUCCESS;
10133 tmp = tmp->next;
10136 ast_cli(fd, "Unable to find given channel %d\n", channel);
10137 ast_mutex_unlock(lock);
10138 return RESULT_FAILURE;
10141 static char dahdi_show_cadences_usage[] =
10142 "Usage: dahdi show cadences\n"
10143 " Shows all cadences currently defined\n";
10145 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10147 int i, j;
10148 for (i = 0; i < num_cadence; i++) {
10149 char output[1024];
10150 char tmp[16], tmp2[64];
10151 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10152 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10154 for (j = 0; j < 16; j++) {
10155 if (cadences[i].ringcadence[j] == 0)
10156 break;
10157 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10158 if (cidrings[i] * 2 - 1 == j)
10159 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10160 else
10161 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10162 if (j != 0)
10163 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10164 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10166 ast_cli(fd,"%s\n",output);
10168 return 0;
10171 /* Based on irqmiss.c */
10172 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10173 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10174 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10176 int span;
10177 int res;
10178 char alarms[50];
10180 int ctl;
10181 DAHDI_SPANINFO s;
10183 #ifdef HAVE_ZAPTEL
10184 ctl = open("/dev/zap/ctl", O_RDWR);
10185 #else
10186 ctl = open("/dev/dahdi/ctl", O_RDWR);
10187 #endif
10188 if (ctl < 0) {
10189 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10190 ast_cli(fd, "No DAHDI interface found.\n");
10191 return RESULT_FAILURE;
10193 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10195 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10196 s.spanno = span;
10197 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10198 if (res) {
10199 continue;
10201 alarms[0] = '\0';
10202 if (s.alarms > 0) {
10203 if (s.alarms & DAHDI_ALARM_BLUE)
10204 strcat(alarms, "BLU/");
10205 if (s.alarms & DAHDI_ALARM_YELLOW)
10206 strcat(alarms, "YEL/");
10207 if (s.alarms & DAHDI_ALARM_RED)
10208 strcat(alarms, "RED/");
10209 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10210 strcat(alarms, "LB/");
10211 if (s.alarms & DAHDI_ALARM_RECOVER)
10212 strcat(alarms, "REC/");
10213 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10214 strcat(alarms, "NOP/");
10215 if (!strlen(alarms))
10216 strcat(alarms, "UUU/");
10217 if (strlen(alarms)) {
10218 /* Strip trailing / */
10219 alarms[strlen(alarms) - 1] = '\0';
10221 } else {
10222 if (s.numchans)
10223 strcpy(alarms, "OK");
10224 else
10225 strcpy(alarms, "UNCONFIGURED");
10228 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10230 close(ctl);
10232 return RESULT_SUCCESS;
10233 #undef FORMAT
10234 #undef FORMAT2
10237 static char show_channels_usage[] =
10238 "Usage: dahdi show channels\n"
10239 " Shows a list of available channels\n";
10241 static char show_channel_usage[] =
10242 "Usage: dahdi show channel <chan num>\n"
10243 " Detailed information about a given channel\n";
10245 static char dahdi_show_status_usage[] =
10246 "Usage: dahdi show status\n"
10247 " Shows a list of DAHDI cards with status\n";
10249 static char destroy_channel_usage[] =
10250 "Usage: dahdi destroy channel <chan num>\n"
10251 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10253 static char dahdi_restart_usage[] =
10254 "Usage: dahdi restart\n"
10255 " Restarts the DAHDI channels: destroys them all and then\n"
10256 " re-reads them from chan_dahdi.conf.\n"
10257 " Note that this will STOP any running CALL on DAHDI channels.\n"
10260 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10261 { "zap", "show", "cadences", NULL },
10262 handle_dahdi_show_cadences, NULL,
10263 NULL };
10265 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10266 { "zap", "show", "channels", NULL },
10267 dahdi_show_channels, NULL,
10268 NULL };
10270 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10271 { "zap", "show", "channel", NULL },
10272 dahdi_show_channel, NULL,
10273 NULL };
10275 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10276 { "zap", "destroy", "channel", NULL },
10277 dahdi_destroy_channel, NULL,
10278 NULL };
10280 static struct ast_cli_entry cli_zap_restart_deprecated = {
10281 { "zap", "restart", NULL },
10282 dahdi_restart_cmd, NULL,
10283 NULL };
10285 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10286 { "zap", "show", "status", NULL },
10287 dahdi_show_status, NULL,
10288 NULL };
10290 static struct ast_cli_entry dahdi_cli[] = {
10291 { { "dahdi", "show", "cadences", NULL },
10292 handle_dahdi_show_cadences, "List cadences",
10293 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10295 { { "dahdi", "show", "channels", NULL},
10296 dahdi_show_channels, "Show active DAHDI channels",
10297 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10299 { { "dahdi", "show", "channel", NULL},
10300 dahdi_show_channel, "Show information on a channel",
10301 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10303 { { "dahdi", "destroy", "channel", NULL},
10304 dahdi_destroy_channel, "Destroy a channel",
10305 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10307 { { "dahdi", "restart", NULL},
10308 dahdi_restart_cmd, "Fully restart DAHDI channels",
10309 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10311 { { "dahdi", "show", "status", NULL},
10312 dahdi_show_status, "Show all DAHDI cards status",
10313 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10316 #define TRANSFER 0
10317 #define HANGUP 1
10319 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10321 if (p) {
10322 switch (mode) {
10323 case TRANSFER:
10324 p->fake_event = DAHDI_EVENT_WINKFLASH;
10325 break;
10326 case HANGUP:
10327 p->fake_event = DAHDI_EVENT_ONHOOK;
10328 break;
10329 default:
10330 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10333 return 0;
10335 static struct dahdi_pvt *find_channel(int channel)
10337 struct dahdi_pvt *p = iflist;
10338 while (p) {
10339 if (p->channel == channel) {
10340 break;
10342 p = p->next;
10344 return p;
10347 static int action_dahdidndon(struct mansession *s, const struct message *m)
10349 struct dahdi_pvt *p = NULL;
10350 const char *channel = astman_get_header(m, "DAHDIChannel");
10352 if (ast_strlen_zero(channel)) {
10353 astman_send_error(s, m, "No channel specified");
10354 return 0;
10356 p = find_channel(atoi(channel));
10357 if (!p) {
10358 astman_send_error(s, m, "No such channel");
10359 return 0;
10361 p->dnd = 1;
10362 astman_send_ack(s, m, "DND Enabled");
10363 return 0;
10366 static int action_dahdidndoff(struct mansession *s, const struct message *m)
10368 struct dahdi_pvt *p = NULL;
10369 const char *channel = astman_get_header(m, "DAHDIChannel");
10371 if (ast_strlen_zero(channel)) {
10372 astman_send_error(s, m, "No channel specified");
10373 return 0;
10375 p = find_channel(atoi(channel));
10376 if (!p) {
10377 astman_send_error(s, m, "No such channel");
10378 return 0;
10380 p->dnd = 0;
10381 astman_send_ack(s, m, "DND Disabled");
10382 return 0;
10385 static int action_transfer(struct mansession *s, const struct message *m)
10387 struct dahdi_pvt *p = NULL;
10388 const char *channel = astman_get_header(m, "DAHDIChannel");
10390 if (ast_strlen_zero(channel)) {
10391 astman_send_error(s, m, "No channel specified");
10392 return 0;
10394 p = find_channel(atoi(channel));
10395 if (!p) {
10396 astman_send_error(s, m, "No such channel");
10397 return 0;
10399 dahdi_fake_event(p,TRANSFER);
10400 astman_send_ack(s, m, "DAHDITransfer");
10401 return 0;
10404 static int action_transferhangup(struct mansession *s, const struct message *m)
10406 struct dahdi_pvt *p = NULL;
10407 const char *channel = astman_get_header(m, "DAHDIChannel");
10409 if (ast_strlen_zero(channel)) {
10410 astman_send_error(s, m, "No channel specified");
10411 return 0;
10413 p = find_channel(atoi(channel));
10414 if (!p) {
10415 astman_send_error(s, m, "No such channel");
10416 return 0;
10418 dahdi_fake_event(p,HANGUP);
10419 astman_send_ack(s, m, "DAHDIHangup");
10420 return 0;
10423 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
10425 struct dahdi_pvt *p = NULL;
10426 const char *channel = astman_get_header(m, "DAHDIChannel");
10427 const char *number = astman_get_header(m, "Number");
10428 int i;
10430 if (ast_strlen_zero(channel)) {
10431 astman_send_error(s, m, "No channel specified");
10432 return 0;
10434 if (ast_strlen_zero(number)) {
10435 astman_send_error(s, m, "No number specified");
10436 return 0;
10438 p = find_channel(atoi(channel));
10439 if (!p) {
10440 astman_send_error(s, m, "No such channel");
10441 return 0;
10443 if (!p->owner) {
10444 astman_send_error(s, m, "Channel does not have it's owner");
10445 return 0;
10447 for (i = 0; i < strlen(number); i++) {
10448 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10449 dahdi_queue_frame(p, &f, NULL);
10451 astman_send_ack(s, m, "DAHDIDialOffhook");
10452 return 0;
10455 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
10457 struct dahdi_pvt *tmp = NULL;
10458 const char *id = astman_get_header(m, "ActionID");
10459 char idText[256] = "";
10461 astman_send_ack(s, m, "DAHDI channel status will follow");
10462 if (!ast_strlen_zero(id))
10463 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10465 ast_mutex_lock(&iflock);
10467 tmp = iflist;
10468 while (tmp) {
10469 if (tmp->channel > 0) {
10470 int alarm = get_alarms(tmp);
10471 astman_append(s,
10472 "Event: DAHDIShowChannels\r\n"
10473 "Channel: %d\r\n"
10474 "Signalling: %s\r\n"
10475 "Context: %s\r\n"
10476 "DND: %s\r\n"
10477 "Alarm: %s\r\n"
10478 "%s"
10479 "\r\n",
10480 tmp->channel, sig2str(tmp->sig), tmp->context,
10481 tmp->dnd ? "Enabled" : "Disabled",
10482 alarm2str(alarm), idText);
10485 tmp = tmp->next;
10488 ast_mutex_unlock(&iflock);
10490 astman_append(s,
10491 "Event: DAHDIShowChannelsComplete\r\n"
10492 "%s"
10493 "\r\n",
10494 idText);
10495 return 0;
10498 static int __unload_module(void)
10500 int x;
10501 struct dahdi_pvt *p, *pl;
10503 #ifdef HAVE_PRI
10504 int i;
10505 for (i = 0; i < NUM_SPANS; i++) {
10506 if (pris[i].master != AST_PTHREADT_NULL)
10507 pthread_cancel(pris[i].master);
10509 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10510 ast_unregister_application(dahdi_send_keypad_facility_app);
10511 #endif
10512 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10513 ast_manager_unregister( "DAHDIDialOffhook" );
10514 ast_manager_unregister( "DAHDIHangup" );
10515 ast_manager_unregister( "DAHDITransfer" );
10516 ast_manager_unregister( "DAHDIDNDoff" );
10517 ast_manager_unregister( "DAHDIDNDon" );
10518 ast_manager_unregister("DAHDIShowChannels");
10519 ast_manager_unregister("DAHDIRestart");
10520 ast_channel_unregister(&dahdi_tech);
10521 ast_mutex_lock(&iflock);
10522 /* Hangup all interfaces if they have an owner */
10523 p = iflist;
10524 while (p) {
10525 if (p->owner)
10526 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10527 p = p->next;
10529 ast_mutex_unlock(&iflock);
10530 ast_mutex_lock(&monlock);
10531 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10532 pthread_cancel(monitor_thread);
10533 pthread_kill(monitor_thread, SIGURG);
10534 pthread_join(monitor_thread, NULL);
10536 monitor_thread = AST_PTHREADT_STOP;
10537 ast_mutex_unlock(&monlock);
10539 ast_mutex_lock(&iflock);
10540 /* Destroy all the interfaces and free their memory */
10541 p = iflist;
10542 while (p) {
10543 /* Free any callerid */
10544 if (p->cidspill)
10545 free(p->cidspill);
10546 /* Close the DAHDI thingy */
10547 if (p->subs[SUB_REAL].dfd > -1)
10548 dahdi_close(p->subs[SUB_REAL].dfd);
10549 pl = p;
10550 p = p->next;
10551 x = pl->channel;
10552 /* Free associated memory */
10553 if (pl)
10554 destroy_dahdi_pvt(&pl);
10555 ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10557 iflist = NULL;
10558 ifcount = 0;
10559 ast_mutex_unlock(&iflock);
10560 #ifdef HAVE_PRI
10561 for (i = 0; i < NUM_SPANS; i++) {
10562 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10563 pthread_join(pris[i].master, NULL);
10564 dahdi_close(pris[i].fds[i]);
10566 #endif
10567 return 0;
10570 static int unload_module(void)
10572 #ifdef HAVE_PRI
10573 int y;
10574 for (y = 0; y < NUM_SPANS; y++)
10575 ast_mutex_destroy(&pris[y].lock);
10576 #endif
10577 return __unload_module();
10580 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10582 char *c, *chan;
10583 int x, start, finish;
10584 struct dahdi_pvt *tmp;
10585 #ifdef HAVE_PRI
10586 struct dahdi_pri *pri;
10587 int trunkgroup, y;
10588 #endif
10590 if ((reload == 0) && (conf->chan.sig < 0)) {
10591 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10592 return -1;
10595 c = ast_strdupa(value);
10597 #ifdef HAVE_PRI
10598 pri = NULL;
10599 if (iscrv) {
10600 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10601 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10602 return -1;
10604 if (trunkgroup < 1) {
10605 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10606 return -1;
10608 c += y;
10609 for (y = 0; y < NUM_SPANS; y++) {
10610 if (pris[y].trunkgroup == trunkgroup) {
10611 pri = pris + y;
10612 break;
10615 if (!pri) {
10616 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10617 return -1;
10620 #endif
10622 while ((chan = strsep(&c, ","))) {
10623 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10624 /* Range */
10625 } else if (sscanf(chan, "%d", &start)) {
10626 /* Just one */
10627 finish = start;
10628 } else if (!strcasecmp(chan, "pseudo")) {
10629 finish = start = CHAN_PSEUDO;
10630 if (found_pseudo)
10631 *found_pseudo = 1;
10632 } else {
10633 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10634 return -1;
10636 if (finish < start) {
10637 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10638 x = finish;
10639 finish = start;
10640 start = x;
10643 for (x = start; x <= finish; x++) {
10644 #ifdef HAVE_PRI
10645 tmp = mkintf(x, conf, pri, reload);
10646 #else
10647 tmp = mkintf(x, conf, NULL, reload);
10648 #endif
10650 if (tmp) {
10651 if (option_verbose > 2) {
10652 #ifdef HAVE_PRI
10653 if (pri)
10654 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10655 else
10656 #endif
10657 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10659 } else {
10660 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10661 (reload == 1) ? "reconfigure" : "register", value);
10662 return -1;
10667 return 0;
10670 /** The length of the parameters list of 'dahdichan'.
10671 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10672 #define MAX_CHANLIST_LEN 80
10673 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10675 struct dahdi_pvt *tmp;
10676 char *ringc; /* temporary string for parsing the dring number. */
10677 int y;
10678 int found_pseudo = 0;
10679 char dahdichan[MAX_CHANLIST_LEN] = {};
10681 for (; v; v = v->next) {
10682 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10683 continue;
10685 /* Create the interface list */
10686 if (!strcasecmp(v->name, "channel")
10687 #ifdef HAVE_PRI
10688 || !strcasecmp(v->name, "crv")
10689 #endif
10691 int iscrv;
10692 if (skipchannels)
10693 continue;
10694 iscrv = !strcasecmp(v->name, "crv");
10695 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
10696 return -1;
10697 } else if (!strcasecmp(v->name, "dahdichan")) {
10698 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
10699 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
10700 if (ast_true(v->value))
10701 confp->chan.usedistinctiveringdetection = 1;
10702 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
10703 if (ast_true(v->value))
10704 distinctiveringaftercid = 1;
10705 } else if (!strcasecmp(v->name, "dring1context")) {
10706 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
10707 } else if (!strcasecmp(v->name, "dring2context")) {
10708 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
10709 } else if (!strcasecmp(v->name, "dring3context")) {
10710 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
10711 } else if (!strcasecmp(v->name, "dring1")) {
10712 ringc = v->value;
10713 sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
10714 } else if (!strcasecmp(v->name, "dring2")) {
10715 ringc = v->value;
10716 sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
10717 } else if (!strcasecmp(v->name, "dring3")) {
10718 ringc = v->value;
10719 sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
10720 } else if (!strcasecmp(v->name, "usecallerid")) {
10721 confp->chan.use_callerid = ast_true(v->value);
10722 } else if (!strcasecmp(v->name, "cidsignalling")) {
10723 if (!strcasecmp(v->value, "bell"))
10724 confp->chan.cid_signalling = CID_SIG_BELL;
10725 else if (!strcasecmp(v->value, "v23"))
10726 confp->chan.cid_signalling = CID_SIG_V23;
10727 else if (!strcasecmp(v->value, "dtmf"))
10728 confp->chan.cid_signalling = CID_SIG_DTMF;
10729 else if (!strcasecmp(v->value, "smdi"))
10730 confp->chan.cid_signalling = CID_SIG_SMDI;
10731 else if (!strcasecmp(v->value, "v23_jp"))
10732 confp->chan.cid_signalling = CID_SIG_V23_JP;
10733 else if (ast_true(v->value))
10734 confp->chan.cid_signalling = CID_SIG_BELL;
10735 } else if (!strcasecmp(v->name, "cidstart")) {
10736 if (!strcasecmp(v->value, "ring"))
10737 confp->chan.cid_start = CID_START_RING;
10738 else if (!strcasecmp(v->value, "polarity"))
10739 confp->chan.cid_start = CID_START_POLARITY;
10740 else if (ast_true(v->value))
10741 confp->chan.cid_start = CID_START_RING;
10742 } else if (!strcasecmp(v->name, "threewaycalling")) {
10743 confp->chan.threewaycalling = ast_true(v->value);
10744 } else if (!strcasecmp(v->name, "cancallforward")) {
10745 confp->chan.cancallforward = ast_true(v->value);
10746 } else if (!strcasecmp(v->name, "relaxdtmf")) {
10747 if (ast_true(v->value))
10748 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
10749 else
10750 confp->chan.dtmfrelax = 0;
10751 } else if (!strcasecmp(v->name, "mailbox")) {
10752 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
10753 } else if (!strcasecmp(v->name, "hasvoicemail")) {
10754 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
10755 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
10757 } else if (!strcasecmp(v->name, "adsi")) {
10758 confp->chan.adsi = ast_true(v->value);
10759 } else if (!strcasecmp(v->name, "usesmdi")) {
10760 confp->chan.use_smdi = ast_true(v->value);
10761 } else if (!strcasecmp(v->name, "smdiport")) {
10762 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
10763 } else if (!strcasecmp(v->name, "transfer")) {
10764 confp->chan.transfer = ast_true(v->value);
10765 } else if (!strcasecmp(v->name, "canpark")) {
10766 confp->chan.canpark = ast_true(v->value);
10767 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
10768 confp->chan.echocanbridged = ast_true(v->value);
10769 } else if (!strcasecmp(v->name, "busydetect")) {
10770 confp->chan.busydetect = ast_true(v->value);
10771 } else if (!strcasecmp(v->name, "busycount")) {
10772 confp->chan.busycount = atoi(v->value);
10773 } else if (!strcasecmp(v->name, "busypattern")) {
10774 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
10775 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
10777 } else if (!strcasecmp(v->name, "callprogress")) {
10778 if (ast_true(v->value))
10779 confp->chan.callprogress |= 1;
10780 else
10781 confp->chan.callprogress &= ~1;
10782 } else if (!strcasecmp(v->name, "faxdetect")) {
10783 if (!strcasecmp(v->value, "incoming")) {
10784 confp->chan.callprogress |= 4;
10785 confp->chan.callprogress &= ~2;
10786 } else if (!strcasecmp(v->value, "outgoing")) {
10787 confp->chan.callprogress &= ~4;
10788 confp->chan.callprogress |= 2;
10789 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
10790 confp->chan.callprogress |= 6;
10791 else
10792 confp->chan.callprogress &= ~6;
10793 } else if (!strcasecmp(v->name, "echocancel")) {
10794 if (!ast_strlen_zero(v->value)) {
10795 y = atoi(v->value);
10796 } else
10797 y = 0;
10798 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
10799 confp->chan.echocancel = y;
10800 else {
10801 confp->chan.echocancel = ast_true(v->value);
10802 if (confp->chan.echocancel)
10803 confp->chan.echocancel=128;
10805 } else if (!strcasecmp(v->name, "echotraining")) {
10806 if (sscanf(v->value, "%d", &y) == 1) {
10807 if ((y < 10) || (y > 4000)) {
10808 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
10809 } else {
10810 confp->chan.echotraining = y;
10812 } else if (ast_true(v->value)) {
10813 confp->chan.echotraining = 400;
10814 } else
10815 confp->chan.echotraining = 0;
10816 } else if (!strcasecmp(v->name, "hidecallerid")) {
10817 confp->chan.hidecallerid = ast_true(v->value);
10818 } else if (!strcasecmp(v->name, "hidecalleridname")) {
10819 confp->chan.hidecalleridname = ast_true(v->value);
10820 } else if (!strcasecmp(v->name, "pulsedial")) {
10821 confp->chan.pulse = ast_true(v->value);
10822 } else if (!strcasecmp(v->name, "callreturn")) {
10823 confp->chan.callreturn = ast_true(v->value);
10824 } else if (!strcasecmp(v->name, "callwaiting")) {
10825 confp->chan.callwaiting = ast_true(v->value);
10826 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
10827 confp->chan.callwaitingcallerid = ast_true(v->value);
10828 } else if (!strcasecmp(v->name, "context")) {
10829 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
10830 } else if (!strcasecmp(v->name, "language")) {
10831 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
10832 } else if (!strcasecmp(v->name, "progzone")) {
10833 ast_copy_string(progzone, v->value, sizeof(progzone));
10834 } else if (!strcasecmp(v->name, "mohinterpret")
10835 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
10836 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
10837 } else if (!strcasecmp(v->name, "mohsuggest")) {
10838 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
10839 } else if (!strcasecmp(v->name, "stripmsd")) {
10840 confp->chan.stripmsd = atoi(v->value);
10841 } else if (!strcasecmp(v->name, "jitterbuffers")) {
10842 numbufs = atoi(v->value);
10843 } else if (!strcasecmp(v->name, "group")) {
10844 confp->chan.group = ast_get_group(v->value);
10845 } else if (!strcasecmp(v->name, "callgroup")) {
10846 confp->chan.callgroup = ast_get_group(v->value);
10847 } else if (!strcasecmp(v->name, "pickupgroup")) {
10848 confp->chan.pickupgroup = ast_get_group(v->value);
10849 } else if (!strcasecmp(v->name, "immediate")) {
10850 confp->chan.immediate = ast_true(v->value);
10851 } else if (!strcasecmp(v->name, "transfertobusy")) {
10852 confp->chan.transfertobusy = ast_true(v->value);
10853 } else if (!strcasecmp(v->name, "rxgain")) {
10854 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
10855 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
10857 } else if (!strcasecmp(v->name, "txgain")) {
10858 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
10859 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
10861 } else if (!strcasecmp(v->name, "tonezone")) {
10862 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
10863 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
10865 } else if (!strcasecmp(v->name, "callerid")) {
10866 if (!strcasecmp(v->value, "asreceived")) {
10867 confp->chan.cid_num[0] = '\0';
10868 confp->chan.cid_name[0] = '\0';
10869 } else {
10870 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
10872 } else if (!strcasecmp(v->name, "fullname")) {
10873 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
10874 } else if (!strcasecmp(v->name, "cid_number")) {
10875 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
10876 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
10877 confp->chan.dahditrcallerid = ast_true(v->value);
10878 } else if (!strcasecmp(v->name, "restrictcid")) {
10879 confp->chan.restrictcid = ast_true(v->value);
10880 } else if (!strcasecmp(v->name, "usecallingpres")) {
10881 confp->chan.use_callingpres = ast_true(v->value);
10882 } else if (!strcasecmp(v->name, "accountcode")) {
10883 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
10884 } else if (!strcasecmp(v->name, "amaflags")) {
10885 y = ast_cdr_amaflags2int(v->value);
10886 if (y < 0)
10887 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
10888 else
10889 confp->chan.amaflags = y;
10890 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
10891 confp->chan.polarityonanswerdelay = atoi(v->value);
10892 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
10893 confp->chan.answeronpolarityswitch = ast_true(v->value);
10894 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
10895 confp->chan.hanguponpolarityswitch = ast_true(v->value);
10896 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
10897 confp->chan.sendcalleridafter = atoi(v->value);
10898 } else if (!reload){
10899 if (!strcasecmp(v->name, "signalling")) {
10900 confp->chan.outsigmod = -1;
10901 if (!strcasecmp(v->value, "em")) {
10902 confp->chan.sig = SIG_EM;
10903 } else if (!strcasecmp(v->value, "em_e1")) {
10904 confp->chan.sig = SIG_EM_E1;
10905 } else if (!strcasecmp(v->value, "em_w")) {
10906 confp->chan.sig = SIG_EMWINK;
10907 confp->chan.radio = 0;
10908 } else if (!strcasecmp(v->value, "fxs_ls")) {
10909 confp->chan.sig = SIG_FXSLS;
10910 confp->chan.radio = 0;
10911 } else if (!strcasecmp(v->value, "fxs_gs")) {
10912 confp->chan.sig = SIG_FXSGS;
10913 confp->chan.radio = 0;
10914 } else if (!strcasecmp(v->value, "fxs_ks")) {
10915 confp->chan.sig = SIG_FXSKS;
10916 confp->chan.radio = 0;
10917 } else if (!strcasecmp(v->value, "fxo_ls")) {
10918 confp->chan.sig = SIG_FXOLS;
10919 confp->chan.radio = 0;
10920 } else if (!strcasecmp(v->value, "fxo_gs")) {
10921 confp->chan.sig = SIG_FXOGS;
10922 confp->chan.radio = 0;
10923 } else if (!strcasecmp(v->value, "fxo_ks")) {
10924 confp->chan.sig = SIG_FXOKS;
10925 confp->chan.radio = 0;
10926 } else if (!strcasecmp(v->value, "fxs_rx")) {
10927 confp->chan.sig = SIG_FXSKS;
10928 confp->chan.radio = 1;
10929 } else if (!strcasecmp(v->value, "fxo_rx")) {
10930 confp->chan.sig = SIG_FXOLS;
10931 confp->chan.radio = 1;
10932 } else if (!strcasecmp(v->value, "fxs_tx")) {
10933 confp->chan.sig = SIG_FXSLS;
10934 confp->chan.radio = 1;
10935 } else if (!strcasecmp(v->value, "fxo_tx")) {
10936 confp->chan.sig = SIG_FXOGS;
10937 confp->chan.radio = 1;
10938 } else if (!strcasecmp(v->value, "em_rx")) {
10939 confp->chan.sig = SIG_EM;
10940 confp->chan.radio = 1;
10941 } else if (!strcasecmp(v->value, "em_tx")) {
10942 confp->chan.sig = SIG_EM;
10943 confp->chan.radio = 1;
10944 } else if (!strcasecmp(v->value, "em_rxtx")) {
10945 confp->chan.sig = SIG_EM;
10946 confp->chan.radio = 2;
10947 } else if (!strcasecmp(v->value, "em_txrx")) {
10948 confp->chan.sig = SIG_EM;
10949 confp->chan.radio = 2;
10950 } else if (!strcasecmp(v->value, "sf")) {
10951 confp->chan.sig = SIG_SF;
10952 confp->chan.radio = 0;
10953 } else if (!strcasecmp(v->value, "sf_w")) {
10954 confp->chan.sig = SIG_SFWINK;
10955 confp->chan.radio = 0;
10956 } else if (!strcasecmp(v->value, "sf_featd")) {
10957 confp->chan.sig = SIG_FEATD;
10958 confp->chan.radio = 0;
10959 } else if (!strcasecmp(v->value, "sf_featdmf")) {
10960 confp->chan.sig = SIG_FEATDMF;
10961 confp->chan.radio = 0;
10962 } else if (!strcasecmp(v->value, "sf_featb")) {
10963 confp->chan.sig = SIG_SF_FEATB;
10964 confp->chan.radio = 0;
10965 } else if (!strcasecmp(v->value, "sf")) {
10966 confp->chan.sig = SIG_SF;
10967 confp->chan.radio = 0;
10968 } else if (!strcasecmp(v->value, "sf_rx")) {
10969 confp->chan.sig = SIG_SF;
10970 confp->chan.radio = 1;
10971 } else if (!strcasecmp(v->value, "sf_tx")) {
10972 confp->chan.sig = SIG_SF;
10973 confp->chan.radio = 1;
10974 } else if (!strcasecmp(v->value, "sf_rxtx")) {
10975 confp->chan.sig = SIG_SF;
10976 confp->chan.radio = 2;
10977 } else if (!strcasecmp(v->value, "sf_txrx")) {
10978 confp->chan.sig = SIG_SF;
10979 confp->chan.radio = 2;
10980 } else if (!strcasecmp(v->value, "featd")) {
10981 confp->chan.sig = SIG_FEATD;
10982 confp->chan.radio = 0;
10983 } else if (!strcasecmp(v->value, "featdmf")) {
10984 confp->chan.sig = SIG_FEATDMF;
10985 confp->chan.radio = 0;
10986 } else if (!strcasecmp(v->value, "featdmf_ta")) {
10987 confp->chan.sig = SIG_FEATDMF_TA;
10988 confp->chan.radio = 0;
10989 } else if (!strcasecmp(v->value, "e911")) {
10990 confp->chan.sig = SIG_E911;
10991 confp->chan.radio = 0;
10992 } else if (!strcasecmp(v->value, "fgccama")) {
10993 confp->chan.sig = SIG_FGC_CAMA;
10994 confp->chan.radio = 0;
10995 } else if (!strcasecmp(v->value, "fgccamamf")) {
10996 confp->chan.sig = SIG_FGC_CAMAMF;
10997 confp->chan.radio = 0;
10998 } else if (!strcasecmp(v->value, "featb")) {
10999 confp->chan.sig = SIG_FEATB;
11000 confp->chan.radio = 0;
11001 #ifdef HAVE_PRI
11002 } else if (!strcasecmp(v->value, "pri_net")) {
11003 confp->chan.radio = 0;
11004 confp->chan.sig = SIG_PRI;
11005 confp->pri.nodetype = PRI_NETWORK;
11006 } else if (!strcasecmp(v->value, "pri_cpe")) {
11007 confp->chan.sig = SIG_PRI;
11008 confp->chan.radio = 0;
11009 confp->pri.nodetype = PRI_CPE;
11010 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11011 confp->chan.sig = SIG_GR303FXOKS;
11012 confp->chan.radio = 0;
11013 confp->pri.nodetype = PRI_NETWORK;
11014 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11015 confp->chan.sig = SIG_GR303FXSKS;
11016 confp->chan.radio = 0;
11017 confp->pri.nodetype = PRI_CPE;
11018 #endif
11019 } else {
11020 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11022 } else if (!strcasecmp(v->name, "outsignalling")) {
11023 if (!strcasecmp(v->value, "em")) {
11024 confp->chan.outsigmod = SIG_EM;
11025 } else if (!strcasecmp(v->value, "em_e1")) {
11026 confp->chan.outsigmod = SIG_EM_E1;
11027 } else if (!strcasecmp(v->value, "em_w")) {
11028 confp->chan.outsigmod = SIG_EMWINK;
11029 } else if (!strcasecmp(v->value, "sf")) {
11030 confp->chan.outsigmod = SIG_SF;
11031 } else if (!strcasecmp(v->value, "sf_w")) {
11032 confp->chan.outsigmod = SIG_SFWINK;
11033 } else if (!strcasecmp(v->value, "sf_featd")) {
11034 confp->chan.outsigmod = SIG_FEATD;
11035 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11036 confp->chan.outsigmod = SIG_FEATDMF;
11037 } else if (!strcasecmp(v->value, "sf_featb")) {
11038 confp->chan.outsigmod = SIG_SF_FEATB;
11039 } else if (!strcasecmp(v->value, "sf")) {
11040 confp->chan.outsigmod = SIG_SF;
11041 } else if (!strcasecmp(v->value, "featd")) {
11042 confp->chan.outsigmod = SIG_FEATD;
11043 } else if (!strcasecmp(v->value, "featdmf")) {
11044 confp->chan.outsigmod = SIG_FEATDMF;
11045 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11046 confp->chan.outsigmod = SIG_FEATDMF_TA;
11047 } else if (!strcasecmp(v->value, "e911")) {
11048 confp->chan.outsigmod = SIG_E911;
11049 } else if (!strcasecmp(v->value, "fgccama")) {
11050 confp->chan.outsigmod = SIG_FGC_CAMA;
11051 } else if (!strcasecmp(v->value, "fgccamamf")) {
11052 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11053 } else if (!strcasecmp(v->value, "featb")) {
11054 confp->chan.outsigmod = SIG_FEATB;
11055 } else {
11056 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11058 #ifdef HAVE_PRI
11059 } else if (!strcasecmp(v->name, "pridialplan")) {
11060 if (!strcasecmp(v->value, "national")) {
11061 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11062 } else if (!strcasecmp(v->value, "unknown")) {
11063 confp->pri.dialplan = PRI_UNKNOWN + 1;
11064 } else if (!strcasecmp(v->value, "private")) {
11065 confp->pri.dialplan = PRI_PRIVATE + 1;
11066 } else if (!strcasecmp(v->value, "international")) {
11067 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11068 } else if (!strcasecmp(v->value, "local")) {
11069 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11070 } else if (!strcasecmp(v->value, "dynamic")) {
11071 confp->pri.dialplan = -1;
11072 } else {
11073 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11075 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11076 if (!strcasecmp(v->value, "national")) {
11077 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11078 } else if (!strcasecmp(v->value, "unknown")) {
11079 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11080 } else if (!strcasecmp(v->value, "private")) {
11081 confp->pri.localdialplan = PRI_PRIVATE + 1;
11082 } else if (!strcasecmp(v->value, "international")) {
11083 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11084 } else if (!strcasecmp(v->value, "local")) {
11085 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11086 } else if (!strcasecmp(v->value, "dynamic")) {
11087 confp->pri.localdialplan = -1;
11088 } else {
11089 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11091 } else if (!strcasecmp(v->name, "switchtype")) {
11092 if (!strcasecmp(v->value, "national"))
11093 confp->pri.switchtype = PRI_SWITCH_NI2;
11094 else if (!strcasecmp(v->value, "ni1"))
11095 confp->pri.switchtype = PRI_SWITCH_NI1;
11096 else if (!strcasecmp(v->value, "dms100"))
11097 confp->pri.switchtype = PRI_SWITCH_DMS100;
11098 else if (!strcasecmp(v->value, "4ess"))
11099 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11100 else if (!strcasecmp(v->value, "5ess"))
11101 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11102 else if (!strcasecmp(v->value, "euroisdn"))
11103 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11104 else if (!strcasecmp(v->value, "qsig"))
11105 confp->pri.switchtype = PRI_SWITCH_QSIG;
11106 else {
11107 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11108 return -1;
11110 } else if (!strcasecmp(v->name, "nsf")) {
11111 if (!strcasecmp(v->value, "sdn"))
11112 confp->pri.nsf = PRI_NSF_SDN;
11113 else if (!strcasecmp(v->value, "megacom"))
11114 confp->pri.nsf = PRI_NSF_MEGACOM;
11115 else if (!strcasecmp(v->value, "tollfreemegacom"))
11116 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11117 else if (!strcasecmp(v->value, "accunet"))
11118 confp->pri.nsf = PRI_NSF_ACCUNET;
11119 else if (!strcasecmp(v->value, "none"))
11120 confp->pri.nsf = PRI_NSF_NONE;
11121 else {
11122 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11123 confp->pri.nsf = PRI_NSF_NONE;
11125 } else if (!strcasecmp(v->name, "priindication")) {
11126 if (!strcasecmp(v->value, "outofband"))
11127 confp->chan.priindication_oob = 1;
11128 else if (!strcasecmp(v->value, "inband"))
11129 confp->chan.priindication_oob = 0;
11130 else
11131 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11132 v->value, v->lineno);
11133 } else if (!strcasecmp(v->name, "priexclusive")) {
11134 confp->chan.priexclusive = ast_true(v->value);
11135 } else if (!strcasecmp(v->name, "internationalprefix")) {
11136 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11137 } else if (!strcasecmp(v->name, "nationalprefix")) {
11138 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11139 } else if (!strcasecmp(v->name, "localprefix")) {
11140 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11141 } else if (!strcasecmp(v->name, "privateprefix")) {
11142 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11143 } else if (!strcasecmp(v->name, "unknownprefix")) {
11144 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11145 } else if (!strcasecmp(v->name, "resetinterval")) {
11146 if (!strcasecmp(v->value, "never"))
11147 confp->pri.resetinterval = -1;
11148 else if (atoi(v->value) >= 60)
11149 confp->pri.resetinterval = atoi(v->value);
11150 else
11151 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11152 v->value, v->lineno);
11153 } else if (!strcasecmp(v->name, "minunused")) {
11154 confp->pri.minunused = atoi(v->value);
11155 } else if (!strcasecmp(v->name, "minidle")) {
11156 confp->pri.minidle = atoi(v->value);
11157 } else if (!strcasecmp(v->name, "idleext")) {
11158 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11159 } else if (!strcasecmp(v->name, "idledial")) {
11160 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11161 } else if (!strcasecmp(v->name, "overlapdial")) {
11162 confp->pri.overlapdial = ast_true(v->value);
11163 #ifdef HAVE_PRI_INBANDRELEASE
11164 } else if (!strcasecmp(v->name, "inbandrelease")) {
11165 confp->pri.inbandrelease = ast_true(v->value);
11166 #endif
11167 } else if (!strcasecmp(v->name, "pritimer")) {
11168 #ifdef PRI_GETSET_TIMERS
11169 char *timerc, *c;
11170 int timer, timeridx;
11171 c = v->value;
11172 timerc = strsep(&c, ",");
11173 if (timerc) {
11174 timer = atoi(c);
11175 if (!timer)
11176 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11177 else {
11178 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11179 pritimers[timeridx] = timer;
11180 else
11181 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11183 } else
11184 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11186 } else if (!strcasecmp(v->name, "facilityenable")) {
11187 confp->pri.facilityenable = ast_true(v->value);
11188 #endif /* PRI_GETSET_TIMERS */
11189 #endif /* HAVE_PRI */
11190 } else if (!strcasecmp(v->name, "cadence")) {
11191 /* setup to scan our argument */
11192 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11193 int i;
11194 struct dahdi_ring_cadence new_cadence;
11195 int cid_location = -1;
11196 int firstcadencepos = 0;
11197 char original_args[80];
11198 int cadence_is_ok = 1;
11200 ast_copy_string(original_args, v->value, sizeof(original_args));
11201 /* 16 cadences allowed (8 pairs) */
11202 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]);
11204 /* Cadence must be even (on/off) */
11205 if (element_count % 2 == 1) {
11206 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11207 cadence_is_ok = 0;
11210 /* Ring cadences cannot be negative */
11211 for (i = 0; i < element_count; i++) {
11212 if (c[i] == 0) {
11213 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11214 cadence_is_ok = 0;
11215 break;
11216 } else if (c[i] < 0) {
11217 if (i % 2 == 1) {
11218 /* Silence duration, negative possibly okay */
11219 if (cid_location == -1) {
11220 cid_location = i;
11221 c[i] *= -1;
11222 } else {
11223 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11224 cadence_is_ok = 0;
11225 break;
11227 } else {
11228 if (firstcadencepos == 0) {
11229 firstcadencepos = i; /* only recorded to avoid duplicate specification */
11230 /* duration will be passed negative to the DAHDI driver */
11231 } else {
11232 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11233 cadence_is_ok = 0;
11234 break;
11240 /* Substitute our scanned cadence */
11241 for (i = 0; i < 16; i++) {
11242 new_cadence.ringcadence[i] = c[i];
11245 if (cadence_is_ok) {
11246 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11247 if (element_count < 2) {
11248 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11249 } else {
11250 if (cid_location == -1) {
11251 /* user didn't say; default to first pause */
11252 cid_location = 1;
11253 } else {
11254 /* convert element_index to cidrings value */
11255 cid_location = (cid_location + 1) / 2;
11257 /* ---we like their cadence; try to install it--- */
11258 if (!user_has_defined_cadences++)
11259 /* this is the first user-defined cadence; clear the default user cadences */
11260 num_cadence = 0;
11261 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11262 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11263 else {
11264 cadences[num_cadence] = new_cadence;
11265 cidrings[num_cadence++] = cid_location;
11266 if (option_verbose > 2)
11267 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11271 } else if (!strcasecmp(v->name, "ringtimeout")) {
11272 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11273 } else if (!strcasecmp(v->name, "prewink")) {
11274 confp->timing.prewinktime = atoi(v->value);
11275 } else if (!strcasecmp(v->name, "preflash")) {
11276 confp->timing.preflashtime = atoi(v->value);
11277 } else if (!strcasecmp(v->name, "wink")) {
11278 confp->timing.winktime = atoi(v->value);
11279 } else if (!strcasecmp(v->name, "flash")) {
11280 confp->timing.flashtime = atoi(v->value);
11281 } else if (!strcasecmp(v->name, "start")) {
11282 confp->timing.starttime = atoi(v->value);
11283 } else if (!strcasecmp(v->name, "rxwink")) {
11284 confp->timing.rxwinktime = atoi(v->value);
11285 } else if (!strcasecmp(v->name, "rxflash")) {
11286 confp->timing.rxflashtime = atoi(v->value);
11287 } else if (!strcasecmp(v->name, "debounce")) {
11288 confp->timing.debouncetime = atoi(v->value);
11289 } else if (!strcasecmp(v->name, "toneduration")) {
11290 int toneduration;
11291 int ctlfd;
11292 int res;
11293 DAHDI_DIAL_PARAMS dps;
11295 #ifdef HAVE_ZAPTEL
11296 ctlfd = open("/dev/zap/ctl", O_RDWR);
11297 #else
11298 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11299 #endif
11301 if (ctlfd == -1) {
11302 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11303 return -1;
11306 toneduration = atoi(v->value);
11307 if (toneduration > -1) {
11308 memset(&dps, 0, sizeof(dps));
11310 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11311 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11312 if (res < 0) {
11313 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11314 return -1;
11317 close(ctlfd);
11318 } else if (!strcasecmp(v->name, "defaultcic")) {
11319 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11320 } else if (!strcasecmp(v->name, "defaultozz")) {
11321 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11323 } else if (!skipchannels)
11324 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11326 if (dahdichan[0]) {
11327 /* The user has set 'dahdichan' */
11328 /*< \todo pass proper line number instead of 0 */
11329 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11330 return -1;
11333 /*< \todo why check for the pseudo in the per-channel section.
11334 * Any actual use for manual setup of the pseudo channel? */
11335 if (!found_pseudo && reload == 0) {
11336 /* Make sure pseudo isn't a member of any groups if
11337 we're automatically making it. */
11339 confp->chan.group = 0;
11340 confp->chan.callgroup = 0;
11341 confp->chan.pickupgroup = 0;
11343 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11345 if (tmp) {
11346 if (option_verbose > 2)
11347 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11348 } else {
11349 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11352 return 0;
11355 static int setup_dahdi(int reload)
11357 struct ast_config *cfg;
11358 struct ast_variable *v;
11359 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11360 int res;
11362 #ifdef HAVE_PRI
11363 char *c;
11364 int spanno;
11365 int i, x;
11366 int logicalspan;
11367 int trunkgroup;
11368 int dchannels[NUM_DCHANS];
11369 #endif
11371 #ifdef HAVE_ZAPTEL
11372 if (!(cfg = ast_config_load("zapata.conf"))) {
11373 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11374 return 0;
11376 #else
11377 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11378 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11379 return 0;
11381 #endif
11382 /* It's a little silly to lock it, but we mind as well just to be sure */
11383 ast_mutex_lock(&iflock);
11384 #ifdef HAVE_PRI
11385 if (!reload) {
11386 /* Process trunkgroups first */
11387 v = ast_variable_browse(cfg, "trunkgroups");
11388 while (v) {
11389 if (!strcasecmp(v->name, "trunkgroup")) {
11390 trunkgroup = atoi(v->value);
11391 if (trunkgroup > 0) {
11392 if ((c = strchr(v->value, ','))) {
11393 i = 0;
11394 memset(dchannels, 0, sizeof(dchannels));
11395 while (c && (i < NUM_DCHANS)) {
11396 dchannels[i] = atoi(c + 1);
11397 if (dchannels[i] < 0) {
11398 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);
11399 } else
11400 i++;
11401 c = strchr(c + 1, ',');
11403 if (i) {
11404 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11405 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);
11406 } else if (option_verbose > 1)
11407 ast_verbose(VERBOSE_PREFIX_2 "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
11408 } else
11409 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11410 } else
11411 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11412 } else
11413 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11414 } else if (!strcasecmp(v->name, "spanmap")) {
11415 spanno = atoi(v->value);
11416 if (spanno > 0) {
11417 if ((c = strchr(v->value, ','))) {
11418 trunkgroup = atoi(c + 1);
11419 if (trunkgroup > 0) {
11420 if ((c = strchr(c + 1, ',')))
11421 logicalspan = atoi(c + 1);
11422 else
11423 logicalspan = 0;
11424 if (logicalspan >= 0) {
11425 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11426 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11427 } else if (option_verbose > 1)
11428 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11429 } else
11430 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);
11431 } else
11432 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11433 } else
11434 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11435 } else
11436 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11437 } else {
11438 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11440 v = v->next;
11443 #endif
11445 /* Copy the default jb config over global_jbconf */
11446 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11448 v = ast_variable_browse(cfg, "channels");
11449 res = process_dahdi(&conf, "", v, reload, 0);
11450 ast_mutex_unlock(&iflock);
11451 ast_config_destroy(cfg);
11452 if (res)
11453 return res;
11454 cfg = ast_config_load("users.conf");
11455 if (cfg) {
11456 char *cat;
11457 const char *chans;
11458 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11459 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11460 if (!strcasecmp(cat, "general"))
11461 continue;
11462 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11463 if (!ast_strlen_zero(chans)) {
11464 struct dahdi_chan_conf sect_conf;
11465 memcpy(&sect_conf, &conf, sizeof(sect_conf));
11467 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11470 ast_config_destroy(cfg);
11472 #ifdef HAVE_PRI
11473 if (!reload) {
11474 for (x = 0; x < NUM_SPANS; x++) {
11475 if (pris[x].pvts[0]) {
11476 if (start_pri(pris + x)) {
11477 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11478 return -1;
11479 } else if (option_verbose > 1)
11480 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11484 #endif
11485 /* And start the monitor for the first time */
11486 restart_monitor();
11487 return 0;
11490 static int load_module(void)
11492 int res;
11494 #ifdef HAVE_PRI
11495 int y,i;
11496 memset(pris, 0, sizeof(pris));
11497 for (y = 0; y < NUM_SPANS; y++) {
11498 ast_mutex_init(&pris[y].lock);
11499 pris[y].offset = -1;
11500 pris[y].master = AST_PTHREADT_NULL;
11501 for (i = 0; i < NUM_DCHANS; i++)
11502 pris[y].fds[i] = -1;
11504 pri_set_error(dahdi_pri_error);
11505 pri_set_message(dahdi_pri_message);
11506 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11507 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11508 #endif
11509 res = setup_dahdi(0);
11510 /* Make sure we can register our DAHDI channel type */
11511 if (res)
11512 return AST_MODULE_LOAD_DECLINE;
11513 if (ast_channel_register(&dahdi_tech)) {
11514 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
11515 __unload_module();
11516 return -1;
11518 #ifdef HAVE_PRI
11519 ast_string_field_init(&inuse, 16);
11520 ast_string_field_set(&inuse, name, "GR-303InUse");
11521 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11522 #endif
11523 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11525 memset(round_robin, 0, sizeof(round_robin));
11526 ast_manager_register("DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
11527 ast_manager_register("DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
11528 ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
11529 ast_manager_register("DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
11530 ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
11531 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
11532 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
11534 return res;
11537 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11539 #define END_SILENCE_LEN 400
11540 #define HEADER_MS 50
11541 #define TRAILER_MS 5
11542 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11543 #define ASCII_BYTES_PER_CHAR 80
11545 unsigned char *buf,*mybuf;
11546 struct dahdi_pvt *p = c->tech_pvt;
11547 struct pollfd fds[1];
11548 int size,res,fd,len,x;
11549 int bytes=0;
11550 /* Initial carrier (imaginary) */
11551 float cr = 1.0;
11552 float ci = 0.0;
11553 float scont = 0.0;
11554 int index;
11556 index = dahdi_get_index(c, p, 0);
11557 if (index < 0) {
11558 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11559 return -1;
11561 if (!text[0]) return(0); /* if nothing to send, dont */
11562 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
11563 if (p->mate)
11564 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11565 else
11566 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11567 if (!buf)
11568 return -1;
11569 mybuf = buf;
11570 if (p->mate) {
11571 int codec = AST_LAW(p);
11572 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
11573 PUT_CLID_MARKMS;
11575 /* Put actual message */
11576 for (x = 0; text[x]; x++) {
11577 PUT_CLID(text[x]);
11579 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
11580 PUT_CLID_MARKMS;
11582 len = bytes;
11583 buf = mybuf;
11584 } else {
11585 len = tdd_generate(p->tdd, buf, text);
11586 if (len < 1) {
11587 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11588 free(mybuf);
11589 return -1;
11592 memset(buf + len, 0x7f, END_SILENCE_LEN);
11593 len += END_SILENCE_LEN;
11594 fd = p->subs[index].dfd;
11595 while (len) {
11596 if (ast_check_hangup(c)) {
11597 free(mybuf);
11598 return -1;
11600 size = len;
11601 if (size > READ_SIZE)
11602 size = READ_SIZE;
11603 fds[0].fd = fd;
11604 fds[0].events = POLLOUT | POLLPRI;
11605 fds[0].revents = 0;
11606 res = poll(fds, 1, -1);
11607 if (!res) {
11608 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11609 continue;
11611 /* if got exception */
11612 if (fds[0].revents & POLLPRI) {
11613 ast_free(mybuf);
11614 return -1;
11616 if (!(fds[0].revents & POLLOUT)) {
11617 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11618 continue;
11620 res = write(fd, buf, size);
11621 if (res != size) {
11622 if (res == -1) {
11623 free(mybuf);
11624 return -1;
11626 if (option_debug)
11627 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11628 break;
11630 len -= size;
11631 buf += size;
11633 free(mybuf);
11634 return(0);
11638 static int reload(void)
11640 int res = 0;
11642 res = setup_dahdi(1);
11643 if (res) {
11644 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
11645 return -1;
11647 return 0;
11650 /* This is a workaround so that menuselect displays a proper description
11651 * AST_MODULE_INFO(, , "DAHDI Telephony"
11654 #ifdef DAHDI_PRI
11655 #define tdesc "DAHDI Telephony w/PRI"
11656 #else
11657 #define tdesc "DAHDI Telephony"
11658 #endif
11660 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
11661 .load = load_module,
11662 .unload = unload_module,
11663 .reload = reload,