add support for a configuration parameter for 'inband audio during RELEASE', which...
[asterisk-bristuff.git] / channels / chan_dahdi.c
blobe9c99c4eb49030a7789edafce6edf995a36bff9d
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 static const char config[] = "chan_dahdi.conf";
168 #define SIG_EM DAHDI_SIG_EM
169 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
170 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
171 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
172 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
173 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
174 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
175 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
176 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
177 #define SIG_FXSLS DAHDI_SIG_FXSLS
178 #define SIG_FXSGS DAHDI_SIG_FXSGS
179 #define SIG_FXSKS DAHDI_SIG_FXSKS
180 #define SIG_FXOLS DAHDI_SIG_FXOLS
181 #define SIG_FXOGS DAHDI_SIG_FXOGS
182 #define SIG_FXOKS DAHDI_SIG_FXOKS
183 #define SIG_PRI DAHDI_SIG_CLEAR
184 #define SIG_SF DAHDI_SIG_SF
185 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
186 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
187 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
188 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
189 #define SIG_EM_E1 DAHDI_SIG_EM_E1
190 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
191 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
193 #define NUM_SPANS 32
194 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
195 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
197 #define CHAN_PSEUDO -2
199 #define DCHAN_PROVISIONED (1 << 0)
200 #define DCHAN_NOTINALARM (1 << 1)
201 #define DCHAN_UP (1 << 2)
203 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
205 static char defaultcic[64] = "";
206 static char defaultozz[64] = "";
208 static char progzone[10] = "";
210 static int distinctiveringaftercid = 0;
212 static int numbufs = 4;
214 #ifdef HAVE_PRI
215 static struct ast_channel inuse;
216 #ifdef PRI_GETSET_TIMERS
217 static int pritimers[PRI_MAX_TIMERS];
218 #endif
219 static int pridebugfd = -1;
220 static char pridebugfilename[1024] = "";
221 #endif
223 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
224 static int firstdigittimeout = 16000;
226 /*! \brief How long to wait for following digits (FXO logic) */
227 static int gendigittimeout = 8000;
229 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
230 static int matchdigittimeout = 3000;
232 /*! \brief Protect the interface list (of dahdi_pvt's) */
233 AST_MUTEX_DEFINE_STATIC(iflock);
236 static int ifcount = 0;
238 #ifdef HAVE_PRI
239 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
240 #endif
242 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
243 when it's doing something critical. */
244 AST_MUTEX_DEFINE_STATIC(monlock);
246 /*! \brief This is the thread for the monitor which checks for input on the channels
247 which are not currently in use. */
248 static pthread_t monitor_thread = AST_PTHREADT_NULL;
250 static int restart_monitor(void);
252 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
254 static int dahdi_sendtext(struct ast_channel *c, const char *text);
256 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
257 static inline int dahdi_get_event(int fd)
259 int j;
260 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
261 return -1;
262 return j;
265 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
266 static inline int dahdi_wait_event(int fd)
268 int i, j = 0;
269 i = DAHDI_IOMUX_SIGEVENT;
270 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
271 return -1;
272 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
273 return -1;
274 return j;
277 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
278 #define READ_SIZE 160
280 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
281 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
283 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
284 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
285 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
286 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
287 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
289 struct dahdi_pvt;
291 static int ringt_base = DEFAULT_RINGT;
293 #ifdef HAVE_PRI
295 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
296 #define PRI_CHANNEL(p) ((p) & 0xff)
297 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
298 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
300 struct dahdi_pri {
301 pthread_t master; /*!< Thread of master */
302 ast_mutex_t lock; /*!< Mutex */
303 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
304 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
305 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
306 int minunused; /*!< Min # of channels to keep empty */
307 int minidle; /*!< Min # of "idling" calls to keep active */
308 int nodetype; /*!< Node type */
309 int switchtype; /*!< Type of switch to emulate */
310 int nsf; /*!< Network-Specific Facilities */
311 int dialplan; /*!< Dialing plan */
312 int localdialplan; /*!< Local dialing plan */
313 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
314 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
315 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
316 char privateprefix[20]; /*!< for private dialplans */
317 char unknownprefix[20]; /*!< for unknown dialplans */
318 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
319 int trunkgroup; /*!< What our trunkgroup is */
320 int mastertrunkgroup; /*!< What trunk group is our master */
321 int prilogicalspan; /*!< Logical span number within trunk group */
322 int numchans; /*!< Num of channels we represent */
323 int overlapdial; /*!< In overlap dialing mode */
324 int facilityenable; /*!< Enable facility IEs */
325 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
326 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
327 struct pri *pri; /*!< Currently active D-channel */
328 int debug;
329 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
330 int offset;
331 int span;
332 int resetting;
333 int resetpos;
334 #ifdef HAVE_PRI_INBANDRELEASE
335 unsigned int inbandrelease:1; /*!< Should we support inband audio after receiving RELEASE? */
336 #endif
337 time_t lastreset; /*!< time when unused channels were last reset */
338 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
339 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
340 struct dahdi_pvt *crvs; /*!< Member CRV structs */
341 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
345 static struct dahdi_pri pris[NUM_SPANS];
347 #if 0
348 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
349 #else
350 #define DEFAULT_PRI_DEBUG 0
351 #endif
353 static inline void pri_rel(struct dahdi_pri *pri)
355 ast_mutex_unlock(&pri->lock);
358 #else
359 /*! Shut up the compiler */
360 struct dahdi_pri;
361 #endif
363 #define SUB_REAL 0 /*!< Active call */
364 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
365 #define SUB_THREEWAY 2 /*!< Three-way call */
367 /* Polarity states */
368 #define POLARITY_IDLE 0
369 #define POLARITY_REV 1
372 static struct dahdi_distRings drings;
374 struct distRingData {
375 int ring[3];
377 struct ringContextData {
378 char contextData[AST_MAX_CONTEXT];
380 struct dahdi_distRings {
381 struct distRingData ringnum[3];
382 struct ringContextData ringContext[3];
385 static char *subnames[] = {
386 "Real",
387 "Callwait",
388 "Threeway"
391 struct dahdi_subchannel {
392 int dfd;
393 struct ast_channel *owner;
394 int chan;
395 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
396 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
397 unsigned int needringing:1;
398 unsigned int needbusy:1;
399 unsigned int needcongestion:1;
400 unsigned int needcallerid:1;
401 unsigned int needanswer:1;
402 unsigned int needflash:1;
403 unsigned int needhold:1;
404 unsigned int needunhold:1;
405 unsigned int linear:1;
406 unsigned int inthreeway:1;
407 DAHDI_CONFINFO curconf;
410 #define CONF_USER_REAL (1 << 0)
411 #define CONF_USER_THIRDCALL (1 << 1)
413 #define MAX_SLAVES 4
415 static struct dahdi_pvt {
416 ast_mutex_t lock;
417 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
418 /*!< Up to three channels can be associated with this call */
420 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
421 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
422 DAHDI_CONFINFO saveconf; /*!< Saved conference info */
424 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
425 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
426 int inconference; /*!< If our real should be in the conference */
428 int sig; /*!< Signalling style */
429 int radio; /*!< radio type */
430 int outsigmod; /*!< Outbound Signalling style (modifier) */
431 int oprmode; /*!< "Operator Services" mode */
432 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
433 float rxgain;
434 float txgain;
435 int tonezone; /*!< tone zone for this chan, or -1 for default */
436 struct dahdi_pvt *next; /*!< Next channel in list */
437 struct dahdi_pvt *prev; /*!< Prev channel in list */
439 /* flags */
440 unsigned int adsi:1;
441 unsigned int answeronpolarityswitch:1;
442 unsigned int busydetect:1;
443 unsigned int callreturn:1;
444 unsigned int callwaiting:1;
445 unsigned int callwaitingcallerid:1;
446 unsigned int cancallforward:1;
447 unsigned int canpark:1;
448 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
449 unsigned int destroy:1;
450 unsigned int didtdd:1; /*!< flag to say its done it once */
451 unsigned int dialednone:1;
452 unsigned int dialing:1;
453 unsigned int digital:1;
454 unsigned int dnd:1;
455 unsigned int echobreak:1;
456 unsigned int echocanbridged:1;
457 unsigned int echocanon:1;
458 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
459 unsigned int firstradio:1;
460 unsigned int hanguponpolarityswitch:1;
461 unsigned int hardwaredtmf:1;
462 unsigned int hidecallerid:1;
463 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
464 unsigned int ignoredtmf:1;
465 unsigned int immediate:1; /*!< Answer before getting digits? */
466 unsigned int inalarm:1;
467 unsigned int unknown_alarm:1;
468 unsigned int mate:1; /*!< flag to say its in MATE mode */
469 unsigned int outgoing:1;
470 unsigned int overlapdial:1;
471 unsigned int permcallwaiting:1;
472 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
473 unsigned int priindication_oob:1;
474 unsigned int priexclusive:1;
475 unsigned int pulse:1;
476 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
477 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
478 unsigned int threewaycalling:1;
479 unsigned int transfer:1;
480 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
481 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
482 unsigned int usedistinctiveringdetection:1;
483 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
484 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
485 #if defined(HAVE_PRI)
486 unsigned int alerting:1;
487 unsigned int alreadyhungup:1;
488 unsigned int isidlecall:1;
489 unsigned int proceeding:1;
490 unsigned int progress:1;
491 unsigned int resetting:1;
492 unsigned int setup_ack:1;
493 #endif
494 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
495 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
497 struct dahdi_distRings drings;
499 char context[AST_MAX_CONTEXT];
500 char defcontext[AST_MAX_CONTEXT];
501 char exten[AST_MAX_EXTENSION];
502 char language[MAX_LANGUAGE];
503 char mohinterpret[MAX_MUSICCLASS];
504 char mohsuggest[MAX_MUSICCLASS];
505 #ifdef PRI_ANI
506 char cid_ani[AST_MAX_EXTENSION];
507 #endif
508 char cid_num[AST_MAX_EXTENSION];
509 int cid_ton; /*!< Type Of Number (TON) */
510 char cid_name[AST_MAX_EXTENSION];
511 char lastcid_num[AST_MAX_EXTENSION];
512 char lastcid_name[AST_MAX_EXTENSION];
513 char *origcid_num; /*!< malloced original callerid */
514 char *origcid_name; /*!< malloced original callerid */
515 char callwait_num[AST_MAX_EXTENSION];
516 char callwait_name[AST_MAX_EXTENSION];
517 char rdnis[AST_MAX_EXTENSION];
518 char dnid[AST_MAX_EXTENSION];
519 ast_group_t group;
520 int law;
521 int confno; /*!< Our conference */
522 int confusers; /*!< Who is using our conference */
523 int propconfno; /*!< Propagated conference number */
524 ast_group_t callgroup;
525 ast_group_t pickupgroup;
526 int channel; /*!< Channel Number or CRV */
527 int span; /*!< Span number */
528 time_t guardtime; /*!< Must wait this much time before using for new call */
529 int cid_signalling; /*!< CID signalling type bell202 or v23 */
530 int cid_start; /*!< CID start indicator, polarity or ring */
531 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
532 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
533 int cidcwexpire; /*!< When to expire our muting for CID/CW */
534 unsigned char *cidspill;
535 int cidpos;
536 int cidlen;
537 int ringt;
538 int ringt_base;
539 int stripmsd;
540 int callwaitcas;
541 int callwaitrings;
542 int echocancel;
543 int echotraining;
544 char echorest[20];
545 int busycount;
546 int busy_tonelength;
547 int busy_quietlength;
548 int callprogress;
549 struct timeval flashtime; /*!< Last flash-hook time */
550 struct ast_dsp *dsp;
551 int cref; /*!< Call reference number */
552 DAHDI_DIAL_OPERATION dop;
553 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
554 char finaldial[64];
555 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
556 int amaflags; /*!< AMA Flags */
557 struct tdd_state *tdd; /*!< TDD flag */
558 char call_forward[AST_MAX_EXTENSION];
559 char mailbox[AST_MAX_EXTENSION];
560 char dialdest[256];
561 int onhooktime;
562 int msgstate;
563 int distinctivering; /*!< Which distinctivering to use */
564 int cidrings; /*!< Which ring to deliver CID on */
565 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
566 int fake_event;
567 int polarityonanswerdelay;
568 struct timeval polaritydelaytv;
569 int sendcalleridafter;
570 #ifdef HAVE_PRI
571 struct dahdi_pri *pri;
572 struct dahdi_pvt *bearer;
573 struct dahdi_pvt *realcall;
574 q931_call *call;
575 int prioffset;
576 int logicalspan;
577 #endif
578 int polarity;
579 int dsp_features;
580 char begindigit;
581 } *iflist = NULL, *ifend = NULL;
583 /*! \brief Channel configuration from chan_dahdi.conf .
584 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
585 * Generally there is a field here for every possible configuration item.
587 * The state of fields is saved along the parsing and whenever a 'channel'
588 * statement is reached, the current dahdi_chan_conf is used to configure the
589 * channel (struct dahdi_pvt)
591 * @seealso dahdi_chan_init for the default values.
593 struct dahdi_chan_conf {
594 struct dahdi_pvt chan;
595 #ifdef HAVE_PRI
596 struct dahdi_pri pri;
597 #endif
598 DAHDI_PARAMS timing;
600 char smdi_port[SMDI_MAX_FILENAME_LEN];
603 /** returns a new dahdi_chan_conf with default values (by-value) */
604 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
605 /* recall that if a field is not included here it is initialized
606 * to 0 or equivalent
608 struct dahdi_chan_conf conf = {
609 #ifdef HAVE_PRI
610 .pri = {
611 .nsf = PRI_NSF_NONE,
612 .switchtype = PRI_SWITCH_NI2,
613 .dialplan = PRI_NATIONAL_ISDN + 1,
614 .localdialplan = PRI_NATIONAL_ISDN + 1,
615 .nodetype = PRI_CPE,
617 .minunused = 2,
618 .idleext = "",
619 .idledial = "",
620 .internationalprefix = "",
621 .nationalprefix = "",
622 .localprefix = "",
623 .privateprefix = "",
624 .unknownprefix = "",
626 .resetinterval = 3600
628 #endif
629 .chan = {
630 .context = "default",
631 .cid_num = "",
632 .cid_name = "",
633 .mohinterpret = "default",
634 .mohsuggest = "",
635 .transfertobusy = 1,
637 .cid_signalling = CID_SIG_BELL,
638 .cid_start = CID_START_RING,
639 .dahditrcallerid = 0,
640 .use_callerid = 1,
641 .sig = -1,
642 .outsigmod = -1,
644 .tonezone = -1,
646 .echocancel = 1,
648 .busycount = 3,
650 .accountcode = "",
652 .mailbox = "",
655 .polarityonanswerdelay = 600,
657 .sendcalleridafter = DEFAULT_CIDRINGS
659 .timing = {
660 .prewinktime = -1,
661 .preflashtime = -1,
662 .winktime = -1,
663 .flashtime = -1,
664 .starttime = -1,
665 .rxwinktime = -1,
666 .rxflashtime = -1,
667 .debouncetime = -1
669 .smdi_port = "/dev/ttyS0",
672 return conf;
676 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
677 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
678 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
679 static int dahdi_sendtext(struct ast_channel *c, const char *text);
680 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
681 static int dahdi_hangup(struct ast_channel *ast);
682 static int dahdi_answer(struct ast_channel *ast);
683 static struct ast_frame *dahdi_read(struct ast_channel *ast);
684 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
685 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
686 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
687 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
688 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
689 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
691 static const struct ast_channel_tech dahdi_tech = {
692 .type = "DAHDI",
693 .description = tdesc,
694 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
695 .requester = dahdi_request,
696 .send_digit_begin = dahdi_digit_begin,
697 .send_digit_end = dahdi_digit_end,
698 .send_text = dahdi_sendtext,
699 .call = dahdi_call,
700 .hangup = dahdi_hangup,
701 .answer = dahdi_answer,
702 .read = dahdi_read,
703 .write = dahdi_write,
704 .bridge = dahdi_bridge,
705 .exception = dahdi_exception,
706 .indicate = dahdi_indicate,
707 .fixup = dahdi_fixup,
708 .setoption = dahdi_setoption,
709 .func_channel_read = dahdi_func_read,
712 #ifdef HAVE_PRI
713 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
714 #else
715 #define GET_CHANNEL(p) ((p)->channel)
716 #endif
718 struct dahdi_pvt *round_robin[32];
720 #ifdef HAVE_PRI
721 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
723 int res;
724 /* Grab the lock first */
725 do {
726 res = ast_mutex_trylock(&pri->lock);
727 if (res) {
728 DEADLOCK_AVOIDANCE(&pvt->lock);
730 } while (res);
731 /* Then break the poll */
732 pthread_kill(pri->master, SIGURG);
733 return 0;
735 #endif
737 #define NUM_CADENCE_MAX 25
738 static int num_cadence = 4;
739 static int user_has_defined_cadences = 0;
741 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
742 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
743 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
744 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
745 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
748 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
749 * is 1, the second pause is 2 and so on.
752 static int cidrings[NUM_CADENCE_MAX] = {
753 2, /*!< Right after first long ring */
754 4, /*!< Right after long part */
755 3, /*!< After third chirp */
756 2, /*!< Second spell */
759 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
760 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
762 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
763 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
765 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
767 int res;
768 if (p->subs[0].owner == ast)
769 res = 0;
770 else if (p->subs[1].owner == ast)
771 res = 1;
772 else if (p->subs[2].owner == ast)
773 res = 2;
774 else {
775 res = -1;
776 if (!nullok)
777 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
779 return res;
782 #ifdef HAVE_PRI
783 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
784 #else
785 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
786 #endif
788 #ifdef HAVE_PRI
789 if (pri)
790 ast_mutex_unlock(&pri->lock);
791 #endif
792 for (;;) {
793 if (p->subs[a].owner) {
794 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
795 DEADLOCK_AVOIDANCE(&p->lock);
796 } else {
797 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
798 ast_mutex_unlock(&p->subs[a].owner->lock);
799 break;
801 } else
802 break;
804 #ifdef HAVE_PRI
805 if (pri)
806 ast_mutex_lock(&pri->lock);
807 #endif
810 #ifdef HAVE_PRI
811 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
812 #else
813 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
814 #endif
816 /* We must unlock the PRI to avoid the possibility of a deadlock */
817 #ifdef HAVE_PRI
818 if (pri)
819 ast_mutex_unlock(&pri->lock);
820 #endif
821 for (;;) {
822 if (p->owner) {
823 if (ast_mutex_trylock(&p->owner->lock)) {
824 DEADLOCK_AVOIDANCE(&p->lock);
825 } else {
826 ast_queue_frame(p->owner, f);
827 ast_mutex_unlock(&p->owner->lock);
828 break;
830 } else
831 break;
833 #ifdef HAVE_PRI
834 if (pri)
835 ast_mutex_lock(&pri->lock);
836 #endif
839 static int restore_gains(struct dahdi_pvt *p);
841 static void swap_subs(struct dahdi_pvt *p, int a, int b)
843 int tchan;
844 int tinthreeway;
845 struct ast_channel *towner;
847 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
849 tchan = p->subs[a].chan;
850 towner = p->subs[a].owner;
851 tinthreeway = p->subs[a].inthreeway;
853 p->subs[a].chan = p->subs[b].chan;
854 p->subs[a].owner = p->subs[b].owner;
855 p->subs[a].inthreeway = p->subs[b].inthreeway;
857 p->subs[b].chan = tchan;
858 p->subs[b].owner = towner;
859 p->subs[b].inthreeway = tinthreeway;
861 if (p->subs[a].owner)
862 p->subs[a].owner->fds[0] = p->subs[a].dfd;
863 if (p->subs[b].owner)
864 p->subs[b].owner->fds[0] = p->subs[b].dfd;
865 wakeup_sub(p, a, NULL);
866 wakeup_sub(p, b, NULL);
869 static int dahdi_open(char *fn)
871 int fd;
872 int isnum;
873 int chan = 0;
874 int bs;
875 int x;
876 isnum = 1;
877 for (x = 0; x < strlen(fn); x++) {
878 if (!isdigit(fn[x])) {
879 isnum = 0;
880 break;
883 if (isnum) {
884 chan = atoi(fn);
885 if (chan < 1) {
886 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
887 return -1;
889 #ifdef HAVE_ZAPTEL
890 fn = "/dev/zap/channel";
891 #else
892 fn = "/dev/dahdi/channel";
893 #endif
895 fd = open(fn, O_RDWR | O_NONBLOCK);
896 if (fd < 0) {
897 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
898 return -1;
900 if (chan) {
901 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
902 x = errno;
903 close(fd);
904 errno = x;
905 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
906 return -1;
909 bs = READ_SIZE;
910 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
911 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
912 x = errno;
913 close(fd);
914 errno = x;
915 return -1;
917 return fd;
920 static void dahdi_close(int fd)
922 if (fd > 0)
923 close(fd);
926 static int dahdi_setlinear(int dfd, int linear)
928 int res;
929 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
930 if (res)
931 return res;
932 return 0;
936 static int alloc_sub(struct dahdi_pvt *p, int x)
938 DAHDI_BUFFERINFO bi;
939 int res;
940 if (p->subs[x].dfd < 0) {
941 #ifdef HAVE_ZAPTEL
942 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
943 #else
944 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
945 #endif
946 if (p->subs[x].dfd > -1) {
947 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
948 if (!res) {
949 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
950 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
951 bi.numbufs = numbufs;
952 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
953 if (res < 0) {
954 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
956 } else
957 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
958 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
959 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
960 dahdi_close(p->subs[x].dfd);
961 p->subs[x].dfd = -1;
962 return -1;
964 if (option_debug)
965 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
966 return 0;
967 } else
968 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
969 return -1;
971 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
972 return -1;
975 static int unalloc_sub(struct dahdi_pvt *p, int x)
977 if (!x) {
978 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
979 return -1;
981 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
982 if (p->subs[x].dfd > -1) {
983 dahdi_close(p->subs[x].dfd);
985 p->subs[x].dfd = -1;
986 p->subs[x].linear = 0;
987 p->subs[x].chan = 0;
988 p->subs[x].owner = NULL;
989 p->subs[x].inthreeway = 0;
990 p->polarity = POLARITY_IDLE;
991 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
992 return 0;
995 static int digit_to_dtmfindex(char digit)
997 if (isdigit(digit))
998 return DAHDI_TONE_DTMF_BASE + (digit - '0');
999 else if (digit >= 'A' && digit <= 'D')
1000 return DAHDI_TONE_DTMF_A + (digit - 'A');
1001 else if (digit >= 'a' && digit <= 'd')
1002 return DAHDI_TONE_DTMF_A + (digit - 'a');
1003 else if (digit == '*')
1004 return DAHDI_TONE_DTMF_s;
1005 else if (digit == '#')
1006 return DAHDI_TONE_DTMF_p;
1007 else
1008 return -1;
1011 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1013 struct dahdi_pvt *pvt;
1014 int index;
1015 int dtmf = -1;
1017 pvt = chan->tech_pvt;
1019 ast_mutex_lock(&pvt->lock);
1021 index = dahdi_get_index(chan, pvt, 0);
1023 if ((index != SUB_REAL) || !pvt->owner)
1024 goto out;
1026 #ifdef HAVE_PRI
1027 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1028 if (pvt->setup_ack) {
1029 if (!pri_grab(pvt, pvt->pri)) {
1030 pri_information(pvt->pri->pri, pvt->call, digit);
1031 pri_rel(pvt->pri);
1032 } else
1033 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1034 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1035 int res;
1036 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1037 res = strlen(pvt->dialdest);
1038 pvt->dialdest[res++] = digit;
1039 pvt->dialdest[res] = '\0';
1041 goto out;
1043 #endif
1044 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1045 goto out;
1047 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1048 int res;
1049 DAHDI_DIAL_OPERATION zo = {
1050 .op = DAHDI_DIAL_OP_APPEND,
1051 .dialstr[0] = 'T',
1052 .dialstr[1] = digit,
1053 .dialstr[2] = 0,
1055 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1056 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1057 else
1058 pvt->dialing = 1;
1059 } else {
1060 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1061 pvt->dialing = 1;
1062 pvt->begindigit = digit;
1065 out:
1066 ast_mutex_unlock(&pvt->lock);
1068 return 0;
1071 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1073 struct dahdi_pvt *pvt;
1074 int res = 0;
1075 int index;
1076 int x;
1078 pvt = chan->tech_pvt;
1080 ast_mutex_lock(&pvt->lock);
1082 index = dahdi_get_index(chan, pvt, 0);
1084 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1085 goto out;
1087 #ifdef HAVE_PRI
1088 /* This means that the digit was already sent via PRI signalling */
1089 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1090 goto out;
1091 #endif
1093 if (pvt->begindigit) {
1094 x = -1;
1095 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1096 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1097 pvt->dialing = 0;
1098 pvt->begindigit = 0;
1101 out:
1102 ast_mutex_unlock(&pvt->lock);
1104 return res;
1107 static char *events[] = {
1108 "No event",
1109 "On hook",
1110 "Ring/Answered",
1111 "Wink/Flash",
1112 "Alarm",
1113 "No more alarm",
1114 "HDLC Abort",
1115 "HDLC Overrun",
1116 "HDLC Bad FCS",
1117 "Dial Complete",
1118 "Ringer On",
1119 "Ringer Off",
1120 "Hook Transition Complete",
1121 "Bits Changed",
1122 "Pulse Start",
1123 "Timer Expired",
1124 "Timer Ping",
1125 "Polarity Reversal",
1126 "Ring Begin",
1129 static struct {
1130 int alarm;
1131 char *name;
1132 } alarms[] = {
1133 { DAHDI_ALARM_RED, "Red Alarm" },
1134 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1135 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1136 { DAHDI_ALARM_RECOVER, "Recovering" },
1137 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1138 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1139 { DAHDI_ALARM_NONE, "None" },
1142 static char *alarm2str(int alarm)
1144 int x;
1145 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1146 if (alarms[x].alarm & alarm)
1147 return alarms[x].name;
1149 return alarm ? "Unknown Alarm" : "No Alarm";
1152 static char *event2str(int event)
1154 static char buf[256];
1155 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1156 return events[event];
1157 sprintf(buf, "Event %d", event); /* safe */
1158 return buf;
1161 #ifdef HAVE_PRI
1162 static char *dialplan2str(int dialplan)
1164 if (dialplan == -1) {
1165 return("Dynamically set dialplan in ISDN");
1167 return (pri_plan2str(dialplan));
1169 #endif
1171 static char *dahdi_sig2str(int sig)
1173 static char buf[256];
1174 switch (sig) {
1175 case SIG_EM:
1176 return "E & M Immediate";
1177 case SIG_EMWINK:
1178 return "E & M Wink";
1179 case SIG_EM_E1:
1180 return "E & M E1";
1181 case SIG_FEATD:
1182 return "Feature Group D (DTMF)";
1183 case SIG_FEATDMF:
1184 return "Feature Group D (MF)";
1185 case SIG_FEATDMF_TA:
1186 return "Feature Groud D (MF) Tandem Access";
1187 case SIG_FEATB:
1188 return "Feature Group B (MF)";
1189 case SIG_E911:
1190 return "E911 (MF)";
1191 case SIG_FGC_CAMA:
1192 return "FGC/CAMA (Dialpulse)";
1193 case SIG_FGC_CAMAMF:
1194 return "FGC/CAMA (MF)";
1195 case SIG_FXSLS:
1196 return "FXS Loopstart";
1197 case SIG_FXSGS:
1198 return "FXS Groundstart";
1199 case SIG_FXSKS:
1200 return "FXS Kewlstart";
1201 case SIG_FXOLS:
1202 return "FXO Loopstart";
1203 case SIG_FXOGS:
1204 return "FXO Groundstart";
1205 case SIG_FXOKS:
1206 return "FXO Kewlstart";
1207 case SIG_PRI:
1208 return "ISDN PRI";
1209 case SIG_SF:
1210 return "SF (Tone) Immediate";
1211 case SIG_SFWINK:
1212 return "SF (Tone) Wink";
1213 case SIG_SF_FEATD:
1214 return "SF (Tone) with Feature Group D (DTMF)";
1215 case SIG_SF_FEATDMF:
1216 return "SF (Tone) with Feature Group D (MF)";
1217 case SIG_SF_FEATB:
1218 return "SF (Tone) with Feature Group B (MF)";
1219 case SIG_GR303FXOKS:
1220 return "GR-303 with FXOKS";
1221 case SIG_GR303FXSKS:
1222 return "GR-303 with FXSKS";
1223 case 0:
1224 return "Pseudo";
1225 default:
1226 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1227 return buf;
1231 #define sig2str dahdi_sig2str
1233 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1235 /* If the conference already exists, and we're already in it
1236 don't bother doing anything */
1237 DAHDI_CONFINFO zi;
1239 memset(&zi, 0, sizeof(zi));
1240 zi.chan = 0;
1242 if (slavechannel > 0) {
1243 /* If we have only one slave, do a digital mon */
1244 zi.confmode = DAHDI_CONF_DIGITALMON;
1245 zi.confno = slavechannel;
1246 } else {
1247 if (!index) {
1248 /* Real-side and pseudo-side both participate in conference */
1249 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1250 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1251 } else
1252 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1253 zi.confno = p->confno;
1255 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1256 return 0;
1257 if (c->dfd < 0)
1258 return 0;
1259 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1260 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1261 return -1;
1263 if (slavechannel < 1) {
1264 p->confno = zi.confno;
1266 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1267 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1268 return 0;
1271 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1273 /* If they're listening to our channel, they're ours */
1274 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1275 return 1;
1276 /* If they're a talker on our (allocated) conference, they're ours */
1277 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1278 return 1;
1279 return 0;
1282 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1284 DAHDI_CONFINFO zi;
1285 if (/* Can't delete if there's no dfd */
1286 (c->dfd < 0) ||
1287 /* Don't delete from the conference if it's not our conference */
1288 !isourconf(p, c)
1289 /* Don't delete if we don't think it's conferenced at all (implied) */
1290 ) return 0;
1291 memset(&zi, 0, sizeof(zi));
1292 zi.chan = 0;
1293 zi.confno = 0;
1294 zi.confmode = 0;
1295 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1296 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1297 return -1;
1299 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1300 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1301 return 0;
1304 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1306 int x;
1307 int useslavenative;
1308 struct dahdi_pvt *slave = NULL;
1309 /* Start out optimistic */
1310 useslavenative = 1;
1311 /* Update conference state in a stateless fashion */
1312 for (x = 0; x < 3; x++) {
1313 /* Any three-way calling makes slave native mode *definitely* out
1314 of the question */
1315 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1316 useslavenative = 0;
1318 /* If we don't have any 3-way calls, check to see if we have
1319 precisely one slave */
1320 if (useslavenative) {
1321 for (x = 0; x < MAX_SLAVES; x++) {
1322 if (p->slaves[x]) {
1323 if (slave) {
1324 /* Whoops already have a slave! No
1325 slave native and stop right away */
1326 slave = NULL;
1327 useslavenative = 0;
1328 break;
1329 } else {
1330 /* We have one slave so far */
1331 slave = p->slaves[x];
1336 /* If no slave, slave native definitely out */
1337 if (!slave)
1338 useslavenative = 0;
1339 else if (slave->law != p->law) {
1340 useslavenative = 0;
1341 slave = NULL;
1343 if (out)
1344 *out = slave;
1345 return useslavenative;
1348 static int reset_conf(struct dahdi_pvt *p)
1350 DAHDI_CONFINFO zi;
1351 memset(&zi, 0, sizeof(zi));
1352 p->confno = -1;
1353 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1354 if (p->subs[SUB_REAL].dfd > -1) {
1355 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1356 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1358 return 0;
1361 static int update_conf(struct dahdi_pvt *p)
1363 int needconf = 0;
1364 int x;
1365 int useslavenative;
1366 struct dahdi_pvt *slave = NULL;
1368 useslavenative = isslavenative(p, &slave);
1369 /* Start with the obvious, general stuff */
1370 for (x = 0; x < 3; x++) {
1371 /* Look for three way calls */
1372 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1373 conf_add(p, &p->subs[x], x, 0);
1374 needconf++;
1375 } else {
1376 conf_del(p, &p->subs[x], x);
1379 /* If we have a slave, add him to our conference now. or DAX
1380 if this is slave native */
1381 for (x = 0; x < MAX_SLAVES; x++) {
1382 if (p->slaves[x]) {
1383 if (useslavenative)
1384 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1385 else {
1386 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1387 needconf++;
1391 /* If we're supposed to be in there, do so now */
1392 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1393 if (useslavenative)
1394 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1395 else {
1396 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1397 needconf++;
1400 /* If we have a master, add ourselves to his conference */
1401 if (p->master) {
1402 if (isslavenative(p->master, NULL)) {
1403 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1404 } else {
1405 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1408 if (!needconf) {
1409 /* Nobody is left (or should be left) in our conference.
1410 Kill it. */
1411 p->confno = -1;
1413 if (option_debug)
1414 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1415 return 0;
1418 static void dahdi_enable_ec(struct dahdi_pvt *p)
1420 int x;
1421 int res;
1422 if (!p)
1423 return;
1424 if (p->echocanon) {
1425 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1426 return;
1428 if (p->digital) {
1429 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
1430 return;
1432 if (p->echocancel) {
1433 if (p->sig == SIG_PRI) {
1434 x = 1;
1435 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1436 if (res)
1437 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1439 x = p->echocancel;
1440 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1441 if (res)
1442 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1443 else {
1444 p->echocanon = 1;
1445 if (option_debug)
1446 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1448 } else if (option_debug)
1449 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1452 static void dahdi_train_ec(struct dahdi_pvt *p)
1454 int x;
1455 int res;
1456 if (p && p->echocancel && p->echotraining) {
1457 x = p->echotraining;
1458 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1459 if (res)
1460 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1461 else {
1462 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1464 } else
1465 ast_log(LOG_DEBUG, "No echo training requested\n");
1468 static void dahdi_disable_ec(struct dahdi_pvt *p)
1470 int x;
1471 int res;
1472 if (p->echocancel) {
1473 x = 0;
1474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1475 if (res)
1476 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1477 else if (option_debug)
1478 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1480 p->echocanon = 0;
1483 static void fill_txgain(DAHDI_GAINS *g, float gain, int law)
1485 int j;
1486 int k;
1487 float linear_gain = pow(10.0, gain / 20.0);
1489 switch (law) {
1490 case DAHDI_LAW_ALAW:
1491 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1492 if (gain) {
1493 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1494 if (k > 32767) k = 32767;
1495 if (k < -32767) k = -32767;
1496 g->txgain[j] = AST_LIN2A(k);
1497 } else {
1498 g->txgain[j] = j;
1501 break;
1502 case DAHDI_LAW_MULAW:
1503 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1504 if (gain) {
1505 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1506 if (k > 32767) k = 32767;
1507 if (k < -32767) k = -32767;
1508 g->txgain[j] = AST_LIN2MU(k);
1509 } else {
1510 g->txgain[j] = j;
1513 break;
1517 static void fill_rxgain(DAHDI_GAINS *g, float gain, int law)
1519 int j;
1520 int k;
1521 float linear_gain = pow(10.0, gain / 20.0);
1523 switch (law) {
1524 case DAHDI_LAW_ALAW:
1525 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1526 if (gain) {
1527 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1528 if (k > 32767) k = 32767;
1529 if (k < -32767) k = -32767;
1530 g->rxgain[j] = AST_LIN2A(k);
1531 } else {
1532 g->rxgain[j] = j;
1535 break;
1536 case DAHDI_LAW_MULAW:
1537 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1538 if (gain) {
1539 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1540 if (k > 32767) k = 32767;
1541 if (k < -32767) k = -32767;
1542 g->rxgain[j] = AST_LIN2MU(k);
1543 } else {
1544 g->rxgain[j] = j;
1547 break;
1551 static int set_actual_txgain(int fd, int chan, float gain, int law)
1553 DAHDI_GAINS g;
1554 int res;
1556 memset(&g, 0, sizeof(g));
1557 g.chan = chan;
1558 res = ioctl(fd, DAHDI_GETGAINS, &g);
1559 if (res) {
1560 if (option_debug)
1561 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1562 return res;
1565 fill_txgain(&g, gain, law);
1567 return ioctl(fd, DAHDI_SETGAINS, &g);
1570 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1572 DAHDI_GAINS g;
1573 int res;
1575 memset(&g, 0, sizeof(g));
1576 g.chan = chan;
1577 res = ioctl(fd, DAHDI_GETGAINS, &g);
1578 if (res) {
1579 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1580 return res;
1583 fill_rxgain(&g, gain, law);
1585 return ioctl(fd, DAHDI_SETGAINS, &g);
1588 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1590 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1593 static int bump_gains(struct dahdi_pvt *p)
1595 int res;
1597 /* Bump receive gain by 5.0db */
1598 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1599 if (res) {
1600 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1601 return -1;
1604 return 0;
1607 static int restore_gains(struct dahdi_pvt *p)
1609 int res;
1611 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1612 if (res) {
1613 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1614 return -1;
1617 return 0;
1620 static inline int dahdi_set_hook(int fd, int hs)
1622 int x, res;
1624 x = hs;
1625 res = ioctl(fd, DAHDI_HOOK, &x);
1627 if (res < 0) {
1628 if (errno == EINPROGRESS)
1629 return 0;
1630 ast_log(LOG_WARNING, "dahdi hook failed: %s\n", strerror(errno));
1633 return res;
1636 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1638 int x, y, res;
1639 x = muted;
1640 if (p->sig == SIG_PRI) {
1641 y = 1;
1642 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1643 if (res)
1644 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1646 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1647 if (res < 0)
1648 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1649 return res;
1652 static int save_conference(struct dahdi_pvt *p)
1654 DAHDI_CONFINFO c;
1655 int res;
1656 if (p->saveconf.confmode) {
1657 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1658 return -1;
1660 p->saveconf.chan = 0;
1661 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1662 if (res) {
1663 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1664 p->saveconf.confmode = 0;
1665 return -1;
1667 c.chan = 0;
1668 c.confno = 0;
1669 c.confmode = DAHDI_CONF_NORMAL;
1670 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1671 if (res) {
1672 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1673 return -1;
1675 if (option_debug)
1676 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1677 return 0;
1680 static int restore_conference(struct dahdi_pvt *p)
1682 int res;
1683 if (p->saveconf.confmode) {
1684 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1685 p->saveconf.confmode = 0;
1686 if (res) {
1687 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1688 return -1;
1691 if (option_debug)
1692 ast_log(LOG_DEBUG, "Restored conferencing\n");
1693 return 0;
1696 static int send_callerid(struct dahdi_pvt *p);
1698 static int send_cwcidspill(struct dahdi_pvt *p)
1700 p->callwaitcas = 0;
1701 p->cidcwexpire = 0;
1702 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1703 return -1;
1704 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1705 /* Make sure we account for the end */
1706 p->cidlen += READ_SIZE * 4;
1707 p->cidpos = 0;
1708 send_callerid(p);
1709 if (option_verbose > 2)
1710 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1711 return 0;
1714 static int has_voicemail(struct dahdi_pvt *p)
1717 return ast_app_has_voicemail(p->mailbox, NULL);
1720 static int send_callerid(struct dahdi_pvt *p)
1722 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1723 int res;
1724 /* Take out of linear mode if necessary */
1725 if (p->subs[SUB_REAL].linear) {
1726 p->subs[SUB_REAL].linear = 0;
1727 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1729 while (p->cidpos < p->cidlen) {
1730 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1731 if (res < 0) {
1732 if (errno == EAGAIN)
1733 return 0;
1734 else {
1735 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1736 return -1;
1739 if (!res)
1740 return 0;
1741 p->cidpos += res;
1743 free(p->cidspill);
1744 p->cidspill = NULL;
1745 if (p->callwaitcas) {
1746 /* Wait for CID/CW to expire */
1747 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1748 } else
1749 restore_conference(p);
1750 return 0;
1753 static int dahdi_callwait(struct ast_channel *ast)
1755 struct dahdi_pvt *p = ast->tech_pvt;
1756 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1757 if (p->cidspill) {
1758 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1759 free(p->cidspill);
1761 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1762 return -1;
1763 save_conference(p);
1764 /* Silence */
1765 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1766 if (!p->callwaitrings && p->callwaitingcallerid) {
1767 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1768 p->callwaitcas = 1;
1769 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1770 } else {
1771 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1772 p->callwaitcas = 0;
1773 p->cidlen = 2400 + READ_SIZE * 4;
1775 p->cidpos = 0;
1776 send_callerid(p);
1778 return 0;
1781 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1783 struct dahdi_pvt *p = ast->tech_pvt;
1784 int x, res, index,mysig;
1785 char *c, *n, *l;
1786 #ifdef HAVE_PRI
1787 char *s = NULL;
1788 #endif
1789 char dest[256]; /* must be same length as p->dialdest */
1790 ast_mutex_lock(&p->lock);
1791 ast_copy_string(dest, rdest, sizeof(dest));
1792 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1793 if ((ast->_state == AST_STATE_BUSY)) {
1794 p->subs[SUB_REAL].needbusy = 1;
1795 ast_mutex_unlock(&p->lock);
1796 return 0;
1798 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1799 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1800 ast_mutex_unlock(&p->lock);
1801 return -1;
1803 p->dialednone = 0;
1804 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1806 /* Special pseudo -- automatically up */
1807 ast_setstate(ast, AST_STATE_UP);
1808 ast_mutex_unlock(&p->lock);
1809 return 0;
1811 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1812 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1813 if (res)
1814 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1815 p->outgoing = 1;
1817 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1819 mysig = p->sig;
1820 if (p->outsigmod > -1)
1821 mysig = p->outsigmod;
1823 switch (mysig) {
1824 case SIG_FXOLS:
1825 case SIG_FXOGS:
1826 case SIG_FXOKS:
1827 if (p->owner == ast) {
1828 /* Normal ring, on hook */
1830 /* Don't send audio while on hook, until the call is answered */
1831 p->dialing = 1;
1832 if (p->use_callerid) {
1833 /* Generate the Caller-ID spill if desired */
1834 if (p->cidspill) {
1835 ast_log(LOG_WARNING, "cidspill already exists??\n");
1836 free(p->cidspill);
1838 p->callwaitcas = 0;
1839 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1840 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1841 p->cidpos = 0;
1842 send_callerid(p);
1845 /* Choose proper cadence */
1846 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1847 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1848 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1849 p->cidrings = cidrings[p->distinctivering - 1];
1850 } else {
1851 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1852 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1853 p->cidrings = p->sendcalleridafter;
1856 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1857 c = strchr(dest, '/');
1858 if (c)
1859 c++;
1860 if (c && (strlen(c) < p->stripmsd)) {
1861 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1862 c = NULL;
1864 if (c) {
1865 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1866 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
1867 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
1868 } else {
1869 p->dop.dialstr[0] = '\0';
1871 x = DAHDI_RING;
1872 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
1873 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
1874 ast_mutex_unlock(&p->lock);
1875 return -1;
1877 p->dialing = 1;
1878 } else {
1879 /* Call waiting call */
1880 p->callwaitrings = 0;
1881 if (ast->cid.cid_num)
1882 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
1883 else
1884 p->callwait_num[0] = '\0';
1885 if (ast->cid.cid_name)
1886 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
1887 else
1888 p->callwait_name[0] = '\0';
1889 /* Call waiting tone instead */
1890 if (dahdi_callwait(ast)) {
1891 ast_mutex_unlock(&p->lock);
1892 return -1;
1894 /* Make ring-back */
1895 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
1896 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
1899 n = ast->cid.cid_name;
1900 l = ast->cid.cid_num;
1901 if (l)
1902 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
1903 else
1904 p->lastcid_num[0] = '\0';
1905 if (n)
1906 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
1907 else
1908 p->lastcid_name[0] = '\0';
1909 ast_setstate(ast, AST_STATE_RINGING);
1910 index = dahdi_get_index(ast, p, 0);
1911 if (index > -1) {
1912 p->subs[index].needringing = 1;
1914 break;
1915 case SIG_FXSLS:
1916 case SIG_FXSGS:
1917 case SIG_FXSKS:
1918 case SIG_EMWINK:
1919 case SIG_EM:
1920 case SIG_EM_E1:
1921 case SIG_FEATD:
1922 case SIG_FEATDMF:
1923 case SIG_E911:
1924 case SIG_FGC_CAMA:
1925 case SIG_FGC_CAMAMF:
1926 case SIG_FEATB:
1927 case SIG_SFWINK:
1928 case SIG_SF:
1929 case SIG_SF_FEATD:
1930 case SIG_SF_FEATDMF:
1931 case SIG_FEATDMF_TA:
1932 case SIG_SF_FEATB:
1933 c = strchr(dest, '/');
1934 if (c)
1935 c++;
1936 else
1937 c = "";
1938 if (strlen(c) < p->stripmsd) {
1939 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1940 ast_mutex_unlock(&p->lock);
1941 return -1;
1943 #ifdef HAVE_PRI
1944 /* Start the trunk, if not GR-303 */
1945 if (!p->pri) {
1946 #endif
1947 x = DAHDI_START;
1948 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
1949 if (res < 0) {
1950 if (errno != EINPROGRESS) {
1951 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
1952 ast_mutex_unlock(&p->lock);
1953 return -1;
1956 #ifdef HAVE_PRI
1958 #endif
1959 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
1960 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1962 c += p->stripmsd;
1964 switch (mysig) {
1965 case SIG_FEATD:
1966 l = ast->cid.cid_num;
1967 if (l)
1968 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
1969 else
1970 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
1971 break;
1972 case SIG_FEATDMF:
1973 l = ast->cid.cid_num;
1974 if (l)
1975 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
1976 else
1977 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
1978 break;
1979 case SIG_FEATDMF_TA:
1981 const char *cic, *ozz;
1983 /* If you have to go through a Tandem Access point you need to use this */
1984 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
1985 if (!ozz)
1986 ozz = defaultozz;
1987 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
1988 if (!cic)
1989 cic = defaultcic;
1990 if (!ozz || !cic) {
1991 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
1992 ast_mutex_unlock(&p->lock);
1993 return -1;
1995 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
1996 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
1997 p->whichwink = 0;
1999 break;
2000 case SIG_E911:
2001 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2002 break;
2003 case SIG_FGC_CAMA:
2004 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2005 break;
2006 case SIG_FGC_CAMAMF:
2007 case SIG_FEATB:
2008 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2009 break;
2010 default:
2011 if (p->pulse)
2012 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2013 else
2014 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2015 break;
2018 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2019 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2020 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2021 p->echorest[sizeof(p->echorest) - 1] = '\0';
2022 p->echobreak = 1;
2023 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2024 } else
2025 p->echobreak = 0;
2026 if (!res) {
2027 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2028 int saveerr = errno;
2030 x = DAHDI_ONHOOK;
2031 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2032 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2033 ast_mutex_unlock(&p->lock);
2034 return -1;
2036 } else
2037 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2038 p->dialing = 1;
2039 if (ast_strlen_zero(c))
2040 p->dialednone = 1;
2041 ast_setstate(ast, AST_STATE_DIALING);
2042 break;
2043 case 0:
2044 /* Special pseudo -- automatically up*/
2045 ast_setstate(ast, AST_STATE_UP);
2046 break;
2047 case SIG_PRI:
2048 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2049 p->dialdest[0] = '\0';
2050 break;
2051 default:
2052 ast_log(LOG_DEBUG, "not yet implemented\n");
2053 ast_mutex_unlock(&p->lock);
2054 return -1;
2056 #ifdef HAVE_PRI
2057 if (p->pri) {
2058 struct pri_sr *sr;
2059 #ifdef SUPPORT_USERUSER
2060 const char *useruser;
2061 #endif
2062 int pridialplan;
2063 int dp_strip;
2064 int prilocaldialplan;
2065 int ldp_strip;
2066 int exclusive;
2067 const char *rr_str;
2068 int redirect_reason;
2070 c = strchr(dest, '/');
2071 if (c)
2072 c++;
2073 else
2074 c = dest;
2076 l = NULL;
2077 n = NULL;
2079 if (!p->hidecallerid) {
2080 l = ast->cid.cid_num;
2081 if (!p->hidecalleridname) {
2082 n = ast->cid.cid_name;
2087 if (strlen(c) < p->stripmsd) {
2088 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2089 ast_mutex_unlock(&p->lock);
2090 return -1;
2092 if (mysig != SIG_FXSKS) {
2093 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2094 s = strchr(c + p->stripmsd, 'w');
2095 if (s) {
2096 if (strlen(s) > 1)
2097 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2098 else
2099 p->dop.dialstr[0] = '\0';
2100 *s = '\0';
2101 } else {
2102 p->dop.dialstr[0] = '\0';
2105 if (pri_grab(p, p->pri)) {
2106 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2107 ast_mutex_unlock(&p->lock);
2108 return -1;
2110 if (!(p->call = pri_new_call(p->pri->pri))) {
2111 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2112 pri_rel(p->pri);
2113 ast_mutex_unlock(&p->lock);
2114 return -1;
2116 if (!(sr = pri_sr_new())) {
2117 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2118 pri_destroycall(p->pri->pri, p->call);
2119 p->call = NULL;
2120 pri_rel(p->pri);
2121 ast_mutex_unlock(&p->lock);
2122 return -1;
2124 if (p->bearer || (mysig == SIG_FXSKS)) {
2125 if (p->bearer) {
2126 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);
2127 p->bearer->call = p->call;
2128 } else
2129 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2130 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2132 p->digital = IS_DIGITAL(ast->transfercapability);
2133 /* Add support for exclusive override */
2134 if (p->priexclusive)
2135 exclusive = 1;
2136 else {
2137 /* otherwise, traditional behavior */
2138 if (p->pri->nodetype == PRI_NETWORK)
2139 exclusive = 0;
2140 else
2141 exclusive = 1;
2144 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2145 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2146 (p->digital ? -1 :
2147 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2148 if (p->pri->facilityenable)
2149 pri_facility_enable(p->pri->pri);
2151 if (option_verbose > 2)
2152 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2153 dp_strip = 0;
2154 pridialplan = p->pri->dialplan - 1;
2155 if (pridialplan == -2) { /* compute dynamically */
2156 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2157 dp_strip = strlen(p->pri->internationalprefix);
2158 pridialplan = PRI_INTERNATIONAL_ISDN;
2159 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2160 dp_strip = strlen(p->pri->nationalprefix);
2161 pridialplan = PRI_NATIONAL_ISDN;
2162 } else {
2163 pridialplan = PRI_LOCAL_ISDN;
2166 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2168 ldp_strip = 0;
2169 prilocaldialplan = p->pri->localdialplan - 1;
2170 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2171 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2172 ldp_strip = strlen(p->pri->internationalprefix);
2173 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2174 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2175 ldp_strip = strlen(p->pri->nationalprefix);
2176 prilocaldialplan = PRI_NATIONAL_ISDN;
2177 } else {
2178 prilocaldialplan = PRI_LOCAL_ISDN;
2181 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2182 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2183 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2184 if (!strcasecmp(rr_str, "UNKNOWN"))
2185 redirect_reason = 0;
2186 else if (!strcasecmp(rr_str, "BUSY"))
2187 redirect_reason = 1;
2188 else if (!strcasecmp(rr_str, "NO_REPLY"))
2189 redirect_reason = 2;
2190 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2191 redirect_reason = 15;
2192 else
2193 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2194 } else
2195 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2196 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2198 #ifdef SUPPORT_USERUSER
2199 /* User-user info */
2200 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2202 if (useruser)
2203 pri_sr_set_useruser(sr, useruser);
2204 #endif
2206 if (pri_setup(p->pri->pri, p->call, sr)) {
2207 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2208 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2209 pri_rel(p->pri);
2210 ast_mutex_unlock(&p->lock);
2211 pri_sr_free(sr);
2212 return -1;
2214 pri_sr_free(sr);
2215 ast_setstate(ast, AST_STATE_DIALING);
2216 pri_rel(p->pri);
2218 #endif
2219 ast_mutex_unlock(&p->lock);
2220 return 0;
2223 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2225 struct dahdi_pvt *p = *pvt;
2226 /* Remove channel from the list */
2227 if (p->prev)
2228 p->prev->next = p->next;
2229 if (p->next)
2230 p->next->prev = p->prev;
2231 if (p->use_smdi)
2232 ast_smdi_interface_unref(p->smdi_iface);
2233 ast_mutex_destroy(&p->lock);
2234 free(p);
2235 *pvt = NULL;
2238 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2240 int owned = 0;
2241 int i = 0;
2243 if (!now) {
2244 if (cur->owner) {
2245 owned = 1;
2248 for (i = 0; i < 3; i++) {
2249 if (cur->subs[i].owner) {
2250 owned = 1;
2253 if (!owned) {
2254 if (prev) {
2255 prev->next = cur->next;
2256 if (prev->next)
2257 prev->next->prev = prev;
2258 else
2259 ifend = prev;
2260 } else {
2261 iflist = cur->next;
2262 if (iflist)
2263 iflist->prev = NULL;
2264 else
2265 ifend = NULL;
2267 if (cur->subs[SUB_REAL].dfd > -1) {
2268 dahdi_close(cur->subs[SUB_REAL].dfd);
2270 destroy_dahdi_pvt(&cur);
2272 } else {
2273 if (prev) {
2274 prev->next = cur->next;
2275 if (prev->next)
2276 prev->next->prev = prev;
2277 else
2278 ifend = prev;
2279 } else {
2280 iflist = cur->next;
2281 if (iflist)
2282 iflist->prev = NULL;
2283 else
2284 ifend = NULL;
2286 if (cur->subs[SUB_REAL].dfd > -1) {
2287 dahdi_close(cur->subs[SUB_REAL].dfd);
2289 destroy_dahdi_pvt(&cur);
2291 return 0;
2294 #ifdef HAVE_PRI
2295 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2297 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2299 static char *dahdi_send_keypad_facility_descrip =
2300 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2301 " IE over the current channel.\n";
2303 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2305 /* Data will be our digit string */
2306 struct dahdi_pvt *p;
2307 char *digits = (char *) data;
2309 if (ast_strlen_zero(digits)) {
2310 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2311 return -1;
2314 p = (struct dahdi_pvt *)chan->tech_pvt;
2316 if (!p) {
2317 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2318 return -1;
2321 ast_mutex_lock(&p->lock);
2323 if (!p->pri || !p->call) {
2324 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2325 ast_mutex_unlock(&p->lock);
2326 return -1;
2329 if (!pri_grab(p, p->pri)) {
2330 pri_keypad_facility(p->pri->pri, p->call, digits);
2331 pri_rel(p->pri);
2332 } else {
2333 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2334 ast_mutex_unlock(&p->lock);
2335 return -1;
2338 ast_mutex_unlock(&p->lock);
2340 return 0;
2343 static int pri_is_up(struct dahdi_pri *pri)
2345 int x;
2346 for (x = 0; x < NUM_DCHANS; x++) {
2347 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2348 return 1;
2350 return 0;
2353 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2355 bearer->owner = &inuse;
2356 bearer->realcall = crv;
2357 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2358 if (crv->subs[SUB_REAL].owner)
2359 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2360 crv->bearer = bearer;
2361 crv->call = bearer->call;
2362 crv->pri = pri;
2363 return 0;
2366 static char *pri_order(int level)
2368 switch (level) {
2369 case 0:
2370 return "Primary";
2371 case 1:
2372 return "Secondary";
2373 case 2:
2374 return "Tertiary";
2375 case 3:
2376 return "Quaternary";
2377 default:
2378 return "<Unknown>";
2382 /* Returns fd of the active dchan */
2383 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2385 int x = -1;
2387 for (x = 0; x < NUM_DCHANS; x++) {
2388 if ((pri->dchans[x] == pri->pri))
2389 break;
2392 return pri->fds[x];
2395 static int pri_find_dchan(struct dahdi_pri *pri)
2397 int oldslot = -1;
2398 struct pri *old;
2399 int newslot = -1;
2400 int x;
2401 old = pri->pri;
2402 for (x = 0; x < NUM_DCHANS; x++) {
2403 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2404 newslot = x;
2405 if (pri->dchans[x] == old) {
2406 oldslot = x;
2409 if (newslot < 0) {
2410 newslot = 0;
2411 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2412 pri->dchannels[newslot]);
2414 if (old && (oldslot != newslot))
2415 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2416 pri->dchannels[oldslot], pri->dchannels[newslot]);
2417 pri->pri = pri->dchans[newslot];
2418 return 0;
2420 #endif
2422 static int dahdi_hangup(struct ast_channel *ast)
2424 int res;
2425 int index,x, law;
2426 /*static int restore_gains(struct dahdi_pvt *p);*/
2427 struct dahdi_pvt *p = ast->tech_pvt;
2428 struct dahdi_pvt *tmp = NULL;
2429 struct dahdi_pvt *prev = NULL;
2430 DAHDI_PARAMS par;
2432 if (option_debug)
2433 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2434 if (!ast->tech_pvt) {
2435 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2436 return 0;
2439 ast_mutex_lock(&p->lock);
2441 index = dahdi_get_index(ast, p, 1);
2443 if (p->sig == SIG_PRI) {
2444 x = 1;
2445 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2448 x = 0;
2449 dahdi_confmute(p, 0);
2450 restore_gains(p);
2451 if (p->origcid_num) {
2452 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2453 free(p->origcid_num);
2454 p->origcid_num = NULL;
2456 if (p->origcid_name) {
2457 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2458 free(p->origcid_name);
2459 p->origcid_name = NULL;
2461 if (p->dsp)
2462 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2463 if (p->exten)
2464 p->exten[0] = '\0';
2466 if (option_debug)
2467 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2468 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2469 p->ignoredtmf = 0;
2471 if (index > -1) {
2472 /* Real channel, do some fixup */
2473 p->subs[index].owner = NULL;
2474 p->subs[index].needanswer = 0;
2475 p->subs[index].needflash = 0;
2476 p->subs[index].needringing = 0;
2477 p->subs[index].needbusy = 0;
2478 p->subs[index].needcongestion = 0;
2479 p->subs[index].linear = 0;
2480 p->subs[index].needcallerid = 0;
2481 p->polarity = POLARITY_IDLE;
2482 dahdi_setlinear(p->subs[index].dfd, 0);
2483 if (index == SUB_REAL) {
2484 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2485 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2486 if (p->subs[SUB_CALLWAIT].inthreeway) {
2487 /* We had flipped over to answer a callwait and now it's gone */
2488 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2489 /* Move to the call-wait, but un-own us until they flip back. */
2490 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2491 unalloc_sub(p, SUB_CALLWAIT);
2492 p->owner = NULL;
2493 } else {
2494 /* The three way hung up, but we still have a call wait */
2495 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2496 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2497 unalloc_sub(p, SUB_THREEWAY);
2498 if (p->subs[SUB_REAL].inthreeway) {
2499 /* This was part of a three way call. Immediately make way for
2500 another call */
2501 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2502 p->owner = p->subs[SUB_REAL].owner;
2503 } else {
2504 /* This call hasn't been completed yet... Set owner to NULL */
2505 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2506 p->owner = NULL;
2508 p->subs[SUB_REAL].inthreeway = 0;
2510 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2511 /* Move to the call-wait and switch back to them. */
2512 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2513 unalloc_sub(p, SUB_CALLWAIT);
2514 p->owner = p->subs[SUB_REAL].owner;
2515 if (p->owner->_state != AST_STATE_UP)
2516 p->subs[SUB_REAL].needanswer = 1;
2517 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2518 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2519 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2520 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2521 unalloc_sub(p, SUB_THREEWAY);
2522 if (p->subs[SUB_REAL].inthreeway) {
2523 /* This was part of a three way call. Immediately make way for
2524 another call */
2525 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2526 p->owner = p->subs[SUB_REAL].owner;
2527 } else {
2528 /* This call hasn't been completed yet... Set owner to NULL */
2529 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2530 p->owner = NULL;
2532 p->subs[SUB_REAL].inthreeway = 0;
2534 } else if (index == SUB_CALLWAIT) {
2535 /* Ditch the holding callwait call, and immediately make it availabe */
2536 if (p->subs[SUB_CALLWAIT].inthreeway) {
2537 /* This is actually part of a three way, placed on hold. Place the third part
2538 on music on hold now */
2539 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2540 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2541 S_OR(p->mohsuggest, NULL),
2542 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2544 p->subs[SUB_THREEWAY].inthreeway = 0;
2545 /* Make it the call wait now */
2546 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2547 unalloc_sub(p, SUB_THREEWAY);
2548 } else
2549 unalloc_sub(p, SUB_CALLWAIT);
2550 } else if (index == SUB_THREEWAY) {
2551 if (p->subs[SUB_CALLWAIT].inthreeway) {
2552 /* The other party of the three way call is currently in a call-wait state.
2553 Start music on hold for them, and take the main guy out of the third call */
2554 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2555 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2556 S_OR(p->mohsuggest, NULL),
2557 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2559 p->subs[SUB_CALLWAIT].inthreeway = 0;
2561 p->subs[SUB_REAL].inthreeway = 0;
2562 /* If this was part of a three way call index, let us make
2563 another three way call */
2564 unalloc_sub(p, SUB_THREEWAY);
2565 } else {
2566 /* This wasn't any sort of call, but how are we an index? */
2567 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2571 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2572 p->owner = NULL;
2573 p->ringt = 0;
2574 p->distinctivering = 0;
2575 p->confirmanswer = 0;
2576 p->cidrings = 1;
2577 p->outgoing = 0;
2578 p->digital = 0;
2579 p->faxhandled = 0;
2580 p->pulsedial = 0;
2581 p->onhooktime = time(NULL);
2582 #ifdef HAVE_PRI
2583 p->proceeding = 0;
2584 p->progress = 0;
2585 p->alerting = 0;
2586 p->setup_ack = 0;
2587 #endif
2588 if (p->dsp) {
2589 ast_dsp_free(p->dsp);
2590 p->dsp = NULL;
2593 law = DAHDI_LAW_DEFAULT;
2594 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2595 if (res < 0)
2596 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2597 /* Perform low level hangup if no owner left */
2598 #ifdef HAVE_PRI
2599 if (p->pri) {
2600 #ifdef SUPPORT_USERUSER
2601 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2602 #endif
2604 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2605 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2606 if (!pri_grab(p, p->pri)) {
2607 if (p->alreadyhungup) {
2608 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2610 #ifdef SUPPORT_USERUSER
2611 pri_call_set_useruser(p->call, useruser);
2612 #endif
2614 pri_hangup(p->pri->pri, p->call, -1);
2615 p->call = NULL;
2616 if (p->bearer)
2617 p->bearer->call = NULL;
2618 } else {
2619 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2620 int icause = ast->hangupcause ? ast->hangupcause : -1;
2621 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2623 #ifdef SUPPORT_USERUSER
2624 pri_call_set_useruser(p->call, useruser);
2625 #endif
2627 p->alreadyhungup = 1;
2628 if (p->bearer)
2629 p->bearer->alreadyhungup = 1;
2630 if (cause) {
2631 if (atoi(cause))
2632 icause = atoi(cause);
2634 pri_hangup(p->pri->pri, p->call, icause);
2636 if (res < 0)
2637 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2638 pri_rel(p->pri);
2639 } else {
2640 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2641 res = -1;
2643 } else {
2644 if (p->bearer)
2645 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2646 p->call = NULL;
2647 res = 0;
2650 #endif
2651 if (p->sig && (p->sig != SIG_PRI))
2652 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2653 if (res < 0) {
2654 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2656 switch (p->sig) {
2657 case SIG_FXOGS:
2658 case SIG_FXOLS:
2659 case SIG_FXOKS:
2660 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2661 if (!res) {
2662 #if 0
2663 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2664 #endif
2665 /* If they're off hook, try playing congestion */
2666 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2667 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2668 else
2669 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2671 break;
2672 case SIG_FXSGS:
2673 case SIG_FXSLS:
2674 case SIG_FXSKS:
2675 /* Make sure we're not made available for at least two seconds assuming
2676 we were actually used for an inbound or outbound call. */
2677 if (ast->_state != AST_STATE_RESERVED) {
2678 time(&p->guardtime);
2679 p->guardtime += 2;
2681 break;
2682 default:
2683 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2685 if (p->cidspill)
2686 free(p->cidspill);
2687 if (p->sig)
2688 dahdi_disable_ec(p);
2689 x = 0;
2690 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2691 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2692 p->didtdd = 0;
2693 p->cidspill = NULL;
2694 p->callwaitcas = 0;
2695 p->callwaiting = p->permcallwaiting;
2696 p->hidecallerid = p->permhidecallerid;
2697 p->dialing = 0;
2698 p->rdnis[0] = '\0';
2699 update_conf(p);
2700 reset_conf(p);
2701 /* Restore data mode */
2702 if (p->sig == SIG_PRI) {
2703 x = 0;
2704 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2706 #ifdef HAVE_PRI
2707 if (p->bearer) {
2708 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2709 /* Free up the bearer channel as well, and
2710 don't use its file descriptor anymore */
2711 update_conf(p->bearer);
2712 reset_conf(p->bearer);
2713 p->bearer->owner = NULL;
2714 p->bearer->realcall = NULL;
2715 p->bearer = NULL;
2716 p->subs[SUB_REAL].dfd = -1;
2717 p->pri = NULL;
2719 #endif
2720 restart_monitor();
2723 p->callwaitingrepeat = 0;
2724 p->cidcwexpire = 0;
2725 p->oprmode = 0;
2726 ast->tech_pvt = NULL;
2727 ast_mutex_unlock(&p->lock);
2728 ast_module_unref(ast_module_info->self);
2729 if (option_verbose > 2)
2730 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2732 ast_mutex_lock(&iflock);
2733 tmp = iflist;
2734 prev = NULL;
2735 if (p->destroy) {
2736 while (tmp) {
2737 if (tmp == p) {
2738 destroy_channel(prev, tmp, 0);
2739 break;
2740 } else {
2741 prev = tmp;
2742 tmp = tmp->next;
2746 ast_mutex_unlock(&iflock);
2747 return 0;
2750 static int dahdi_answer(struct ast_channel *ast)
2752 struct dahdi_pvt *p = ast->tech_pvt;
2753 int res = 0;
2754 int index;
2755 int oldstate = ast->_state;
2756 ast_setstate(ast, AST_STATE_UP);
2757 ast_mutex_lock(&p->lock);
2758 index = dahdi_get_index(ast, p, 0);
2759 if (index < 0)
2760 index = SUB_REAL;
2761 /* nothing to do if a radio channel */
2762 if ((p->radio || (p->oprmode < 0))) {
2763 ast_mutex_unlock(&p->lock);
2764 return 0;
2766 switch (p->sig) {
2767 case SIG_FXSLS:
2768 case SIG_FXSGS:
2769 case SIG_FXSKS:
2770 p->ringt = 0;
2771 /* Fall through */
2772 case SIG_EM:
2773 case SIG_EM_E1:
2774 case SIG_EMWINK:
2775 case SIG_FEATD:
2776 case SIG_FEATDMF:
2777 case SIG_FEATDMF_TA:
2778 case SIG_E911:
2779 case SIG_FGC_CAMA:
2780 case SIG_FGC_CAMAMF:
2781 case SIG_FEATB:
2782 case SIG_SF:
2783 case SIG_SFWINK:
2784 case SIG_SF_FEATD:
2785 case SIG_SF_FEATDMF:
2786 case SIG_SF_FEATB:
2787 case SIG_FXOLS:
2788 case SIG_FXOGS:
2789 case SIG_FXOKS:
2790 /* Pick up the line */
2791 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
2792 if (p->hanguponpolarityswitch) {
2793 gettimeofday(&p->polaritydelaytv, NULL);
2795 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2796 tone_zone_play_tone(p->subs[index].dfd, -1);
2797 p->dialing = 0;
2798 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
2799 if (oldstate == AST_STATE_RINGING) {
2800 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
2801 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
2802 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2803 p->owner = p->subs[SUB_REAL].owner;
2806 if (p->sig & __DAHDI_SIG_FXS) {
2807 dahdi_enable_ec(p);
2808 dahdi_train_ec(p);
2810 break;
2811 #ifdef HAVE_PRI
2812 case SIG_PRI:
2813 /* Send a pri acknowledge */
2814 if (!pri_grab(p, p->pri)) {
2815 p->proceeding = 1;
2816 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2817 pri_rel(p->pri);
2818 } else {
2819 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2820 res = -1;
2822 break;
2823 #endif
2824 case 0:
2825 ast_mutex_unlock(&p->lock);
2826 return 0;
2827 default:
2828 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
2829 res = -1;
2831 ast_mutex_unlock(&p->lock);
2832 return res;
2835 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
2837 char *cp;
2838 signed char *scp;
2839 int x;
2840 int index;
2841 struct dahdi_pvt *p = chan->tech_pvt, *pp;
2842 struct oprmode *oprmode;
2845 /* all supported options require data */
2846 if (!data || (datalen < 1)) {
2847 errno = EINVAL;
2848 return -1;
2851 switch (option) {
2852 case AST_OPTION_TXGAIN:
2853 scp = (signed char *) data;
2854 index = dahdi_get_index(chan, p, 0);
2855 if (index < 0) {
2856 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
2857 return -1;
2859 if (option_debug)
2860 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
2861 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
2862 case AST_OPTION_RXGAIN:
2863 scp = (signed char *) data;
2864 index = dahdi_get_index(chan, p, 0);
2865 if (index < 0) {
2866 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
2867 return -1;
2869 if (option_debug)
2870 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
2871 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
2872 case AST_OPTION_TONE_VERIFY:
2873 if (!p->dsp)
2874 break;
2875 cp = (char *) data;
2876 switch (*cp) {
2877 case 1:
2878 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
2879 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
2880 break;
2881 case 2:
2882 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
2883 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
2884 break;
2885 default:
2886 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
2887 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
2888 break;
2890 break;
2891 case AST_OPTION_TDD:
2892 /* turn on or off TDD */
2893 cp = (char *) data;
2894 p->mate = 0;
2895 if (!*cp) { /* turn it off */
2896 if (option_debug)
2897 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
2898 if (p->tdd)
2899 tdd_free(p->tdd);
2900 p->tdd = 0;
2901 break;
2903 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
2904 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
2905 dahdi_disable_ec(p);
2906 /* otherwise, turn it on */
2907 if (!p->didtdd) { /* if havent done it yet */
2908 unsigned char mybuf[41000], *buf;
2909 int size, res, fd, len;
2910 struct pollfd fds[1];
2912 buf = mybuf;
2913 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
2914 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
2915 len = 40000;
2916 index = dahdi_get_index(chan, p, 0);
2917 if (index < 0) {
2918 ast_log(LOG_WARNING, "No index in TDD?\n");
2919 return -1;
2921 fd = p->subs[index].dfd;
2922 while (len) {
2923 if (ast_check_hangup(chan))
2924 return -1;
2925 size = len;
2926 if (size > READ_SIZE)
2927 size = READ_SIZE;
2928 fds[0].fd = fd;
2929 fds[0].events = POLLPRI | POLLOUT;
2930 fds[0].revents = 0;
2931 res = poll(fds, 1, -1);
2932 if (!res) {
2933 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
2934 continue;
2936 /* if got exception */
2937 if (fds[0].revents & POLLPRI)
2938 return -1;
2939 if (!(fds[0].revents & POLLOUT)) {
2940 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
2941 continue;
2943 res = write(fd, buf, size);
2944 if (res != size) {
2945 if (res == -1) return -1;
2946 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
2947 break;
2949 len -= size;
2950 buf += size;
2952 p->didtdd = 1; /* set to have done it now */
2954 if (*cp == 2) { /* Mate mode */
2955 if (p->tdd)
2956 tdd_free(p->tdd);
2957 p->tdd = 0;
2958 p->mate = 1;
2959 break;
2961 if (!p->tdd) { /* if we dont have one yet */
2962 p->tdd = tdd_new(); /* allocate one */
2964 break;
2965 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
2966 if (!p->dsp)
2967 break;
2968 cp = (char *) data;
2969 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
2970 *cp ? "ON" : "OFF", (int) *cp, chan->name);
2971 p->dtmfrelax = 0;
2972 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
2973 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
2974 break;
2975 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
2976 cp = (char *) data;
2977 if (!*cp) {
2978 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
2979 x = 0;
2980 dahdi_disable_ec(p);
2981 } else {
2982 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
2983 x = 1;
2985 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
2986 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
2987 break;
2988 case AST_OPTION_OPRMODE: /* Operator services mode */
2989 oprmode = (struct oprmode *) data;
2990 pp = oprmode->peer->tech_pvt;
2991 p->oprmode = pp->oprmode = 0;
2992 /* setup peers */
2993 p->oprpeer = pp;
2994 pp->oprpeer = p;
2995 /* setup modes, if any */
2996 if (oprmode->mode)
2998 pp->oprmode = oprmode->mode;
2999 p->oprmode = -oprmode->mode;
3001 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
3002 oprmode->mode, chan->name,oprmode->peer->name);;
3003 break;
3004 case AST_OPTION_ECHOCAN:
3005 cp = (char *) data;
3006 if (*cp) {
3007 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3008 dahdi_enable_ec(p);
3009 } else {
3010 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3011 dahdi_disable_ec(p);
3013 break;
3015 errno = 0;
3017 return 0;
3020 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3022 struct dahdi_pvt *p = chan->tech_pvt;
3024 if (!strcasecmp(data, "rxgain")) {
3025 ast_mutex_lock(&p->lock);
3026 snprintf(buf, len, "%f", p->rxgain);
3027 ast_mutex_unlock(&p->lock);
3028 } else if (!strcasecmp(data, "txgain")) {
3029 ast_mutex_lock(&p->lock);
3030 snprintf(buf, len, "%f", p->txgain);
3031 ast_mutex_unlock(&p->lock);
3032 } else {
3033 ast_copy_string(buf, "", len);
3035 return 0;
3039 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3041 /* Unlink a specific slave or all slaves/masters from a given master */
3042 int x;
3043 int hasslaves;
3044 if (!master)
3045 return;
3046 if (needlock) {
3047 ast_mutex_lock(&master->lock);
3048 if (slave) {
3049 while (ast_mutex_trylock(&slave->lock)) {
3050 DEADLOCK_AVOIDANCE(&master->lock);
3054 hasslaves = 0;
3055 for (x = 0; x < MAX_SLAVES; x++) {
3056 if (master->slaves[x]) {
3057 if (!slave || (master->slaves[x] == slave)) {
3058 /* Take slave out of the conference */
3059 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3060 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3061 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3062 master->slaves[x]->master = NULL;
3063 master->slaves[x] = NULL;
3064 } else
3065 hasslaves = 1;
3067 if (!hasslaves)
3068 master->inconference = 0;
3070 if (!slave) {
3071 if (master->master) {
3072 /* Take master out of the conference */
3073 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3074 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3075 hasslaves = 0;
3076 for (x = 0; x < MAX_SLAVES; x++) {
3077 if (master->master->slaves[x] == master)
3078 master->master->slaves[x] = NULL;
3079 else if (master->master->slaves[x])
3080 hasslaves = 1;
3082 if (!hasslaves)
3083 master->master->inconference = 0;
3085 master->master = NULL;
3087 update_conf(master);
3088 if (needlock) {
3089 if (slave)
3090 ast_mutex_unlock(&slave->lock);
3091 ast_mutex_unlock(&master->lock);
3095 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3096 int x;
3097 if (!slave || !master) {
3098 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3099 return;
3101 for (x = 0; x < MAX_SLAVES; x++) {
3102 if (!master->slaves[x]) {
3103 master->slaves[x] = slave;
3104 break;
3107 if (x >= MAX_SLAVES) {
3108 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3109 master->slaves[MAX_SLAVES - 1] = slave;
3111 if (slave->master)
3112 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3113 slave->master = master;
3115 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3118 static void disable_dtmf_detect(struct dahdi_pvt *p)
3120 #ifdef DAHDI_TONEDETECT
3121 int val;
3122 #endif
3124 p->ignoredtmf = 1;
3126 #ifdef DAHDI_TONEDETECT
3127 val = 0;
3128 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3129 #endif
3130 if (!p->hardwaredtmf && p->dsp) {
3131 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3132 ast_dsp_set_features(p->dsp, p->dsp_features);
3136 static void enable_dtmf_detect(struct dahdi_pvt *p)
3138 #ifdef DAHDI_TONEDETECT
3139 int val;
3140 #endif
3142 if (p->channel == CHAN_PSEUDO)
3143 return;
3145 p->ignoredtmf = 0;
3147 #ifdef DAHDI_TONEDETECT
3148 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3149 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3150 #endif
3151 if (!p->hardwaredtmf && p->dsp) {
3152 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3153 ast_dsp_set_features(p->dsp, p->dsp_features);
3157 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)
3159 struct ast_channel *who;
3160 struct dahdi_pvt *p0, *p1, *op0, *op1;
3161 struct dahdi_pvt *master = NULL, *slave = NULL;
3162 struct ast_frame *f;
3163 int inconf = 0;
3164 int nothingok = 1;
3165 int ofd0, ofd1;
3166 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3167 int os0 = -1, os1 = -1;
3168 int priority = 0;
3169 struct ast_channel *oc0, *oc1;
3170 enum ast_bridge_result res;
3172 #ifdef PRI_2BCT
3173 int triedtopribridge = 0;
3174 q931_call *q931c0 = NULL, *q931c1 = NULL;
3175 #endif
3177 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3178 There is code below to handle it properly until DTMF is actually seen,
3179 but due to currently unresolved issues it's ignored...
3182 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3183 return AST_BRIDGE_FAILED_NOWARN;
3185 ast_mutex_lock(&c0->lock);
3186 while (ast_mutex_trylock(&c1->lock)) {
3187 DEADLOCK_AVOIDANCE(&c0->lock);
3190 p0 = c0->tech_pvt;
3191 p1 = c1->tech_pvt;
3192 /* cant do pseudo-channels here */
3193 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3194 ast_mutex_unlock(&c0->lock);
3195 ast_mutex_unlock(&c1->lock);
3196 return AST_BRIDGE_FAILED_NOWARN;
3199 oi0 = dahdi_get_index(c0, p0, 0);
3200 oi1 = dahdi_get_index(c1, p1, 0);
3201 if ((oi0 < 0) || (oi1 < 0)) {
3202 ast_mutex_unlock(&c0->lock);
3203 ast_mutex_unlock(&c1->lock);
3204 return AST_BRIDGE_FAILED;
3207 op0 = p0 = c0->tech_pvt;
3208 op1 = p1 = c1->tech_pvt;
3209 ofd0 = c0->fds[0];
3210 ofd1 = c1->fds[0];
3211 oc0 = p0->owner;
3212 oc1 = p1->owner;
3214 if (ast_mutex_trylock(&p0->lock)) {
3215 /* Don't block, due to potential for deadlock */
3216 ast_mutex_unlock(&c0->lock);
3217 ast_mutex_unlock(&c1->lock);
3218 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3219 return AST_BRIDGE_RETRY;
3221 if (ast_mutex_trylock(&p1->lock)) {
3222 /* Don't block, due to potential for deadlock */
3223 ast_mutex_unlock(&p0->lock);
3224 ast_mutex_unlock(&c0->lock);
3225 ast_mutex_unlock(&c1->lock);
3226 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3227 return AST_BRIDGE_RETRY;
3230 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3231 if (p0->owner && p1->owner) {
3232 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3233 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3234 master = p0;
3235 slave = p1;
3236 inconf = 1;
3237 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3238 master = p1;
3239 slave = p0;
3240 inconf = 1;
3241 } else {
3242 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3243 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3244 p0->channel,
3245 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3246 p0->subs[SUB_REAL].inthreeway, p0->channel,
3247 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3248 p1->subs[SUB_REAL].inthreeway);
3250 nothingok = 0;
3252 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3253 if (p1->subs[SUB_THREEWAY].inthreeway) {
3254 master = p1;
3255 slave = p0;
3256 nothingok = 0;
3258 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3259 if (p0->subs[SUB_THREEWAY].inthreeway) {
3260 master = p0;
3261 slave = p1;
3262 nothingok = 0;
3264 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3265 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3266 don't put us in anything */
3267 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3268 master = p1;
3269 slave = p0;
3270 nothingok = 0;
3272 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3273 /* Same as previous */
3274 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3275 master = p0;
3276 slave = p1;
3277 nothingok = 0;
3280 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3281 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3282 if (master && slave) {
3283 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3284 in an active threeway call with a channel that is ringing, we should
3285 indicate ringing. */
3286 if ((oi1 == SUB_THREEWAY) &&
3287 p1->subs[SUB_THREEWAY].inthreeway &&
3288 p1->subs[SUB_REAL].owner &&
3289 p1->subs[SUB_REAL].inthreeway &&
3290 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3291 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3292 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3293 os1 = p1->subs[SUB_REAL].owner->_state;
3294 } else {
3295 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3296 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3298 if ((oi0 == SUB_THREEWAY) &&
3299 p0->subs[SUB_THREEWAY].inthreeway &&
3300 p0->subs[SUB_REAL].owner &&
3301 p0->subs[SUB_REAL].inthreeway &&
3302 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3303 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3304 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3305 os0 = p0->subs[SUB_REAL].owner->_state;
3306 } else {
3307 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3308 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3310 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3311 if (!p0->echocanbridged || !p1->echocanbridged) {
3312 /* Disable echo cancellation if appropriate */
3313 dahdi_disable_ec(p0);
3314 dahdi_disable_ec(p1);
3317 dahdi_link(slave, master);
3318 master->inconference = inconf;
3319 } else if (!nothingok)
3320 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3322 update_conf(p0);
3323 update_conf(p1);
3324 t0 = p0->subs[SUB_REAL].inthreeway;
3325 t1 = p1->subs[SUB_REAL].inthreeway;
3327 ast_mutex_unlock(&p0->lock);
3328 ast_mutex_unlock(&p1->lock);
3330 ast_mutex_unlock(&c0->lock);
3331 ast_mutex_unlock(&c1->lock);
3333 /* Native bridge failed */
3334 if ((!master || !slave) && !nothingok) {
3335 dahdi_enable_ec(p0);
3336 dahdi_enable_ec(p1);
3337 return AST_BRIDGE_FAILED;
3340 if (option_verbose > 2)
3341 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3343 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3344 disable_dtmf_detect(op0);
3346 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3347 disable_dtmf_detect(op1);
3349 for (;;) {
3350 struct ast_channel *c0_priority[2] = {c0, c1};
3351 struct ast_channel *c1_priority[2] = {c1, c0};
3353 /* Here's our main loop... Start by locking things, looking for private parts,
3354 and then balking if anything is wrong */
3355 ast_mutex_lock(&c0->lock);
3356 while (ast_mutex_trylock(&c1->lock)) {
3357 DEADLOCK_AVOIDANCE(&c0->lock);
3360 p0 = c0->tech_pvt;
3361 p1 = c1->tech_pvt;
3363 if (op0 == p0)
3364 i0 = dahdi_get_index(c0, p0, 1);
3365 if (op1 == p1)
3366 i1 = dahdi_get_index(c1, p1, 1);
3367 ast_mutex_unlock(&c0->lock);
3368 ast_mutex_unlock(&c1->lock);
3370 if (!timeoutms ||
3371 (op0 != p0) ||
3372 (op1 != p1) ||
3373 (ofd0 != c0->fds[0]) ||
3374 (ofd1 != c1->fds[0]) ||
3375 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3376 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3377 (oc0 != p0->owner) ||
3378 (oc1 != p1->owner) ||
3379 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3380 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3381 (oi0 != i0) ||
3382 (oi1 != i1)) {
3383 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3384 op0->channel, oi0, op1->channel, oi1);
3385 res = AST_BRIDGE_RETRY;
3386 goto return_from_bridge;
3389 #ifdef PRI_2BCT
3390 q931c0 = p0->call;
3391 q931c1 = p1->call;
3392 if (p0->transfer && p1->transfer
3393 && q931c0 && q931c1
3394 && !triedtopribridge) {
3395 pri_channel_bridge(q931c0, q931c1);
3396 triedtopribridge = 1;
3398 #endif
3400 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3401 if (!who) {
3402 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3403 continue;
3405 f = ast_read(who);
3406 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3407 *fo = f;
3408 *rc = who;
3409 res = AST_BRIDGE_COMPLETE;
3410 goto return_from_bridge;
3412 if (f->frametype == AST_FRAME_DTMF) {
3413 if ((who == c0) && p0->pulsedial) {
3414 ast_write(c1, f);
3415 } else if ((who == c1) && p1->pulsedial) {
3416 ast_write(c0, f);
3417 } else {
3418 *fo = f;
3419 *rc = who;
3420 res = AST_BRIDGE_COMPLETE;
3421 goto return_from_bridge;
3424 ast_frfree(f);
3426 /* Swap who gets priority */
3427 priority = !priority;
3430 return_from_bridge:
3431 if (op0 == p0)
3432 dahdi_enable_ec(p0);
3434 if (op1 == p1)
3435 dahdi_enable_ec(p1);
3437 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3438 enable_dtmf_detect(op0);
3440 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3441 enable_dtmf_detect(op1);
3443 dahdi_unlink(slave, master, 1);
3445 return res;
3448 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3450 struct dahdi_pvt *p = newchan->tech_pvt;
3451 int x;
3452 ast_mutex_lock(&p->lock);
3453 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3454 if (p->owner == oldchan) {
3455 p->owner = newchan;
3457 for (x = 0; x < 3; x++)
3458 if (p->subs[x].owner == oldchan) {
3459 if (!x)
3460 dahdi_unlink(NULL, p, 0);
3461 p->subs[x].owner = newchan;
3463 if (newchan->_state == AST_STATE_RINGING)
3464 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3465 update_conf(p);
3466 ast_mutex_unlock(&p->lock);
3467 return 0;
3470 static int dahdi_ring_phone(struct dahdi_pvt *p)
3472 int x;
3473 int res;
3474 /* Make sure our transmit state is on hook */
3475 x = 0;
3476 x = DAHDI_ONHOOK;
3477 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3478 do {
3479 x = DAHDI_RING;
3480 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3481 if (res) {
3482 switch (errno) {
3483 case EBUSY:
3484 case EINTR:
3485 /* Wait just in case */
3486 usleep(10000);
3487 continue;
3488 case EINPROGRESS:
3489 res = 0;
3490 break;
3491 default:
3492 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3493 res = 0;
3496 } while (res);
3497 return res;
3500 static void *ss_thread(void *data);
3502 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3504 static int attempt_transfer(struct dahdi_pvt *p)
3506 /* In order to transfer, we need at least one of the channels to
3507 actually be in a call bridge. We can't conference two applications
3508 together (but then, why would we want to?) */
3509 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3510 /* The three-way person we're about to transfer to could still be in MOH, so
3511 stop if now if appropriate */
3512 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3513 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3514 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3515 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3517 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3518 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3520 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3521 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3522 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3523 return -1;
3525 /* Orphan the channel after releasing the lock */
3526 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3527 unalloc_sub(p, SUB_THREEWAY);
3528 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3529 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3530 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3531 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3533 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3534 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3536 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3537 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3538 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3539 return -1;
3541 /* Three-way is now the REAL */
3542 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3543 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3544 unalloc_sub(p, SUB_THREEWAY);
3545 /* Tell the caller not to hangup */
3546 return 1;
3547 } else {
3548 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3549 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3550 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3551 return -1;
3553 return 0;
3556 static int check_for_conference(struct dahdi_pvt *p)
3558 DAHDI_CONFINFO ci;
3559 /* Fine if we already have a master, etc */
3560 if (p->master || (p->confno > -1))
3561 return 0;
3562 memset(&ci, 0, sizeof(ci));
3563 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3564 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3565 return 0;
3567 /* If we have no master and don't have a confno, then
3568 if we're in a conference, it's probably a MeetMe room or
3569 some such, so don't let us 3-way out! */
3570 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3571 if (option_verbose > 2)
3572 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3573 return 1;
3575 return 0;
3578 static int get_alarms(struct dahdi_pvt *p)
3580 int res;
3581 DAHDI_SPANINFO zi;
3582 memset(&zi, 0, sizeof(zi));
3583 zi.spanno = p->span;
3584 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi);
3585 if (res < 0) {
3586 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3587 return 0;
3589 return zi.alarms;
3592 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3594 struct dahdi_pvt *p = ast->tech_pvt;
3595 struct ast_frame *f = *dest;
3597 if (option_debug)
3598 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3600 if (p->confirmanswer) {
3601 if (option_debug)
3602 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3603 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3604 of a DTMF digit */
3605 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3606 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3607 *dest = &p->subs[index].f;
3608 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3609 p->confirmanswer = 0;
3610 } else if (p->callwaitcas) {
3611 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3612 if (option_debug)
3613 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3614 if (p->cidspill)
3615 free(p->cidspill);
3616 send_cwcidspill(p);
3618 if ((f->subclass != 'm') && (f->subclass != 'u'))
3619 p->callwaitcas = 0;
3620 p->subs[index].f.frametype = AST_FRAME_NULL;
3621 p->subs[index].f.subclass = 0;
3622 *dest = &p->subs[index].f;
3623 } else if (f->subclass == 'f') {
3624 /* Fax tone -- Handle and return NULL */
3625 if ((p->callprogress & 0x6) && !p->faxhandled) {
3626 p->faxhandled++;
3627 if (strcmp(ast->exten, "fax")) {
3628 const char *target_context = S_OR(ast->macrocontext, ast->context);
3630 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3631 if (option_verbose > 2)
3632 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3633 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3634 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3635 if (ast_async_goto(ast, target_context, "fax", 1))
3636 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3637 } else
3638 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3639 } else if (option_debug)
3640 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3641 } else if (option_debug)
3642 ast_log(LOG_DEBUG, "Fax already handled\n");
3643 dahdi_confmute(p, 0);
3644 p->subs[index].f.frametype = AST_FRAME_NULL;
3645 p->subs[index].f.subclass = 0;
3646 *dest = &p->subs[index].f;
3647 } else if (f->subclass == 'm') {
3648 /* Confmute request */
3649 dahdi_confmute(p, 1);
3650 p->subs[index].f.frametype = AST_FRAME_NULL;
3651 p->subs[index].f.subclass = 0;
3652 *dest = &p->subs[index].f;
3653 } else if (f->subclass == 'u') {
3654 /* Unmute */
3655 dahdi_confmute(p, 0);
3656 p->subs[index].f.frametype = AST_FRAME_NULL;
3657 p->subs[index].f.subclass = 0;
3658 *dest = &p->subs[index].f;
3659 } else
3660 dahdi_confmute(p, 0);
3663 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
3665 int res, x;
3666 int index, mysig;
3667 char *c;
3668 struct dahdi_pvt *p = ast->tech_pvt;
3669 pthread_t threadid;
3670 pthread_attr_t attr;
3671 struct ast_channel *chan;
3672 struct ast_frame *f;
3674 index = dahdi_get_index(ast, p, 0);
3675 mysig = p->sig;
3676 if (p->outsigmod > -1)
3677 mysig = p->outsigmod;
3678 p->subs[index].f.frametype = AST_FRAME_NULL;
3679 p->subs[index].f.subclass = 0;
3680 p->subs[index].f.datalen = 0;
3681 p->subs[index].f.samples = 0;
3682 p->subs[index].f.mallocd = 0;
3683 p->subs[index].f.offset = 0;
3684 p->subs[index].f.src = "dahdi_handle_event";
3685 p->subs[index].f.data = NULL;
3686 f = &p->subs[index].f;
3688 if (index < 0)
3689 return &p->subs[index].f;
3690 if (p->fake_event) {
3691 res = p->fake_event;
3692 p->fake_event = 0;
3693 } else
3694 res = dahdi_get_event(p->subs[index].dfd);
3696 if (option_debug)
3697 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
3699 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
3700 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
3702 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
3703 #ifdef HAVE_PRI
3704 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
3705 /* absorb event */
3706 } else {
3707 #endif
3708 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
3709 p->subs[index].f.subclass = res & 0xff;
3710 #ifdef HAVE_PRI
3712 #endif
3713 dahdi_handle_dtmfup(ast, index, &f);
3714 return f;
3717 if (res & DAHDI_EVENT_DTMFDOWN) {
3718 if (option_debug)
3719 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
3720 /* Mute conference */
3721 dahdi_confmute(p, 1);
3722 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
3723 p->subs[index].f.subclass = res & 0xff;
3724 return &p->subs[index].f;
3727 switch (res) {
3728 #ifdef DAHDI_EVENT_EC_DISABLED
3729 case DAHDI_EVENT_EC_DISABLED:
3730 if (option_verbose > 2)
3731 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
3732 p->echocanon = 0;
3733 break;
3734 #endif
3735 case DAHDI_EVENT_BITSCHANGED:
3736 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
3737 case DAHDI_EVENT_PULSE_START:
3738 /* Stop tone if there's a pulse start and the PBX isn't started */
3739 if (!ast->pbx)
3740 tone_zone_play_tone(p->subs[index].dfd, -1);
3741 break;
3742 case DAHDI_EVENT_DIALCOMPLETE:
3743 if (p->inalarm) break;
3744 if ((p->radio || (p->oprmode < 0))) break;
3745 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
3746 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
3747 return NULL;
3749 if (!x) { /* if not still dialing in driver */
3750 dahdi_enable_ec(p);
3751 if (p->echobreak) {
3752 dahdi_train_ec(p);
3753 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
3754 p->dop.op = DAHDI_DIAL_OP_REPLACE;
3755 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
3756 p->echobreak = 0;
3757 } else {
3758 p->dialing = 0;
3759 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
3760 /* if thru with dialing after offhook */
3761 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
3762 ast_setstate(ast, AST_STATE_UP);
3763 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3764 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3765 break;
3766 } else { /* if to state wait for offhook to dial rest */
3767 /* we now wait for off hook */
3768 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
3771 if (ast->_state == AST_STATE_DIALING) {
3772 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3773 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
3774 } 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)))) {
3775 ast_setstate(ast, AST_STATE_RINGING);
3776 } else if (!p->answeronpolarityswitch) {
3777 ast_setstate(ast, AST_STATE_UP);
3778 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3779 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3780 /* If aops=0 and hops=1, this is necessary */
3781 p->polarity = POLARITY_REV;
3782 } else {
3783 /* Start clean, so we can catch the change to REV polarity when party answers */
3784 p->polarity = POLARITY_IDLE;
3789 break;
3790 case DAHDI_EVENT_ALARM:
3791 #ifdef HAVE_PRI
3792 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
3793 /* T309 is not enabled : hangup calls when alarm occurs */
3794 if (p->call) {
3795 if (p->pri && p->pri->pri) {
3796 if (!pri_grab(p, p->pri)) {
3797 pri_hangup(p->pri->pri, p->call, -1);
3798 pri_destroycall(p->pri->pri, p->call);
3799 p->call = NULL;
3800 pri_rel(p->pri);
3801 } else
3802 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3803 } else
3804 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
3806 if (p->owner)
3807 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3809 if (p->bearer)
3810 p->bearer->inalarm = 1;
3811 else
3812 #endif
3813 p->inalarm = 1;
3814 res = get_alarms(p);
3815 do {
3816 const char *alarm_str = alarm2str(res);
3818 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
3819 * doesn't know what to do with it. Don't confuse users with log messages. */
3820 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3821 p->unknown_alarm = 1;
3822 break;
3823 } else {
3824 p->unknown_alarm = 0;
3827 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3828 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3829 "Alarm: %s\r\n"
3830 "Channel: %d\r\n",
3831 alarm_str, p->channel);
3832 } while (0);
3833 #ifdef HAVE_LIBPRI
3834 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3835 /* fall through intentionally */
3836 } else {
3837 break;
3839 #endif
3840 case DAHDI_EVENT_ONHOOK:
3841 if (p->radio) {
3842 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3843 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
3844 break;
3846 if (p->oprmode < 0)
3848 if (p->oprmode != -1) break;
3849 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3851 /* Make sure it starts ringing */
3852 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3853 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
3854 save_conference(p->oprpeer);
3855 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3857 break;
3859 switch (p->sig) {
3860 case SIG_FXOLS:
3861 case SIG_FXOGS:
3862 case SIG_FXOKS:
3863 p->onhooktime = time(NULL);
3864 p->msgstate = -1;
3865 /* Check for some special conditions regarding call waiting */
3866 if (index == SUB_REAL) {
3867 /* The normal line was hung up */
3868 if (p->subs[SUB_CALLWAIT].owner) {
3869 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3870 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3871 if (option_verbose > 2)
3872 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
3873 unalloc_sub(p, SUB_CALLWAIT);
3874 #if 0
3875 p->subs[index].needanswer = 0;
3876 p->subs[index].needringing = 0;
3877 #endif
3878 p->callwaitingrepeat = 0;
3879 p->cidcwexpire = 0;
3880 p->owner = NULL;
3881 /* Don't start streaming audio yet if the incoming call isn't up yet */
3882 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
3883 p->dialing = 1;
3884 dahdi_ring_phone(p);
3885 } else if (p->subs[SUB_THREEWAY].owner) {
3886 unsigned int mssinceflash;
3887 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3888 the private structure -- not especially easy or clean */
3889 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
3890 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3891 ast_mutex_unlock(&p->lock);
3892 DEADLOCK_AVOIDANCE(&ast->lock);
3893 /* We can grab ast and p in that order, without worry. We should make sure
3894 nothing seriously bad has happened though like some sort of bizarre double
3895 masquerade! */
3896 ast_mutex_lock(&p->lock);
3897 if (p->owner != ast) {
3898 ast_log(LOG_WARNING, "This isn't good...\n");
3899 return NULL;
3902 if (!p->subs[SUB_THREEWAY].owner) {
3903 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
3904 return NULL;
3906 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
3907 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
3908 if (mssinceflash < MIN_MS_SINCE_FLASH) {
3909 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3910 hanging up. Hangup both channels now */
3911 if (p->subs[SUB_THREEWAY].owner)
3912 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
3913 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3914 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
3915 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3916 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
3917 if (p->transfer) {
3918 /* In any case this isn't a threeway call anymore */
3919 p->subs[SUB_REAL].inthreeway = 0;
3920 p->subs[SUB_THREEWAY].inthreeway = 0;
3921 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
3922 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
3923 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3924 /* Swap subs and dis-own channel */
3925 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3926 p->owner = NULL;
3927 /* Ring the phone */
3928 dahdi_ring_phone(p);
3929 } else {
3930 if ((res = attempt_transfer(p)) < 0) {
3931 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3932 if (p->subs[SUB_THREEWAY].owner)
3933 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3934 } else if (res) {
3935 /* Don't actually hang up at this point */
3936 if (p->subs[SUB_THREEWAY].owner)
3937 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3938 break;
3941 } else {
3942 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3943 if (p->subs[SUB_THREEWAY].owner)
3944 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3946 } else {
3947 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3948 /* Swap subs and dis-own channel */
3949 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3950 p->owner = NULL;
3951 /* Ring the phone */
3952 dahdi_ring_phone(p);
3955 } else {
3956 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
3958 /* Fall through */
3959 default:
3960 dahdi_disable_ec(p);
3961 return NULL;
3963 break;
3964 case DAHDI_EVENT_RINGOFFHOOK:
3965 if (p->inalarm) break;
3966 if (p->oprmode < 0)
3968 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3970 /* Make sure it stops ringing */
3971 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3972 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
3973 restore_conference(p->oprpeer);
3975 break;
3977 if (p->radio)
3979 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3980 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
3981 break;
3983 /* for E911, its supposed to wait for offhook then dial
3984 the second half of the dial string */
3985 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
3986 c = strchr(p->dialdest, '/');
3987 if (c)
3988 c++;
3989 else
3990 c = p->dialdest;
3991 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
3992 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
3993 if (strlen(p->dop.dialstr) > 4) {
3994 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
3995 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
3996 p->echorest[sizeof(p->echorest) - 1] = '\0';
3997 p->echobreak = 1;
3998 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
3999 } else
4000 p->echobreak = 0;
4001 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
4002 int saveerr = errno;
4004 x = DAHDI_ONHOOK;
4005 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4006 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4007 return NULL;
4009 p->dialing = 1;
4010 return &p->subs[index].f;
4012 switch (p->sig) {
4013 case SIG_FXOLS:
4014 case SIG_FXOGS:
4015 case SIG_FXOKS:
4016 switch (ast->_state) {
4017 case AST_STATE_RINGING:
4018 dahdi_enable_ec(p);
4019 dahdi_train_ec(p);
4020 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4021 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4022 /* Make sure it stops ringing */
4023 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4024 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4025 if (p->cidspill) {
4026 /* Cancel any running CallerID spill */
4027 free(p->cidspill);
4028 p->cidspill = NULL;
4030 p->dialing = 0;
4031 p->callwaitcas = 0;
4032 if (p->confirmanswer) {
4033 /* Ignore answer if "confirm answer" is enabled */
4034 p->subs[index].f.frametype = AST_FRAME_NULL;
4035 p->subs[index].f.subclass = 0;
4036 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4037 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4038 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4039 if (res < 0) {
4040 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4041 p->dop.dialstr[0] = '\0';
4042 return NULL;
4043 } else {
4044 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4045 p->subs[index].f.frametype = AST_FRAME_NULL;
4046 p->subs[index].f.subclass = 0;
4047 p->dialing = 1;
4049 p->dop.dialstr[0] = '\0';
4050 ast_setstate(ast, AST_STATE_DIALING);
4051 } else
4052 ast_setstate(ast, AST_STATE_UP);
4053 return &p->subs[index].f;
4054 case AST_STATE_DOWN:
4055 ast_setstate(ast, AST_STATE_RING);
4056 ast->rings = 1;
4057 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4058 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4059 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4060 return &p->subs[index].f;
4061 case AST_STATE_UP:
4062 /* Make sure it stops ringing */
4063 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4064 /* Okay -- probably call waiting*/
4065 if (ast_bridged_channel(p->owner))
4066 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4067 p->subs[index].needunhold = 1;
4068 break;
4069 case AST_STATE_RESERVED:
4070 /* Start up dialtone */
4071 if (has_voicemail(p))
4072 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4073 else
4074 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4075 break;
4076 default:
4077 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4079 break;
4080 case SIG_FXSLS:
4081 case SIG_FXSGS:
4082 case SIG_FXSKS:
4083 if (ast->_state == AST_STATE_RING) {
4084 p->ringt = p->ringt_base;
4087 /* Fall through */
4088 case SIG_EM:
4089 case SIG_EM_E1:
4090 case SIG_EMWINK:
4091 case SIG_FEATD:
4092 case SIG_FEATDMF:
4093 case SIG_FEATDMF_TA:
4094 case SIG_E911:
4095 case SIG_FGC_CAMA:
4096 case SIG_FGC_CAMAMF:
4097 case SIG_FEATB:
4098 case SIG_SF:
4099 case SIG_SFWINK:
4100 case SIG_SF_FEATD:
4101 case SIG_SF_FEATDMF:
4102 case SIG_SF_FEATB:
4103 if (ast->_state == AST_STATE_PRERING)
4104 ast_setstate(ast, AST_STATE_RING);
4105 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4106 if (option_debug)
4107 ast_log(LOG_DEBUG, "Ring detected\n");
4108 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4109 p->subs[index].f.subclass = AST_CONTROL_RING;
4110 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4111 if (option_debug)
4112 ast_log(LOG_DEBUG, "Line answered\n");
4113 if (p->confirmanswer) {
4114 p->subs[index].f.frametype = AST_FRAME_NULL;
4115 p->subs[index].f.subclass = 0;
4116 } else {
4117 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4118 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4119 ast_setstate(ast, AST_STATE_UP);
4121 } else if (ast->_state != AST_STATE_RING)
4122 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4123 break;
4124 default:
4125 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4127 break;
4128 #ifdef DAHDI_EVENT_RINGBEGIN
4129 case DAHDI_EVENT_RINGBEGIN:
4130 switch (p->sig) {
4131 case SIG_FXSLS:
4132 case SIG_FXSGS:
4133 case SIG_FXSKS:
4134 if (ast->_state == AST_STATE_RING) {
4135 p->ringt = p->ringt_base;
4137 break;
4139 break;
4140 #endif
4141 case DAHDI_EVENT_RINGEROFF:
4142 if (p->inalarm) break;
4143 if ((p->radio || (p->oprmode < 0))) break;
4144 ast->rings++;
4145 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4146 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4147 free(p->cidspill);
4148 p->cidspill = NULL;
4149 p->callwaitcas = 0;
4151 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4152 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4153 break;
4154 case DAHDI_EVENT_RINGERON:
4155 break;
4156 case DAHDI_EVENT_NOALARM:
4157 p->inalarm = 0;
4158 #ifdef HAVE_PRI
4159 /* Extremely unlikely but just in case */
4160 if (p->bearer)
4161 p->bearer->inalarm = 0;
4162 #endif
4163 if (!p->unknown_alarm) {
4164 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4165 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4166 "Channel: %d\r\n", p->channel);
4167 } else {
4168 p->unknown_alarm = 0;
4170 break;
4171 case DAHDI_EVENT_WINKFLASH:
4172 if (p->inalarm) break;
4173 if (p->radio) break;
4174 if (p->oprmode < 0) break;
4175 if (p->oprmode > 1)
4177 DAHDI_PARAMS par;
4179 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4181 if (!par.rxisoffhook)
4183 /* Make sure it stops ringing */
4184 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4185 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4186 save_conference(p);
4187 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4190 break;
4192 /* Remember last time we got a flash-hook */
4193 gettimeofday(&p->flashtime, NULL);
4194 switch (mysig) {
4195 case SIG_FXOLS:
4196 case SIG_FXOGS:
4197 case SIG_FXOKS:
4198 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4199 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4200 p->callwaitcas = 0;
4202 if (index != SUB_REAL) {
4203 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4204 goto winkflashdone;
4207 if (p->subs[SUB_CALLWAIT].owner) {
4208 /* Swap to call-wait */
4209 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4210 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4211 p->owner = p->subs[SUB_REAL].owner;
4212 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4213 if (p->owner->_state == AST_STATE_RINGING) {
4214 ast_setstate(p->owner, AST_STATE_UP);
4215 p->subs[SUB_REAL].needanswer = 1;
4217 p->callwaitingrepeat = 0;
4218 p->cidcwexpire = 0;
4219 /* Start music on hold if appropriate */
4220 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4221 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4222 S_OR(p->mohsuggest, NULL),
4223 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4225 p->subs[SUB_CALLWAIT].needhold = 1;
4226 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4227 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4228 S_OR(p->mohsuggest, NULL),
4229 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4231 p->subs[SUB_REAL].needunhold = 1;
4232 } else if (!p->subs[SUB_THREEWAY].owner) {
4233 char cid_num[256];
4234 char cid_name[256];
4236 if (!p->threewaycalling) {
4237 /* Just send a flash if no 3-way calling */
4238 p->subs[SUB_REAL].needflash = 1;
4239 goto winkflashdone;
4240 } else if (!check_for_conference(p)) {
4241 if (p->dahditrcallerid && p->owner) {
4242 if (p->owner->cid.cid_num)
4243 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4244 if (p->owner->cid.cid_name)
4245 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4247 /* XXX This section needs much more error checking!!! XXX */
4248 /* Start a 3-way call if feasible */
4249 if (!((ast->pbx) ||
4250 (ast->_state == AST_STATE_UP) ||
4251 (ast->_state == AST_STATE_RING))) {
4252 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4253 goto winkflashdone;
4255 if (alloc_sub(p, SUB_THREEWAY)) {
4256 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4257 goto winkflashdone;
4259 /* Make new channel */
4260 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4261 if (p->dahditrcallerid) {
4262 if (!p->origcid_num)
4263 p->origcid_num = ast_strdup(p->cid_num);
4264 if (!p->origcid_name)
4265 p->origcid_name = ast_strdup(p->cid_name);
4266 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4267 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4269 /* Swap things around between the three-way and real call */
4270 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4271 /* Disable echo canceller for better dialing */
4272 dahdi_disable_ec(p);
4273 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4274 if (res)
4275 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4276 p->owner = chan;
4277 pthread_attr_init(&attr);
4278 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4279 if (!chan) {
4280 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4281 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4282 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4283 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4284 dahdi_enable_ec(p);
4285 ast_hangup(chan);
4286 } else {
4287 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4288 int way3bridge = 0, cdr3way = 0;
4290 if (!other) {
4291 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4292 } else
4293 way3bridge = 1;
4295 if (p->subs[SUB_THREEWAY].owner->cdr)
4296 cdr3way = 1;
4298 if (option_verbose > 2)
4299 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4300 /* Start music on hold if appropriate */
4301 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4302 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4303 S_OR(p->mohsuggest, NULL),
4304 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4306 p->subs[SUB_THREEWAY].needhold = 1;
4308 pthread_attr_destroy(&attr);
4310 } else {
4311 /* Already have a 3 way call */
4312 if (p->subs[SUB_THREEWAY].inthreeway) {
4313 /* Call is already up, drop the last person */
4314 if (option_debug)
4315 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4316 /* If the primary call isn't answered yet, use it */
4317 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4318 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4319 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4320 p->owner = p->subs[SUB_REAL].owner;
4322 /* Drop the last call and stop the conference */
4323 if (option_verbose > 2)
4324 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4325 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4326 p->subs[SUB_REAL].inthreeway = 0;
4327 p->subs[SUB_THREEWAY].inthreeway = 0;
4328 } else {
4329 /* Lets see what we're up to */
4330 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4331 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4332 int otherindex = SUB_THREEWAY;
4333 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4334 int way3bridge = 0, cdr3way = 0;
4336 if (!other) {
4337 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4338 } else
4339 way3bridge = 1;
4341 if (p->subs[SUB_THREEWAY].owner->cdr)
4342 cdr3way = 1;
4344 if (option_verbose > 2)
4345 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);
4346 /* Put them in the threeway, and flip */
4347 p->subs[SUB_THREEWAY].inthreeway = 1;
4348 p->subs[SUB_REAL].inthreeway = 1;
4349 if (ast->_state == AST_STATE_UP) {
4350 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4351 otherindex = SUB_REAL;
4353 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4354 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4355 p->subs[otherindex].needunhold = 1;
4356 p->owner = p->subs[SUB_REAL].owner;
4357 if (ast->_state == AST_STATE_RINGING) {
4358 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4359 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4360 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4362 } else {
4363 if (option_verbose > 2)
4364 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4365 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4366 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4367 p->owner = p->subs[SUB_REAL].owner;
4368 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4369 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4370 p->subs[SUB_REAL].needunhold = 1;
4371 dahdi_enable_ec(p);
4376 winkflashdone:
4377 update_conf(p);
4378 break;
4379 case SIG_EM:
4380 case SIG_EM_E1:
4381 case SIG_EMWINK:
4382 case SIG_FEATD:
4383 case SIG_SF:
4384 case SIG_SFWINK:
4385 case SIG_SF_FEATD:
4386 case SIG_FXSLS:
4387 case SIG_FXSGS:
4388 if (p->dialing)
4389 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4390 else
4391 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4392 break;
4393 case SIG_FEATDMF_TA:
4394 switch (p->whichwink) {
4395 case 0:
4396 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4397 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4398 break;
4399 case 1:
4400 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4401 break;
4402 case 2:
4403 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4404 return NULL;
4406 p->whichwink++;
4407 /* Fall through */
4408 case SIG_FEATDMF:
4409 case SIG_E911:
4410 case SIG_FGC_CAMAMF:
4411 case SIG_FGC_CAMA:
4412 case SIG_FEATB:
4413 case SIG_SF_FEATDMF:
4414 case SIG_SF_FEATB:
4415 /* FGD MF *Must* wait for wink */
4416 if (!ast_strlen_zero(p->dop.dialstr)) {
4417 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4418 if (res < 0) {
4419 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4420 p->dop.dialstr[0] = '\0';
4421 return NULL;
4422 } else
4423 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4425 p->dop.dialstr[0] = '\0';
4426 break;
4427 default:
4428 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4430 break;
4431 case DAHDI_EVENT_HOOKCOMPLETE:
4432 if (p->inalarm) break;
4433 if ((p->radio || (p->oprmode < 0))) break;
4434 switch (mysig) {
4435 case SIG_FXSLS: /* only interesting for FXS */
4436 case SIG_FXSGS:
4437 case SIG_FXSKS:
4438 case SIG_EM:
4439 case SIG_EM_E1:
4440 case SIG_EMWINK:
4441 case SIG_FEATD:
4442 case SIG_SF:
4443 case SIG_SFWINK:
4444 case SIG_SF_FEATD:
4445 if (!ast_strlen_zero(p->dop.dialstr)) {
4446 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4447 if (res < 0) {
4448 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4449 p->dop.dialstr[0] = '\0';
4450 return NULL;
4451 } else
4452 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4454 p->dop.dialstr[0] = '\0';
4455 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4456 break;
4457 case SIG_FEATDMF:
4458 case SIG_FEATDMF_TA:
4459 case SIG_E911:
4460 case SIG_FGC_CAMA:
4461 case SIG_FGC_CAMAMF:
4462 case SIG_FEATB:
4463 case SIG_SF_FEATDMF:
4464 case SIG_SF_FEATB:
4465 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4466 break;
4467 default:
4468 break;
4470 break;
4471 case DAHDI_EVENT_POLARITY:
4473 * If we get a Polarity Switch event, check to see
4474 * if we should change the polarity state and
4475 * mark the channel as UP or if this is an indication
4476 * of remote end disconnect.
4478 if (p->polarity == POLARITY_IDLE) {
4479 p->polarity = POLARITY_REV;
4480 if (p->answeronpolarityswitch &&
4481 ((ast->_state == AST_STATE_DIALING) ||
4482 (ast->_state == AST_STATE_RINGING))) {
4483 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4484 ast_setstate(p->owner, AST_STATE_UP);
4485 if (p->hanguponpolarityswitch) {
4486 gettimeofday(&p->polaritydelaytv, NULL);
4488 } else
4489 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4491 /* Removed else statement from here as it was preventing hangups from ever happening*/
4492 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4493 if (p->hanguponpolarityswitch &&
4494 (p->polarityonanswerdelay > 0) &&
4495 (p->polarity == POLARITY_REV) &&
4496 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4497 /* Added log_debug information below to provide a better indication of what is going on */
4498 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) );
4500 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4501 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4502 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4503 p->polarity = POLARITY_IDLE;
4504 } else {
4505 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);
4507 } else {
4508 p->polarity = POLARITY_IDLE;
4509 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4511 /* Added more log_debug information below to provide a better indication of what is going on */
4512 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) );
4513 break;
4514 default:
4515 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4517 return &p->subs[index].f;
4520 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4522 struct dahdi_pvt *p = ast->tech_pvt;
4523 int res;
4524 int usedindex=-1;
4525 int index;
4526 struct ast_frame *f;
4529 index = dahdi_get_index(ast, p, 1);
4531 p->subs[index].f.frametype = AST_FRAME_NULL;
4532 p->subs[index].f.datalen = 0;
4533 p->subs[index].f.samples = 0;
4534 p->subs[index].f.mallocd = 0;
4535 p->subs[index].f.offset = 0;
4536 p->subs[index].f.subclass = 0;
4537 p->subs[index].f.delivery = ast_tv(0,0);
4538 p->subs[index].f.src = "dahdi_exception";
4539 p->subs[index].f.data = NULL;
4542 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4543 /* If nobody owns us, absorb the event appropriately, otherwise
4544 we loop indefinitely. This occurs when, during call waiting, the
4545 other end hangs up our channel so that it no longer exists, but we
4546 have neither FLASH'd nor ONHOOK'd to signify our desire to
4547 change to the other channel. */
4548 if (p->fake_event) {
4549 res = p->fake_event;
4550 p->fake_event = 0;
4551 } else
4552 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4553 /* Switch to real if there is one and this isn't something really silly... */
4554 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4555 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4556 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4557 p->owner = p->subs[SUB_REAL].owner;
4558 if (p->owner && ast_bridged_channel(p->owner))
4559 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4560 p->subs[SUB_REAL].needunhold = 1;
4562 switch (res) {
4563 case DAHDI_EVENT_ONHOOK:
4564 dahdi_disable_ec(p);
4565 if (p->owner) {
4566 if (option_verbose > 2)
4567 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4568 dahdi_ring_phone(p);
4569 p->callwaitingrepeat = 0;
4570 p->cidcwexpire = 0;
4571 } else
4572 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4573 update_conf(p);
4574 break;
4575 case DAHDI_EVENT_RINGOFFHOOK:
4576 dahdi_enable_ec(p);
4577 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4578 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4579 p->subs[SUB_REAL].needanswer = 1;
4580 p->dialing = 0;
4582 break;
4583 case DAHDI_EVENT_HOOKCOMPLETE:
4584 case DAHDI_EVENT_RINGERON:
4585 case DAHDI_EVENT_RINGEROFF:
4586 /* Do nothing */
4587 break;
4588 case DAHDI_EVENT_WINKFLASH:
4589 gettimeofday(&p->flashtime, NULL);
4590 if (p->owner) {
4591 if (option_verbose > 2)
4592 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4593 if (p->owner->_state != AST_STATE_UP) {
4594 /* Answer if necessary */
4595 usedindex = dahdi_get_index(p->owner, p, 0);
4596 if (usedindex > -1) {
4597 p->subs[usedindex].needanswer = 1;
4599 ast_setstate(p->owner, AST_STATE_UP);
4601 p->callwaitingrepeat = 0;
4602 p->cidcwexpire = 0;
4603 if (ast_bridged_channel(p->owner))
4604 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4605 p->subs[SUB_REAL].needunhold = 1;
4606 } else
4607 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4608 update_conf(p);
4609 break;
4610 default:
4611 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4613 f = &p->subs[index].f;
4614 return f;
4616 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4617 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4618 /* If it's not us, return NULL immediately */
4619 if (ast != p->owner) {
4620 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4621 f = &p->subs[index].f;
4622 return f;
4624 f = dahdi_handle_event(ast);
4625 return f;
4628 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4630 struct dahdi_pvt *p = ast->tech_pvt;
4631 struct ast_frame *f;
4632 ast_mutex_lock(&p->lock);
4633 f = __dahdi_exception(ast);
4634 ast_mutex_unlock(&p->lock);
4635 return f;
4638 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4640 struct dahdi_pvt *p = ast->tech_pvt;
4641 int res;
4642 int index;
4643 void *readbuf;
4644 struct ast_frame *f;
4646 while (ast_mutex_trylock(&p->lock)) {
4647 DEADLOCK_AVOIDANCE(&ast->lock);
4650 index = dahdi_get_index(ast, p, 0);
4652 /* Hang up if we don't really exist */
4653 if (index < 0) {
4654 ast_log(LOG_WARNING, "We dont exist?\n");
4655 ast_mutex_unlock(&p->lock);
4656 return NULL;
4659 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4661 p->subs[index].f.frametype = AST_FRAME_NULL;
4662 p->subs[index].f.datalen = 0;
4663 p->subs[index].f.samples = 0;
4664 p->subs[index].f.mallocd = 0;
4665 p->subs[index].f.offset = 0;
4666 p->subs[index].f.subclass = 0;
4667 p->subs[index].f.delivery = ast_tv(0,0);
4668 p->subs[index].f.src = "dahdi_read";
4669 p->subs[index].f.data = NULL;
4671 /* make sure it sends initial key state as first frame */
4672 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4674 DAHDI_PARAMS ps;
4676 ps.channo = p->channel;
4677 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4678 ast_mutex_unlock(&p->lock);
4679 return NULL;
4681 p->firstradio = 1;
4682 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4683 if (ps.rxisoffhook)
4685 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4687 else
4689 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4691 ast_mutex_unlock(&p->lock);
4692 return &p->subs[index].f;
4694 if (p->ringt == 1) {
4695 ast_mutex_unlock(&p->lock);
4696 return NULL;
4698 else if (p->ringt > 0)
4699 p->ringt--;
4701 if (p->subs[index].needringing) {
4702 /* Send ringing frame if requested */
4703 p->subs[index].needringing = 0;
4704 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4705 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4706 ast_setstate(ast, AST_STATE_RINGING);
4707 ast_mutex_unlock(&p->lock);
4708 return &p->subs[index].f;
4711 if (p->subs[index].needbusy) {
4712 /* Send busy frame if requested */
4713 p->subs[index].needbusy = 0;
4714 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4715 p->subs[index].f.subclass = AST_CONTROL_BUSY;
4716 ast_mutex_unlock(&p->lock);
4717 return &p->subs[index].f;
4720 if (p->subs[index].needcongestion) {
4721 /* Send congestion frame if requested */
4722 p->subs[index].needcongestion = 0;
4723 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4724 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
4725 ast_mutex_unlock(&p->lock);
4726 return &p->subs[index].f;
4729 if (p->subs[index].needcallerid) {
4730 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
4731 S_OR(p->lastcid_name, NULL),
4732 S_OR(p->lastcid_num, NULL)
4734 p->subs[index].needcallerid = 0;
4737 if (p->subs[index].needanswer) {
4738 /* Send answer frame if requested */
4739 p->subs[index].needanswer = 0;
4740 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4741 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4742 ast_mutex_unlock(&p->lock);
4743 return &p->subs[index].f;
4746 if (p->subs[index].needflash) {
4747 /* Send answer frame if requested */
4748 p->subs[index].needflash = 0;
4749 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4750 p->subs[index].f.subclass = AST_CONTROL_FLASH;
4751 ast_mutex_unlock(&p->lock);
4752 return &p->subs[index].f;
4755 if (p->subs[index].needhold) {
4756 /* Send answer frame if requested */
4757 p->subs[index].needhold = 0;
4758 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4759 p->subs[index].f.subclass = AST_CONTROL_HOLD;
4760 ast_mutex_unlock(&p->lock);
4761 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
4762 return &p->subs[index].f;
4765 if (p->subs[index].needunhold) {
4766 /* Send answer frame if requested */
4767 p->subs[index].needunhold = 0;
4768 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4769 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
4770 ast_mutex_unlock(&p->lock);
4771 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
4772 return &p->subs[index].f;
4775 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
4776 if (!p->subs[index].linear) {
4777 p->subs[index].linear = 1;
4778 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4779 if (res)
4780 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
4782 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
4783 (ast->rawreadformat == AST_FORMAT_ALAW)) {
4784 if (p->subs[index].linear) {
4785 p->subs[index].linear = 0;
4786 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4787 if (res)
4788 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
4790 } else {
4791 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
4792 ast_mutex_unlock(&p->lock);
4793 return NULL;
4795 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
4796 CHECK_BLOCKING(ast);
4797 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4798 ast_clear_flag(ast, AST_FLAG_BLOCKING);
4799 /* Check for hangup */
4800 if (res < 0) {
4801 f = NULL;
4802 if (res == -1) {
4803 if (errno == EAGAIN) {
4804 /* Return "NULL" frame if there is nobody there */
4805 ast_mutex_unlock(&p->lock);
4806 return &p->subs[index].f;
4807 } else if (errno == ELAST) {
4808 f = __dahdi_exception(ast);
4809 } else
4810 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
4812 ast_mutex_unlock(&p->lock);
4813 return f;
4815 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
4816 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4817 f = __dahdi_exception(ast);
4818 ast_mutex_unlock(&p->lock);
4819 return f;
4821 if (p->tdd) { /* if in TDD mode, see if we receive that */
4822 int c;
4824 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
4825 if (c < 0) {
4826 ast_log(LOG_DEBUG,"tdd_feed failed\n");
4827 ast_mutex_unlock(&p->lock);
4828 return NULL;
4830 if (c) { /* if a char to return */
4831 p->subs[index].f.subclass = 0;
4832 p->subs[index].f.frametype = AST_FRAME_TEXT;
4833 p->subs[index].f.mallocd = 0;
4834 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4835 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
4836 p->subs[index].f.datalen = 1;
4837 *((char *) p->subs[index].f.data) = c;
4838 ast_mutex_unlock(&p->lock);
4839 return &p->subs[index].f;
4842 /* Ensure the CW timer decrements only on a single subchannel */
4843 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
4844 p->callwaitingrepeat--;
4846 if (p->cidcwexpire)
4847 p->cidcwexpire--;
4848 /* Repeat callwaiting */
4849 if (p->callwaitingrepeat == 1) {
4850 p->callwaitrings++;
4851 dahdi_callwait(ast);
4853 /* Expire CID/CW */
4854 if (p->cidcwexpire == 1) {
4855 if (option_verbose > 2)
4856 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
4857 restore_conference(p);
4859 if (p->subs[index].linear) {
4860 p->subs[index].f.datalen = READ_SIZE * 2;
4861 } else
4862 p->subs[index].f.datalen = READ_SIZE;
4864 /* Handle CallerID Transmission */
4865 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
4866 send_callerid(p);
4869 p->subs[index].f.frametype = AST_FRAME_VOICE;
4870 p->subs[index].f.subclass = ast->rawreadformat;
4871 p->subs[index].f.samples = READ_SIZE;
4872 p->subs[index].f.mallocd = 0;
4873 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4874 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
4875 #if 0
4876 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
4877 #endif
4878 if (p->dialing || /* Transmitting something */
4879 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
4880 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
4882 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4883 don't send anything */
4884 p->subs[index].f.frametype = AST_FRAME_NULL;
4885 p->subs[index].f.subclass = 0;
4886 p->subs[index].f.samples = 0;
4887 p->subs[index].f.mallocd = 0;
4888 p->subs[index].f.offset = 0;
4889 p->subs[index].f.data = NULL;
4890 p->subs[index].f.datalen= 0;
4892 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
4893 /* Perform busy detection. etc on the dahdi line */
4894 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
4895 if (f) {
4896 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
4897 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
4898 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4899 a busy */
4900 f = NULL;
4902 } else if (f->frametype == AST_FRAME_DTMF) {
4903 #ifdef HAVE_PRI
4904 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
4905 /* Don't accept in-band DTMF when in overlap dial mode */
4906 f->frametype = AST_FRAME_NULL;
4907 f->subclass = 0;
4909 #endif
4910 /* DSP clears us of being pulse */
4911 p->pulsedial = 0;
4914 } else
4915 f = &p->subs[index].f;
4917 if (f && (f->frametype == AST_FRAME_DTMF))
4918 dahdi_handle_dtmfup(ast, index, &f);
4920 /* If we have a fake_event, trigger exception to handle it */
4921 if (p->fake_event)
4922 ast_set_flag(ast, AST_FLAG_EXCEPTION);
4924 ast_mutex_unlock(&p->lock);
4925 return f;
4928 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
4930 int sent=0;
4931 int size;
4932 int res;
4933 int fd;
4934 fd = p->subs[index].dfd;
4935 while (len) {
4936 size = len;
4937 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
4938 size = (linear ? READ_SIZE * 2 : READ_SIZE);
4939 res = write(fd, buf, size);
4940 if (res != size) {
4941 if (option_debug)
4942 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
4943 return sent;
4945 len -= size;
4946 buf += size;
4948 return sent;
4951 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
4953 struct dahdi_pvt *p = ast->tech_pvt;
4954 int res;
4955 int index;
4956 index = dahdi_get_index(ast, p, 0);
4957 if (index < 0) {
4958 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
4959 return -1;
4962 #if 0
4963 #ifdef HAVE_PRI
4964 ast_mutex_lock(&p->lock);
4965 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
4966 if (p->pri->pri) {
4967 if (!pri_grab(p, p->pri)) {
4968 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
4969 pri_rel(p->pri);
4970 } else
4971 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
4973 p->proceeding=1;
4975 ast_mutex_unlock(&p->lock);
4976 #endif
4977 #endif
4978 /* Write a frame of (presumably voice) data */
4979 if (frame->frametype != AST_FRAME_VOICE) {
4980 if (frame->frametype != AST_FRAME_IMAGE)
4981 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
4982 return 0;
4984 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
4985 (frame->subclass != AST_FORMAT_ULAW) &&
4986 (frame->subclass != AST_FORMAT_ALAW)) {
4987 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
4988 return -1;
4990 if (p->dialing) {
4991 if (option_debug)
4992 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
4993 return 0;
4995 if (!p->owner) {
4996 if (option_debug)
4997 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
4998 return 0;
5000 if (p->cidspill) {
5001 if (option_debug)
5002 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5003 return 0;
5005 /* Return if it's not valid data */
5006 if (!frame->data || !frame->datalen)
5007 return 0;
5009 if (frame->subclass == AST_FORMAT_SLINEAR) {
5010 if (!p->subs[index].linear) {
5011 p->subs[index].linear = 1;
5012 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5013 if (res)
5014 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5016 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5017 } else {
5018 /* x-law already */
5019 if (p->subs[index].linear) {
5020 p->subs[index].linear = 0;
5021 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5022 if (res)
5023 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5025 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5027 if (res < 0) {
5028 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5029 return -1;
5031 return 0;
5034 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5036 struct dahdi_pvt *p = chan->tech_pvt;
5037 int res=-1;
5038 int index;
5039 int func = DAHDI_FLASH;
5040 ast_mutex_lock(&p->lock);
5041 index = dahdi_get_index(chan, p, 0);
5042 if (option_debug)
5043 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5044 if (index == SUB_REAL) {
5045 switch (condition) {
5046 case AST_CONTROL_BUSY:
5047 #ifdef HAVE_PRI
5048 if (p->priindication_oob && p->sig == SIG_PRI) {
5049 chan->hangupcause = AST_CAUSE_USER_BUSY;
5050 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5051 res = 0;
5052 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5053 if (p->pri->pri) {
5054 if (!pri_grab(p, p->pri)) {
5055 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5056 pri_rel(p->pri);
5058 else
5059 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5061 p->progress = 1;
5062 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5063 } else
5064 #endif
5065 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5066 break;
5067 case AST_CONTROL_RINGING:
5068 #ifdef HAVE_PRI
5069 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5070 if (p->pri->pri) {
5071 if (!pri_grab(p, p->pri)) {
5072 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5073 pri_rel(p->pri);
5075 else
5076 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5078 p->alerting = 1;
5080 #endif
5081 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5082 if (chan->_state != AST_STATE_UP) {
5083 if ((chan->_state != AST_STATE_RING) ||
5084 ((p->sig != SIG_FXSKS) &&
5085 (p->sig != SIG_FXSLS) &&
5086 (p->sig != SIG_FXSGS)))
5087 ast_setstate(chan, AST_STATE_RINGING);
5089 break;
5090 case AST_CONTROL_PROCEEDING:
5091 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5092 #ifdef HAVE_PRI
5093 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5094 if (p->pri->pri) {
5095 if (!pri_grab(p, p->pri)) {
5096 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5097 pri_rel(p->pri);
5099 else
5100 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5102 p->proceeding = 1;
5104 #endif
5105 /* don't continue in ast_indicate */
5106 res = 0;
5107 break;
5108 case AST_CONTROL_PROGRESS:
5109 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5110 #ifdef HAVE_PRI
5111 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5112 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5113 if (p->pri->pri) {
5114 if (!pri_grab(p, p->pri)) {
5115 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5116 pri_rel(p->pri);
5118 else
5119 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5121 p->progress = 1;
5123 #endif
5124 /* don't continue in ast_indicate */
5125 res = 0;
5126 break;
5127 case AST_CONTROL_CONGESTION:
5128 chan->hangupcause = AST_CAUSE_CONGESTION;
5129 #ifdef HAVE_PRI
5130 if (p->priindication_oob && p->sig == SIG_PRI) {
5131 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5132 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5133 res = 0;
5134 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5135 if (p->pri) {
5136 if (!pri_grab(p, p->pri)) {
5137 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5138 pri_rel(p->pri);
5139 } else
5140 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5142 p->progress = 1;
5143 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5144 } else
5145 #endif
5146 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5147 break;
5148 case AST_CONTROL_HOLD:
5149 #ifdef HAVE_PRI
5150 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5151 if (!pri_grab(p, p->pri)) {
5152 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5153 pri_rel(p->pri);
5154 } else
5155 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5156 } else
5157 #endif
5158 ast_moh_start(chan, data, p->mohinterpret);
5159 break;
5160 case AST_CONTROL_UNHOLD:
5161 #ifdef HAVE_PRI
5162 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5163 if (!pri_grab(p, p->pri)) {
5164 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5165 pri_rel(p->pri);
5166 } else
5167 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5168 } else
5169 #endif
5170 ast_moh_stop(chan);
5171 break;
5172 case AST_CONTROL_RADIO_KEY:
5173 if (p->radio)
5174 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5175 res = 0;
5176 break;
5177 case AST_CONTROL_RADIO_UNKEY:
5178 if (p->radio)
5179 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5180 res = 0;
5181 break;
5182 case AST_CONTROL_FLASH:
5183 /* flash hookswitch */
5184 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5185 /* Clear out the dial buffer */
5186 p->dop.dialstr[0] = '\0';
5187 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5188 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5189 chan->name, strerror(errno));
5190 } else
5191 res = 0;
5192 } else
5193 res = 0;
5194 break;
5195 case AST_CONTROL_SRCUPDATE:
5196 res = 0;
5197 break;
5198 case -1:
5199 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5200 break;
5202 } else
5203 res = 0;
5204 ast_mutex_unlock(&p->lock);
5205 return res;
5208 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5210 struct ast_channel *tmp;
5211 int deflaw;
5212 int res;
5213 int x,y;
5214 int features;
5215 char *b2 = NULL;
5216 DAHDI_PARAMS ps;
5217 if (i->subs[index].owner) {
5218 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5219 return NULL;
5221 y = 1;
5222 do {
5223 if (b2)
5224 free(b2);
5225 #ifdef HAVE_PRI
5226 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5227 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5228 else
5229 #endif
5230 if (i->channel == CHAN_PSEUDO)
5231 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5232 else
5233 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5234 for (x = 0; x < 3; x++) {
5235 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
5236 break;
5238 y++;
5239 } while (x < 3);
5240 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", b2);
5241 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5242 free(b2);
5243 if (!tmp)
5244 return NULL;
5245 tmp->tech = &dahdi_tech;
5246 ps.channo = i->channel;
5247 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5248 if (res) {
5249 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5250 ps.curlaw = DAHDI_LAW_MULAW;
5252 if (ps.curlaw == DAHDI_LAW_ALAW)
5253 deflaw = AST_FORMAT_ALAW;
5254 else
5255 deflaw = AST_FORMAT_ULAW;
5256 if (law) {
5257 if (law == DAHDI_LAW_ALAW)
5258 deflaw = AST_FORMAT_ALAW;
5259 else
5260 deflaw = AST_FORMAT_ULAW;
5262 tmp->fds[0] = i->subs[index].dfd;
5263 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5264 /* Start out assuming ulaw since it's smaller :) */
5265 tmp->rawreadformat = deflaw;
5266 tmp->readformat = deflaw;
5267 tmp->rawwriteformat = deflaw;
5268 tmp->writeformat = deflaw;
5269 i->subs[index].linear = 0;
5270 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5271 features = 0;
5272 if (index == SUB_REAL) {
5273 if (i->busydetect && CANBUSYDETECT(i))
5274 features |= DSP_FEATURE_BUSY_DETECT;
5275 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5276 features |= DSP_FEATURE_CALL_PROGRESS;
5277 if ((!i->outgoing && (i->callprogress & 4)) ||
5278 (i->outgoing && (i->callprogress & 2))) {
5279 features |= DSP_FEATURE_FAX_DETECT;
5281 #ifdef DAHDI_TONEDETECT
5282 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5283 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5284 #endif
5285 i->hardwaredtmf = 0;
5286 features |= DSP_FEATURE_DTMF_DETECT;
5287 #ifdef DAHDI_TONEDETECT
5288 } else if (NEED_MFDETECT(i)) {
5289 i->hardwaredtmf = 1;
5290 features |= DSP_FEATURE_DTMF_DETECT;
5292 #endif
5294 if (features) {
5295 if (i->dsp) {
5296 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5297 } else {
5298 if (i->channel != CHAN_PSEUDO)
5299 i->dsp = ast_dsp_new();
5300 else
5301 i->dsp = NULL;
5302 if (i->dsp) {
5303 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5304 #ifdef HAVE_PRI
5305 /* We cannot do progress detection until receives PROGRESS message */
5306 if (i->outgoing && (i->sig == SIG_PRI)) {
5307 /* Remember requested DSP features, don't treat
5308 talking as ANSWER */
5309 features = 0;
5311 #endif
5312 ast_dsp_set_features(i->dsp, features);
5313 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5314 if (!ast_strlen_zero(progzone))
5315 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5316 if (i->busydetect && CANBUSYDETECT(i)) {
5317 ast_dsp_set_busy_count(i->dsp, i->busycount);
5318 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5324 if (state == AST_STATE_RING)
5325 tmp->rings = 1;
5326 tmp->tech_pvt = i;
5327 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5328 /* Only FXO signalled stuff can be picked up */
5329 tmp->callgroup = i->callgroup;
5330 tmp->pickupgroup = i->pickupgroup;
5332 if (!ast_strlen_zero(i->language))
5333 ast_string_field_set(tmp, language, i->language);
5334 if (!i->owner)
5335 i->owner = tmp;
5336 if (!ast_strlen_zero(i->accountcode))
5337 ast_string_field_set(tmp, accountcode, i->accountcode);
5338 if (i->amaflags)
5339 tmp->amaflags = i->amaflags;
5340 i->subs[index].owner = tmp;
5341 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5342 ast_string_field_set(tmp, call_forward, i->call_forward);
5343 /* If we've been told "no ADSI" then enforce it */
5344 if (!i->adsi)
5345 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5346 if (!ast_strlen_zero(i->exten))
5347 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5348 if (!ast_strlen_zero(i->rdnis))
5349 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5350 if (!ast_strlen_zero(i->dnid))
5351 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5353 /* Don't use ast_set_callerid() here because it will
5354 * generate a needless NewCallerID event */
5355 #ifdef PRI_ANI
5356 if (!ast_strlen_zero(i->cid_ani))
5357 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5358 else
5359 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5360 #else
5361 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5362 #endif
5363 tmp->cid.cid_pres = i->callingpres;
5364 tmp->cid.cid_ton = i->cid_ton;
5365 #ifdef HAVE_PRI
5366 tmp->transfercapability = transfercapability;
5367 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5368 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5369 i->digital = 1;
5370 /* Assume calls are not idle calls unless we're told differently */
5371 i->isidlecall = 0;
5372 i->alreadyhungup = 0;
5373 #endif
5374 /* clear the fake event in case we posted one before we had ast_channel */
5375 i->fake_event = 0;
5376 /* Assure there is no confmute on this channel */
5377 dahdi_confmute(i, 0);
5378 /* Configure the new channel jb */
5379 ast_jb_configure(tmp, &global_jbconf);
5380 if (startpbx) {
5381 if (ast_pbx_start(tmp)) {
5382 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5383 ast_hangup(tmp);
5384 i->owner = NULL;
5385 return NULL;
5389 ast_module_ref(ast_module_info->self);
5391 return tmp;
5395 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5397 char c;
5399 *str = 0; /* start with empty output buffer */
5400 for (;;)
5402 /* Wait for the first digit (up to specified ms). */
5403 c = ast_waitfordigit(chan, ms);
5404 /* if timeout, hangup or error, return as such */
5405 if (c < 1)
5406 return c;
5407 *str++ = c;
5408 *str = 0;
5409 if (strchr(term, c))
5410 return 1;
5414 static int dahdi_wink(struct dahdi_pvt *p, int index)
5416 int j;
5417 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5418 for (;;)
5420 /* set bits of interest */
5421 j = DAHDI_IOMUX_SIGEVENT;
5422 /* wait for some happening */
5423 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5424 /* exit loop if we have it */
5425 if (j & DAHDI_IOMUX_SIGEVENT) break;
5427 /* get the event info */
5428 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5429 return 0;
5432 static void *ss_thread(void *data)
5434 struct ast_channel *chan = data;
5435 struct dahdi_pvt *p = chan->tech_pvt;
5436 char exten[AST_MAX_EXTENSION] = "";
5437 char exten2[AST_MAX_EXTENSION] = "";
5438 unsigned char buf[256];
5439 char dtmfcid[300];
5440 char dtmfbuf[300];
5441 struct callerid_state *cs = NULL;
5442 char *name = NULL, *number = NULL;
5443 int distMatches;
5444 int curRingData[3];
5445 int receivedRingT;
5446 int counter1;
5447 int counter;
5448 int samples = 0;
5449 struct ast_smdi_md_message *smdi_msg = NULL;
5450 int flags;
5451 int i;
5452 int timeout;
5453 int getforward = 0;
5454 char *s1, *s2;
5455 int len = 0;
5456 int res;
5457 int index;
5459 /* in the bizarre case where the channel has become a zombie before we
5460 even get started here, abort safely
5462 if (!p) {
5463 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5464 ast_hangup(chan);
5465 return NULL;
5468 if (option_verbose > 2)
5469 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5470 index = dahdi_get_index(chan, p, 1);
5471 if (index < 0) {
5472 ast_log(LOG_WARNING, "Huh?\n");
5473 ast_hangup(chan);
5474 return NULL;
5476 if (p->dsp)
5477 ast_dsp_digitreset(p->dsp);
5478 switch (p->sig) {
5479 #ifdef HAVE_PRI
5480 case SIG_PRI:
5481 /* Now loop looking for an extension */
5482 ast_copy_string(exten, p->exten, sizeof(exten));
5483 len = strlen(exten);
5484 res = 0;
5485 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5486 if (len && !ast_ignore_pattern(chan->context, exten))
5487 tone_zone_play_tone(p->subs[index].dfd, -1);
5488 else
5489 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5490 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5491 timeout = matchdigittimeout;
5492 else
5493 timeout = gendigittimeout;
5494 res = ast_waitfordigit(chan, timeout);
5495 if (res < 0) {
5496 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5497 ast_hangup(chan);
5498 return NULL;
5499 } else if (res) {
5500 exten[len++] = res;
5501 exten[len] = '\0';
5502 } else
5503 break;
5505 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5506 if (ast_strlen_zero(exten)) {
5507 if (option_verbose > 2)
5508 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5509 exten[0] = 's';
5510 exten[1] = '\0';
5512 tone_zone_play_tone(p->subs[index].dfd, -1);
5513 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5514 /* Start the real PBX */
5515 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5516 if (p->dsp) ast_dsp_digitreset(p->dsp);
5517 dahdi_enable_ec(p);
5518 ast_setstate(chan, AST_STATE_RING);
5519 res = ast_pbx_run(chan);
5520 if (res) {
5521 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5523 } else {
5524 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5525 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5526 ast_hangup(chan);
5527 p->exten[0] = '\0';
5528 /* Since we send release complete here, we won't get one */
5529 p->call = NULL;
5531 return NULL;
5532 break;
5533 #endif
5534 case SIG_FEATD:
5535 case SIG_FEATDMF:
5536 case SIG_FEATDMF_TA:
5537 case SIG_E911:
5538 case SIG_FGC_CAMAMF:
5539 case SIG_FEATB:
5540 case SIG_EMWINK:
5541 case SIG_SF_FEATD:
5542 case SIG_SF_FEATDMF:
5543 case SIG_SF_FEATB:
5544 case SIG_SFWINK:
5545 if (dahdi_wink(p, index))
5546 return NULL;
5547 /* Fall through */
5548 case SIG_EM:
5549 case SIG_EM_E1:
5550 case SIG_SF:
5551 case SIG_FGC_CAMA:
5552 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5553 if (p->dsp)
5554 ast_dsp_digitreset(p->dsp);
5555 /* set digit mode appropriately */
5556 if (p->dsp) {
5557 if (NEED_MFDETECT(p))
5558 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5559 else
5560 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5562 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5563 /* Wait for the first digit only if immediate=no */
5564 if (!p->immediate)
5565 /* Wait for the first digit (up to 5 seconds). */
5566 res = ast_waitfordigit(chan, 5000);
5567 else
5568 res = 0;
5569 if (res > 0) {
5570 /* save first char */
5571 dtmfbuf[0] = res;
5572 switch (p->sig) {
5573 case SIG_FEATD:
5574 case SIG_SF_FEATD:
5575 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5576 if (res > 0)
5577 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5578 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5579 break;
5580 case SIG_FEATDMF_TA:
5581 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5582 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5583 if (dahdi_wink(p, index)) return NULL;
5584 dtmfbuf[0] = 0;
5585 /* Wait for the first digit (up to 5 seconds). */
5586 res = ast_waitfordigit(chan, 5000);
5587 if (res <= 0) break;
5588 dtmfbuf[0] = res;
5589 /* fall through intentionally */
5590 case SIG_FEATDMF:
5591 case SIG_E911:
5592 case SIG_FGC_CAMAMF:
5593 case SIG_SF_FEATDMF:
5594 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5595 /* if international caca, do it again to get real ANO */
5596 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5598 if (dahdi_wink(p, index)) return NULL;
5599 dtmfbuf[0] = 0;
5600 /* Wait for the first digit (up to 5 seconds). */
5601 res = ast_waitfordigit(chan, 5000);
5602 if (res <= 0) break;
5603 dtmfbuf[0] = res;
5604 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5606 if (res > 0) {
5607 /* if E911, take off hook */
5608 if (p->sig == SIG_E911)
5609 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5610 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5612 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5613 break;
5614 case SIG_FEATB:
5615 case SIG_SF_FEATB:
5616 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5617 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5618 break;
5619 case SIG_EMWINK:
5620 /* if we received a '*', we are actually receiving Feature Group D
5621 dial syntax, so use that mode; otherwise, fall through to normal
5622 mode
5624 if (res == '*') {
5625 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5626 if (res > 0)
5627 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5628 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5629 break;
5631 default:
5632 /* If we got the first digit, get the rest */
5633 len = 1;
5634 dtmfbuf[len] = '\0';
5635 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5636 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5637 timeout = matchdigittimeout;
5638 } else {
5639 timeout = gendigittimeout;
5641 res = ast_waitfordigit(chan, timeout);
5642 if (res < 0) {
5643 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5644 ast_hangup(chan);
5645 return NULL;
5646 } else if (res) {
5647 dtmfbuf[len++] = res;
5648 dtmfbuf[len] = '\0';
5649 } else {
5650 break;
5653 break;
5656 if (res == -1) {
5657 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5658 ast_hangup(chan);
5659 return NULL;
5660 } else if (res < 0) {
5661 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
5662 ast_hangup(chan);
5663 return NULL;
5666 if (p->sig == SIG_FGC_CAMA) {
5667 char anibuf[100];
5669 if (ast_safe_sleep(chan,1000) == -1) {
5670 ast_hangup(chan);
5671 return NULL;
5673 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5674 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5675 res = my_getsigstr(chan, anibuf, "#", 10000);
5676 if ((res > 0) && (strlen(anibuf) > 2)) {
5677 if (anibuf[strlen(anibuf) - 1] == '#')
5678 anibuf[strlen(anibuf) - 1] = 0;
5679 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
5681 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5684 ast_copy_string(exten, dtmfbuf, sizeof(exten));
5685 if (ast_strlen_zero(exten))
5686 ast_copy_string(exten, "s", sizeof(exten));
5687 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
5688 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5689 if (exten[0] == '*') {
5690 char *stringp=NULL;
5691 ast_copy_string(exten2, exten, sizeof(exten2));
5692 /* Parse out extension and callerid */
5693 stringp=exten2 +1;
5694 s1 = strsep(&stringp, "*");
5695 s2 = strsep(&stringp, "*");
5696 if (s2) {
5697 if (!ast_strlen_zero(p->cid_num))
5698 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5699 else
5700 ast_set_callerid(chan, s1, NULL, s1);
5701 ast_copy_string(exten, s2, sizeof(exten));
5702 } else
5703 ast_copy_string(exten, s1, sizeof(exten));
5704 } else if (p->sig == SIG_FEATD)
5705 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5707 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5708 if (exten[0] == '*') {
5709 char *stringp=NULL;
5710 ast_copy_string(exten2, exten, sizeof(exten2));
5711 /* Parse out extension and callerid */
5712 stringp=exten2 +1;
5713 s1 = strsep(&stringp, "#");
5714 s2 = strsep(&stringp, "#");
5715 if (s2) {
5716 if (!ast_strlen_zero(p->cid_num))
5717 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5718 else
5719 if (*(s1 + 2))
5720 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
5721 ast_copy_string(exten, s2 + 1, sizeof(exten));
5722 } else
5723 ast_copy_string(exten, s1 + 2, sizeof(exten));
5724 } else
5725 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5727 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
5728 if (exten[0] == '*') {
5729 char *stringp=NULL;
5730 ast_copy_string(exten2, exten, sizeof(exten2));
5731 /* Parse out extension and callerid */
5732 stringp=exten2 +1;
5733 s1 = strsep(&stringp, "#");
5734 s2 = strsep(&stringp, "#");
5735 if (s2 && (*(s2 + 1) == '0')) {
5736 if (*(s2 + 2))
5737 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
5739 if (s1) ast_copy_string(exten, s1, sizeof(exten));
5740 else ast_copy_string(exten, "911", sizeof(exten));
5741 } else
5742 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
5744 if (p->sig == SIG_FEATB) {
5745 if (exten[0] == '*') {
5746 char *stringp=NULL;
5747 ast_copy_string(exten2, exten, sizeof(exten2));
5748 /* Parse out extension and callerid */
5749 stringp=exten2 +1;
5750 s1 = strsep(&stringp, "#");
5751 ast_copy_string(exten, exten2 + 1, sizeof(exten));
5752 } else
5753 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
5755 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5756 dahdi_wink(p, index);
5757 /* some switches require a minimum guard time between
5758 the last FGD wink and something that answers
5759 immediately. This ensures it */
5760 if (ast_safe_sleep(chan,100)) return NULL;
5762 dahdi_enable_ec(p);
5763 if (NEED_MFDETECT(p)) {
5764 if (p->dsp) {
5765 if (!p->hardwaredtmf)
5766 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5767 else {
5768 ast_dsp_free(p->dsp);
5769 p->dsp = NULL;
5774 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
5775 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5776 if (p->dsp) ast_dsp_digitreset(p->dsp);
5777 res = ast_pbx_run(chan);
5778 if (res) {
5779 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5780 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5782 return NULL;
5783 } else {
5784 if (option_verbose > 2)
5785 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
5786 sleep(2);
5787 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
5788 if (res < 0)
5789 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
5790 else
5791 sleep(1);
5792 res = ast_streamfile(chan, "ss-noservice", chan->language);
5793 if (res >= 0)
5794 ast_waitstream(chan, "");
5795 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5796 ast_hangup(chan);
5797 return NULL;
5799 break;
5800 case SIG_FXOLS:
5801 case SIG_FXOGS:
5802 case SIG_FXOKS:
5803 /* Read the first digit */
5804 timeout = firstdigittimeout;
5805 /* If starting a threeway call, never timeout on the first digit so someone
5806 can use flash-hook as a "hold" feature */
5807 if (p->subs[SUB_THREEWAY].owner)
5808 timeout = 999999;
5809 while (len < AST_MAX_EXTENSION-1) {
5810 /* Read digit unless it's supposed to be immediate, in which case the
5811 only answer is 's' */
5812 if (p->immediate)
5813 res = 's';
5814 else
5815 res = ast_waitfordigit(chan, timeout);
5816 timeout = 0;
5817 if (res < 0) {
5818 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5819 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5820 ast_hangup(chan);
5821 return NULL;
5822 } else if (res) {
5823 exten[len++]=res;
5824 exten[len] = '\0';
5826 if (!ast_ignore_pattern(chan->context, exten))
5827 tone_zone_play_tone(p->subs[index].dfd, -1);
5828 else
5829 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5830 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
5831 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5832 if (getforward) {
5833 /* Record this as the forwarding extension */
5834 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
5835 if (option_verbose > 2)
5836 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
5837 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5838 if (res)
5839 break;
5840 usleep(500000);
5841 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5842 sleep(1);
5843 memset(exten, 0, sizeof(exten));
5844 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5845 len = 0;
5846 getforward = 0;
5847 } else {
5848 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5849 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5850 if (!ast_strlen_zero(p->cid_num)) {
5851 if (!p->hidecallerid)
5852 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5853 else
5854 ast_set_callerid(chan, NULL, NULL, p->cid_num);
5856 if (!ast_strlen_zero(p->cid_name)) {
5857 if (!p->hidecallerid)
5858 ast_set_callerid(chan, NULL, p->cid_name, NULL);
5860 ast_setstate(chan, AST_STATE_RING);
5861 dahdi_enable_ec(p);
5862 res = ast_pbx_run(chan);
5863 if (res) {
5864 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5865 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5867 return NULL;
5869 } else {
5870 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5871 so just set the timeout to matchdigittimeout and wait some more */
5872 timeout = matchdigittimeout;
5874 } else if (res == 0) {
5875 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
5876 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5877 dahdi_wait_event(p->subs[index].dfd);
5878 ast_hangup(chan);
5879 return NULL;
5880 } else if (p->callwaiting && !strcmp(exten, "*70")) {
5881 if (option_verbose > 2)
5882 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
5883 /* Disable call waiting if enabled */
5884 p->callwaiting = 0;
5885 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5886 if (res) {
5887 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5888 chan->name, strerror(errno));
5890 len = 0;
5891 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
5892 memset(exten, 0, sizeof(exten));
5893 timeout = firstdigittimeout;
5895 } else if (!strcmp(exten,ast_pickup_ext())) {
5896 /* Scan all channels and see if there are any
5897 * ringing channels that have call groups
5898 * that equal this channels pickup group
5900 if (index == SUB_REAL) {
5901 /* Switch us from Third call to Call Wait */
5902 if (p->subs[SUB_THREEWAY].owner) {
5903 /* If you make a threeway call and the *8# a call, it should actually
5904 look like a callwait */
5905 alloc_sub(p, SUB_CALLWAIT);
5906 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
5907 unalloc_sub(p, SUB_THREEWAY);
5909 dahdi_enable_ec(p);
5910 if (ast_pickup_call(chan)) {
5911 ast_log(LOG_DEBUG, "No call pickup possible...\n");
5912 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5913 dahdi_wait_event(p->subs[index].dfd);
5915 ast_hangup(chan);
5916 return NULL;
5917 } else {
5918 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
5919 ast_hangup(chan);
5920 return NULL;
5923 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
5924 if (option_verbose > 2)
5925 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
5926 /* Disable Caller*ID if enabled */
5927 p->hidecallerid = 1;
5928 if (chan->cid.cid_num)
5929 free(chan->cid.cid_num);
5930 chan->cid.cid_num = NULL;
5931 if (chan->cid.cid_name)
5932 free(chan->cid.cid_name);
5933 chan->cid.cid_name = NULL;
5934 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5935 if (res) {
5936 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5937 chan->name, strerror(errno));
5939 len = 0;
5940 memset(exten, 0, sizeof(exten));
5941 timeout = firstdigittimeout;
5942 } else if (p->callreturn && !strcmp(exten, "*69")) {
5943 res = 0;
5944 if (!ast_strlen_zero(p->lastcid_num)) {
5945 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
5947 if (!res)
5948 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5949 break;
5950 } else if (!strcmp(exten, "*78")) {
5951 /* Do not disturb */
5952 if (option_verbose > 2)
5953 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
5954 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5955 "Channel: DAHDI/%d\r\n"
5956 "Status: enabled\r\n", p->channel);
5957 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5958 p->dnd = 1;
5959 getforward = 0;
5960 memset(exten, 0, sizeof(exten));
5961 len = 0;
5962 } else if (!strcmp(exten, "*79")) {
5963 /* Do not disturb */
5964 if (option_verbose > 2)
5965 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
5966 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5967 "Channel: DAHDI/%d\r\n"
5968 "Status: disabled\r\n", p->channel);
5969 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5970 p->dnd = 0;
5971 getforward = 0;
5972 memset(exten, 0, sizeof(exten));
5973 len = 0;
5974 } else if (p->cancallforward && !strcmp(exten, "*72")) {
5975 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5976 getforward = 1;
5977 memset(exten, 0, sizeof(exten));
5978 len = 0;
5979 } else if (p->cancallforward && !strcmp(exten, "*73")) {
5980 if (option_verbose > 2)
5981 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
5982 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5983 memset(p->call_forward, 0, sizeof(p->call_forward));
5984 getforward = 0;
5985 memset(exten, 0, sizeof(exten));
5986 len = 0;
5987 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
5988 p->subs[SUB_THREEWAY].owner &&
5989 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
5990 /* This is a three way call, the main call being a real channel,
5991 and we're parking the first call. */
5992 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
5993 if (option_verbose > 2)
5994 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
5995 break;
5996 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
5997 if (option_verbose > 2)
5998 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
5999 res = ast_db_put("blacklist", p->lastcid_num, "1");
6000 if (!res) {
6001 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6002 memset(exten, 0, sizeof(exten));
6003 len = 0;
6005 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6006 if (option_verbose > 2)
6007 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6008 /* Enable Caller*ID if enabled */
6009 p->hidecallerid = 0;
6010 if (chan->cid.cid_num)
6011 free(chan->cid.cid_num);
6012 chan->cid.cid_num = NULL;
6013 if (chan->cid.cid_name)
6014 free(chan->cid.cid_name);
6015 chan->cid.cid_name = NULL;
6016 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6017 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6018 if (res) {
6019 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6020 chan->name, strerror(errno));
6022 len = 0;
6023 memset(exten, 0, sizeof(exten));
6024 timeout = firstdigittimeout;
6025 } else if (!strcmp(exten, "*0")) {
6026 struct ast_channel *nbridge =
6027 p->subs[SUB_THREEWAY].owner;
6028 struct dahdi_pvt *pbridge = NULL;
6029 /* set up the private struct of the bridged one, if any */
6030 if (nbridge && ast_bridged_channel(nbridge))
6031 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6032 if (nbridge && pbridge &&
6033 (nbridge->tech == &dahdi_tech) &&
6034 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
6035 ISTRUNK(pbridge)) {
6036 int func = DAHDI_FLASH;
6037 /* Clear out the dial buffer */
6038 p->dop.dialstr[0] = '\0';
6039 /* flash hookswitch */
6040 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6041 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6042 nbridge->name, strerror(errno));
6044 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6045 unalloc_sub(p, SUB_THREEWAY);
6046 p->owner = p->subs[SUB_REAL].owner;
6047 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6048 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6049 ast_hangup(chan);
6050 return NULL;
6051 } else {
6052 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6053 dahdi_wait_event(p->subs[index].dfd);
6054 tone_zone_play_tone(p->subs[index].dfd, -1);
6055 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6056 unalloc_sub(p, SUB_THREEWAY);
6057 p->owner = p->subs[SUB_REAL].owner;
6058 ast_hangup(chan);
6059 return NULL;
6061 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6062 ((exten[0] != '*') || (strlen(exten) > 2))) {
6063 if (option_debug)
6064 ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
6065 break;
6067 if (!timeout)
6068 timeout = gendigittimeout;
6069 if (len && !ast_ignore_pattern(chan->context, exten))
6070 tone_zone_play_tone(p->subs[index].dfd, -1);
6072 break;
6073 case SIG_FXSLS:
6074 case SIG_FXSGS:
6075 case SIG_FXSKS:
6076 #ifdef HAVE_PRI
6077 if (p->pri) {
6078 /* This is a GR-303 trunk actually. Wait for the first ring... */
6079 struct ast_frame *f;
6080 int res;
6081 time_t start;
6083 time(&start);
6084 ast_setstate(chan, AST_STATE_RING);
6085 while (time(NULL) < start + 3) {
6086 res = ast_waitfor(chan, 1000);
6087 if (res) {
6088 f = ast_read(chan);
6089 if (!f) {
6090 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6091 ast_hangup(chan);
6092 return NULL;
6093 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6094 res = 1;
6095 } else
6096 res = 0;
6097 ast_frfree(f);
6098 if (res) {
6099 ast_log(LOG_DEBUG, "Got ring!\n");
6100 res = 0;
6101 break;
6106 #endif
6107 /* check for SMDI messages */
6108 if (p->use_smdi && p->smdi_iface) {
6109 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6111 if (smdi_msg != NULL) {
6112 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6114 if (smdi_msg->type == 'B')
6115 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6116 else if (smdi_msg->type == 'N')
6117 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6119 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6120 } else {
6121 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6125 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6126 number = smdi_msg->calling_st;
6128 /* If we want caller id, we're in a prering state due to a polarity reversal
6129 * and we're set to use a polarity reversal to trigger the start of caller id,
6130 * grab the caller id and wait for ringing to start... */
6131 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6132 /* If set to use DTMF CID signalling, listen for DTMF */
6133 if (p->cid_signalling == CID_SIG_DTMF) {
6134 int i = 0;
6135 cs = NULL;
6136 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6137 "channel %s\n", chan->name);
6138 dahdi_setlinear(p->subs[index].dfd, 0);
6139 res = 2000;
6140 for (;;) {
6141 struct ast_frame *f;
6142 res = ast_waitfor(chan, res);
6143 if (res <= 0) {
6144 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6145 "Exiting simple switch\n");
6146 ast_hangup(chan);
6147 return NULL;
6149 f = ast_read(chan);
6150 if (!f)
6151 break;
6152 if (f->frametype == AST_FRAME_DTMF) {
6153 dtmfbuf[i++] = f->subclass;
6154 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6155 res = 2000;
6157 ast_frfree(f);
6158 if (chan->_state == AST_STATE_RING ||
6159 chan->_state == AST_STATE_RINGING)
6160 break; /* Got ring */
6162 dtmfbuf[i] = '\0';
6163 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6164 /* Got cid and ring. */
6165 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6166 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6167 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6168 dtmfcid, flags);
6169 /* If first byte is NULL, we have no cid */
6170 if (!ast_strlen_zero(dtmfcid))
6171 number = dtmfcid;
6172 else
6173 number = NULL;
6174 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6175 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6176 cs = callerid_new(p->cid_signalling);
6177 if (cs) {
6178 samples = 0;
6179 #if 1
6180 bump_gains(p);
6181 #endif
6182 /* Take out of linear mode for Caller*ID processing */
6183 dahdi_setlinear(p->subs[index].dfd, 0);
6185 /* First we wait and listen for the Caller*ID */
6186 for (;;) {
6187 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6188 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6189 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6190 callerid_free(cs);
6191 ast_hangup(chan);
6192 return NULL;
6194 if (i & DAHDI_IOMUX_SIGEVENT) {
6195 res = dahdi_get_event(p->subs[index].dfd);
6196 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6198 if (p->cid_signalling == CID_SIG_V23_JP) {
6199 #ifdef DAHDI_EVENT_RINGBEGIN
6200 if (res == DAHDI_EVENT_RINGBEGIN) {
6201 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6202 usleep(1);
6204 #endif
6205 } else {
6206 res = 0;
6207 break;
6209 } else if (i & DAHDI_IOMUX_READ) {
6210 res = read(p->subs[index].dfd, buf, sizeof(buf));
6211 if (res < 0) {
6212 if (errno != ELAST) {
6213 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6214 callerid_free(cs);
6215 ast_hangup(chan);
6216 return NULL;
6218 break;
6220 samples += res;
6222 if (p->cid_signalling == CID_SIG_V23_JP) {
6223 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6224 } else {
6225 res = callerid_feed(cs, buf, res, AST_LAW(p));
6228 if (res < 0) {
6229 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6230 break;
6231 } else if (res)
6232 break;
6233 else if (samples > (8000 * 10))
6234 break;
6237 if (res == 1) {
6238 callerid_get(cs, &name, &number, &flags);
6239 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6242 if (p->cid_signalling == CID_SIG_V23_JP) {
6243 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6244 usleep(1);
6245 res = 4000;
6246 } else {
6248 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6249 res = 2000;
6252 for (;;) {
6253 struct ast_frame *f;
6254 res = ast_waitfor(chan, res);
6255 if (res <= 0) {
6256 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6257 "Exiting simple switch\n");
6258 ast_hangup(chan);
6259 return NULL;
6261 if (!(f = ast_read(chan))) {
6262 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6263 ast_hangup(chan);
6264 return NULL;
6266 ast_frfree(f);
6267 if (chan->_state == AST_STATE_RING ||
6268 chan->_state == AST_STATE_RINGING)
6269 break; /* Got ring */
6272 /* We must have a ring by now, so, if configured, lets try to listen for
6273 * distinctive ringing */
6274 if (p->usedistinctiveringdetection == 1) {
6275 len = 0;
6276 distMatches = 0;
6277 /* Clear the current ring data array so we dont have old data in it. */
6278 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6279 curRingData[receivedRingT] = 0;
6280 receivedRingT = 0;
6281 counter = 0;
6282 counter1 = 0;
6283 /* Check to see if context is what it should be, if not set to be. */
6284 if (strcmp(p->context,p->defcontext) != 0) {
6285 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6286 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6289 for (;;) {
6290 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6291 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6292 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6293 callerid_free(cs);
6294 ast_hangup(chan);
6295 return NULL;
6297 if (i & DAHDI_IOMUX_SIGEVENT) {
6298 res = dahdi_get_event(p->subs[index].dfd);
6299 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6300 res = 0;
6301 /* Let us detect distinctive ring */
6303 curRingData[receivedRingT] = p->ringt;
6305 if (p->ringt < p->ringt_base/2)
6306 break;
6307 /* Increment the ringT counter so we can match it against
6308 values in chan_dahdi.conf for distinctive ring */
6309 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6310 break;
6311 } else if (i & DAHDI_IOMUX_READ) {
6312 res = read(p->subs[index].dfd, buf, sizeof(buf));
6313 if (res < 0) {
6314 if (errno != ELAST) {
6315 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6316 callerid_free(cs);
6317 ast_hangup(chan);
6318 return NULL;
6320 break;
6322 if (p->ringt)
6323 p->ringt--;
6324 if (p->ringt == 1) {
6325 res = -1;
6326 break;
6330 if (option_verbose > 2)
6331 /* this only shows up if you have n of the dring patterns filled in */
6332 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6334 for (counter = 0; counter < 3; counter++) {
6335 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6336 channel */
6337 distMatches = 0;
6338 for (counter1 = 0; counter1 < 3; counter1++) {
6339 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6340 (p->drings.ringnum[counter].ring[counter1]-10)) {
6341 distMatches++;
6344 if (distMatches == 3) {
6345 /* The ring matches, set the context to whatever is for distinctive ring.. */
6346 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6347 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6348 if (option_verbose > 2)
6349 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6350 break;
6354 /* Restore linear mode (if appropriate) for Caller*ID processing */
6355 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6356 #if 1
6357 restore_gains(p);
6358 #endif
6359 } else
6360 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6361 } else {
6362 ast_log(LOG_WARNING, "Channel %s in prering "
6363 "state, but I have nothing to do. "
6364 "Terminating simple switch, should be "
6365 "restarted by the actual ring.\n",
6366 chan->name);
6367 ast_hangup(chan);
6368 return NULL;
6370 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6371 /* FSK Bell202 callerID */
6372 cs = callerid_new(p->cid_signalling);
6373 if (cs) {
6374 #if 1
6375 bump_gains(p);
6376 #endif
6377 samples = 0;
6378 len = 0;
6379 distMatches = 0;
6380 /* Clear the current ring data array so we dont have old data in it. */
6381 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6382 curRingData[receivedRingT] = 0;
6383 receivedRingT = 0;
6384 counter = 0;
6385 counter1 = 0;
6386 /* Check to see if context is what it should be, if not set to be. */
6387 if (strcmp(p->context,p->defcontext) != 0) {
6388 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6389 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6392 /* Take out of linear mode for Caller*ID processing */
6393 dahdi_setlinear(p->subs[index].dfd, 0);
6394 for (;;) {
6395 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6396 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6397 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6398 callerid_free(cs);
6399 ast_hangup(chan);
6400 return NULL;
6402 if (i & DAHDI_IOMUX_SIGEVENT) {
6403 res = dahdi_get_event(p->subs[index].dfd);
6404 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6405 /* If we get a PR event, they hung up while processing calerid */
6406 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6407 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6408 p->polarity = POLARITY_IDLE;
6409 callerid_free(cs);
6410 ast_hangup(chan);
6411 return NULL;
6413 res = 0;
6414 /* Let us detect callerid when the telco uses distinctive ring */
6416 curRingData[receivedRingT] = p->ringt;
6418 if (p->ringt < p->ringt_base/2)
6419 break;
6420 /* Increment the ringT counter so we can match it against
6421 values in chan_dahdi.conf for distinctive ring */
6422 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6423 break;
6424 } else if (i & DAHDI_IOMUX_READ) {
6425 res = read(p->subs[index].dfd, buf, sizeof(buf));
6426 if (res < 0) {
6427 if (errno != ELAST) {
6428 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6429 callerid_free(cs);
6430 ast_hangup(chan);
6431 return NULL;
6433 break;
6435 if (p->ringt)
6436 p->ringt--;
6437 if (p->ringt == 1) {
6438 res = -1;
6439 break;
6441 samples += res;
6442 res = callerid_feed(cs, buf, res, AST_LAW(p));
6443 if (res < 0) {
6444 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6445 break;
6446 } else if (res)
6447 break;
6448 else if (samples > (8000 * 10))
6449 break;
6452 if (res == 1) {
6453 callerid_get(cs, &name, &number, &flags);
6454 if (option_debug)
6455 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6457 if (distinctiveringaftercid == 1) {
6458 /* Clear the current ring data array so we dont have old data in it. */
6459 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6460 curRingData[receivedRingT] = 0;
6462 receivedRingT = 0;
6463 if (option_verbose > 2)
6464 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6465 for (;;) {
6466 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6467 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6468 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6469 callerid_free(cs);
6470 ast_hangup(chan);
6471 return NULL;
6473 if (i & DAHDI_IOMUX_SIGEVENT) {
6474 res = dahdi_get_event(p->subs[index].dfd);
6475 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6476 res = 0;
6477 /* Let us detect callerid when the telco uses distinctive ring */
6479 curRingData[receivedRingT] = p->ringt;
6481 if (p->ringt < p->ringt_base/2)
6482 break;
6483 /* Increment the ringT counter so we can match it against
6484 values in chan_dahdi.conf for distinctive ring */
6485 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6486 break;
6487 } else if (i & DAHDI_IOMUX_READ) {
6488 res = read(p->subs[index].dfd, buf, sizeof(buf));
6489 if (res < 0) {
6490 if (errno != ELAST) {
6491 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6492 callerid_free(cs);
6493 ast_hangup(chan);
6494 return NULL;
6496 break;
6498 if (p->ringt)
6499 p->ringt--;
6500 if (p->ringt == 1) {
6501 res = -1;
6502 break;
6507 if (p->usedistinctiveringdetection == 1) {
6508 if (option_verbose > 2)
6509 /* this only shows up if you have n of the dring patterns filled in */
6510 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6512 for (counter = 0; counter < 3; counter++) {
6513 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6514 channel */
6515 if (option_verbose > 2)
6516 /* this only shows up if you have n of the dring patterns filled in */
6517 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6518 p->drings.ringnum[counter].ring[0],
6519 p->drings.ringnum[counter].ring[1],
6520 p->drings.ringnum[counter].ring[2]);
6521 distMatches = 0;
6522 for (counter1 = 0; counter1 < 3; counter1++) {
6523 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6524 (p->drings.ringnum[counter].ring[counter1]-10)) {
6525 distMatches++;
6528 if (distMatches == 3) {
6529 /* The ring matches, set the context to whatever is for distinctive ring.. */
6530 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6531 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6532 if (option_verbose > 2)
6533 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6534 break;
6538 /* Restore linear mode (if appropriate) for Caller*ID processing */
6539 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6540 #if 1
6541 restore_gains(p);
6542 #endif
6543 if (res < 0) {
6544 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6546 } else
6547 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6549 else
6550 cs = NULL;
6552 if (number)
6553 ast_shrink_phone_number(number);
6554 ast_set_callerid(chan, number, name, number);
6556 if (smdi_msg)
6557 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6559 if (cs)
6560 callerid_free(cs);
6562 ast_setstate(chan, AST_STATE_RING);
6563 chan->rings = 1;
6564 p->ringt = p->ringt_base;
6565 res = ast_pbx_run(chan);
6566 if (res) {
6567 ast_hangup(chan);
6568 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6570 return NULL;
6571 default:
6572 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6573 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6574 if (res < 0)
6575 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6577 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6578 if (res < 0)
6579 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6580 ast_hangup(chan);
6581 return NULL;
6584 /* destroy a DAHDI channel, identified by its number */
6585 static int dahdi_destroy_channel_bynum(int channel)
6587 struct dahdi_pvt *tmp = NULL;
6588 struct dahdi_pvt *prev = NULL;
6590 tmp = iflist;
6591 while (tmp) {
6592 if (tmp->channel == channel) {
6593 destroy_channel(prev, tmp, 1);
6594 return RESULT_SUCCESS;
6596 prev = tmp;
6597 tmp = tmp->next;
6599 return RESULT_FAILURE;
6602 static int handle_init_event(struct dahdi_pvt *i, int event)
6604 int res;
6605 pthread_t threadid;
6606 pthread_attr_t attr;
6607 struct ast_channel *chan;
6608 pthread_attr_init(&attr);
6609 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6610 /* Handle an event on a given channel for the monitor thread. */
6611 switch (event) {
6612 case DAHDI_EVENT_NONE:
6613 case DAHDI_EVENT_BITSCHANGED:
6614 break;
6615 case DAHDI_EVENT_WINKFLASH:
6616 case DAHDI_EVENT_RINGOFFHOOK:
6617 if (i->inalarm) break;
6618 if (i->radio) break;
6619 /* Got a ring/answer. What kind of channel are we? */
6620 switch (i->sig) {
6621 case SIG_FXOLS:
6622 case SIG_FXOGS:
6623 case SIG_FXOKS:
6624 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6625 if (res && (errno == EBUSY))
6626 break;
6627 if (i->cidspill) {
6628 /* Cancel VMWI spill */
6629 free(i->cidspill);
6630 i->cidspill = NULL;
6632 if (i->immediate) {
6633 dahdi_enable_ec(i);
6634 /* The channel is immediately up. Start right away */
6635 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6636 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6637 if (!chan) {
6638 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6639 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6640 if (res < 0)
6641 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6643 } else {
6644 /* Check for callerid, digits, etc */
6645 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6646 if (chan) {
6647 if (has_voicemail(i))
6648 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6649 else
6650 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6651 if (res < 0)
6652 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
6653 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6654 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6655 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6656 if (res < 0)
6657 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6658 ast_hangup(chan);
6660 } else
6661 ast_log(LOG_WARNING, "Unable to create channel\n");
6663 break;
6664 case SIG_FXSLS:
6665 case SIG_FXSGS:
6666 case SIG_FXSKS:
6667 i->ringt = i->ringt_base;
6668 /* Fall through */
6669 case SIG_EMWINK:
6670 case SIG_FEATD:
6671 case SIG_FEATDMF:
6672 case SIG_FEATDMF_TA:
6673 case SIG_E911:
6674 case SIG_FGC_CAMA:
6675 case SIG_FGC_CAMAMF:
6676 case SIG_FEATB:
6677 case SIG_EM:
6678 case SIG_EM_E1:
6679 case SIG_SFWINK:
6680 case SIG_SF_FEATD:
6681 case SIG_SF_FEATDMF:
6682 case SIG_SF_FEATB:
6683 case SIG_SF:
6684 /* Check for callerid, digits, etc */
6685 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
6686 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6687 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6688 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6689 if (res < 0)
6690 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6691 ast_hangup(chan);
6692 } else if (!chan) {
6693 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
6695 break;
6696 default:
6697 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6698 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6699 if (res < 0)
6700 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6701 return -1;
6703 break;
6704 case DAHDI_EVENT_NOALARM:
6705 i->inalarm = 0;
6706 if (!i->unknown_alarm) {
6707 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
6708 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6709 "Channel: %d\r\n", i->channel);
6710 } else {
6711 i->unknown_alarm = 0;
6713 break;
6714 case DAHDI_EVENT_ALARM:
6715 i->inalarm = 1;
6716 res = get_alarms(i);
6717 do {
6718 const char *alarm_str = alarm2str(res);
6720 /* hack alert! DAHDI 1.4 now exposes FXO battery as an alarm, but asterisk 1.4
6721 * doesn't know what to do with it. Don't confuse users with log messages. */
6722 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
6723 i->unknown_alarm = 1;
6724 break;
6725 } else {
6726 i->unknown_alarm = 0;
6729 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm_str);
6730 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
6731 "Alarm: %s\r\n"
6732 "Channel: %d\r\n",
6733 alarm_str, i->channel);
6734 } while (0);
6735 /* fall thru intentionally */
6736 case DAHDI_EVENT_ONHOOK:
6737 if (i->radio)
6738 break;
6739 /* Back on hook. Hang up. */
6740 switch (i->sig) {
6741 case SIG_FXOLS:
6742 case SIG_FXOGS:
6743 case SIG_FEATD:
6744 case SIG_FEATDMF:
6745 case SIG_FEATDMF_TA:
6746 case SIG_E911:
6747 case SIG_FGC_CAMA:
6748 case SIG_FGC_CAMAMF:
6749 case SIG_FEATB:
6750 case SIG_EM:
6751 case SIG_EM_E1:
6752 case SIG_EMWINK:
6753 case SIG_SF_FEATD:
6754 case SIG_SF_FEATDMF:
6755 case SIG_SF_FEATB:
6756 case SIG_SF:
6757 case SIG_SFWINK:
6758 case SIG_FXSLS:
6759 case SIG_FXSGS:
6760 case SIG_FXSKS:
6761 case SIG_GR303FXSKS:
6762 dahdi_disable_ec(i);
6763 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6764 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6765 break;
6766 case SIG_GR303FXOKS:
6767 case SIG_FXOKS:
6768 dahdi_disable_ec(i);
6769 /* Diddle the battery for the zhone */
6770 #ifdef ZHONE_HACK
6771 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6772 usleep(1);
6773 #endif
6774 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6775 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6776 break;
6777 case SIG_PRI:
6778 dahdi_disable_ec(i);
6779 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6780 break;
6781 default:
6782 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6783 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6784 return -1;
6786 break;
6787 case DAHDI_EVENT_POLARITY:
6788 switch (i->sig) {
6789 case SIG_FXSLS:
6790 case SIG_FXSKS:
6791 case SIG_FXSGS:
6792 /* We have already got a PR before the channel was
6793 created, but it wasn't handled. We need polarity
6794 to be REV for remote hangup detection to work.
6795 At least in Spain */
6796 if (i->hanguponpolarityswitch)
6797 i->polarity = POLARITY_REV;
6799 if (i->cid_start == CID_START_POLARITY) {
6800 i->polarity = POLARITY_REV;
6801 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
6802 "CID detection on channel %d\n",
6803 i->channel);
6804 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
6805 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6806 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6809 break;
6810 default:
6811 ast_log(LOG_WARNING, "handle_init_event detected "
6812 "polarity reversal on non-FXO (SIG_FXS) "
6813 "interface %d\n", i->channel);
6815 break;
6816 case DAHDI_EVENT_REMOVED: /* destroy channel */
6817 ast_log(LOG_NOTICE,
6818 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6819 i->channel);
6820 dahdi_destroy_channel_bynum(i->channel);
6821 break;
6823 pthread_attr_destroy(&attr);
6824 return 0;
6827 static void *do_monitor(void *data)
6829 int count, res, res2, spoint, pollres=0;
6830 struct dahdi_pvt *i;
6831 struct dahdi_pvt *last = NULL;
6832 time_t thispass = 0, lastpass = 0;
6833 int found;
6834 char buf[1024];
6835 struct pollfd *pfds=NULL;
6836 int lastalloc = -1;
6837 /* This thread monitors all the frame relay interfaces which are not yet in use
6838 (and thus do not have a separate thread) indefinitely */
6839 /* From here on out, we die whenever asked */
6840 #if 0
6841 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
6842 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
6843 return NULL;
6845 ast_log(LOG_DEBUG, "Monitor starting...\n");
6846 #endif
6847 for (;;) {
6848 /* Lock the interface list */
6849 ast_mutex_lock(&iflock);
6850 if (!pfds || (lastalloc != ifcount)) {
6851 if (pfds) {
6852 free(pfds);
6853 pfds = NULL;
6855 if (ifcount) {
6856 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
6857 ast_mutex_unlock(&iflock);
6858 return NULL;
6861 lastalloc = ifcount;
6863 /* Build the stuff we're going to poll on, that is the socket of every
6864 dahdi_pvt that does not have an associated owner channel */
6865 count = 0;
6866 i = iflist;
6867 while (i) {
6868 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
6869 if (!i->owner && !i->subs[SUB_REAL].owner) {
6870 /* This needs to be watched, as it lacks an owner */
6871 pfds[count].fd = i->subs[SUB_REAL].dfd;
6872 pfds[count].events = POLLPRI;
6873 pfds[count].revents = 0;
6874 /* Message waiting or r2 channels also get watched for reading */
6875 if (i->cidspill)
6876 pfds[count].events |= POLLIN;
6877 count++;
6880 i = i->next;
6882 /* Okay, now that we know what to do, release the interface lock */
6883 ast_mutex_unlock(&iflock);
6885 pthread_testcancel();
6886 /* Wait at least a second for something to happen */
6887 res = poll(pfds, count, 1000);
6888 pthread_testcancel();
6889 /* Okay, poll has finished. Let's see what happened. */
6890 if (res < 0) {
6891 if ((errno != EAGAIN) && (errno != EINTR))
6892 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
6893 continue;
6895 /* Alright, lock the interface list again, and let's look and see what has
6896 happened */
6897 ast_mutex_lock(&iflock);
6898 found = 0;
6899 spoint = 0;
6900 lastpass = thispass;
6901 thispass = time(NULL);
6902 i = iflist;
6903 while (i) {
6904 if (thispass != lastpass) {
6905 if (!found && ((i == last) || ((i == iflist) && !last))) {
6906 last = i;
6907 if (last) {
6908 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
6909 (last->sig & __DAHDI_SIG_FXO)) {
6910 res = ast_app_has_voicemail(last->mailbox, NULL);
6911 if (last->msgstate != res) {
6912 int x;
6913 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
6914 x = DAHDI_FLUSH_BOTH;
6915 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
6916 if (res2)
6917 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
6918 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
6919 /* Turn on on hook transfer for 4 seconds */
6920 x = 4000;
6921 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
6922 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
6923 last->cidpos = 0;
6924 last->msgstate = res;
6925 last->onhooktime = thispass;
6927 found ++;
6930 last = last->next;
6934 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
6935 if (i->radio && !i->owner)
6937 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
6938 if (res)
6940 if (option_debug)
6941 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
6942 /* Don't hold iflock while handling init events */
6943 ast_mutex_unlock(&iflock);
6944 handle_init_event(i, res);
6945 ast_mutex_lock(&iflock);
6947 i = i->next;
6948 continue;
6950 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
6951 if (pollres & POLLIN) {
6952 if (i->owner || i->subs[SUB_REAL].owner) {
6953 #ifdef HAVE_PRI
6954 if (!i->pri)
6955 #endif
6956 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
6957 i = i->next;
6958 continue;
6960 if (!i->cidspill) {
6961 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
6962 i = i->next;
6963 continue;
6965 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
6966 if (res > 0) {
6967 /* We read some number of bytes. Write an equal amount of data */
6968 if (res > i->cidlen - i->cidpos)
6969 res = i->cidlen - i->cidpos;
6970 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
6971 if (res2 > 0) {
6972 i->cidpos += res2;
6973 if (i->cidpos >= i->cidlen) {
6974 free(i->cidspill);
6975 i->cidspill = 0;
6976 i->cidpos = 0;
6977 i->cidlen = 0;
6979 } else {
6980 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
6981 i->msgstate = -1;
6983 } else {
6984 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
6987 if (pollres & POLLPRI) {
6988 if (i->owner || i->subs[SUB_REAL].owner) {
6989 #ifdef HAVE_PRI
6990 if (!i->pri)
6991 #endif
6992 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
6993 i = i->next;
6994 continue;
6996 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
6997 if (option_debug)
6998 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
6999 /* Don't hold iflock while handling init events */
7000 ast_mutex_unlock(&iflock);
7001 handle_init_event(i, res);
7002 ast_mutex_lock(&iflock);
7005 i=i->next;
7007 ast_mutex_unlock(&iflock);
7009 /* Never reached */
7010 return NULL;
7014 static int restart_monitor(void)
7016 pthread_attr_t attr;
7017 pthread_attr_init(&attr);
7018 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7019 /* If we're supposed to be stopped -- stay stopped */
7020 if (monitor_thread == AST_PTHREADT_STOP)
7021 return 0;
7022 ast_mutex_lock(&monlock);
7023 if (monitor_thread == pthread_self()) {
7024 ast_mutex_unlock(&monlock);
7025 ast_log(LOG_WARNING, "Cannot kill myself\n");
7026 return -1;
7028 if (monitor_thread != AST_PTHREADT_NULL) {
7029 /* Wake up the thread */
7030 pthread_kill(monitor_thread, SIGURG);
7031 } else {
7032 /* Start a new monitor */
7033 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7034 ast_mutex_unlock(&monlock);
7035 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7036 pthread_attr_destroy(&attr);
7037 return -1;
7040 ast_mutex_unlock(&monlock);
7041 pthread_attr_destroy(&attr);
7042 return 0;
7045 #ifdef HAVE_PRI
7046 static int pri_resolve_span(int *span, int channel, int offset, DAHDI_SPANINFO *si)
7048 int x;
7049 int trunkgroup;
7050 /* Get appropriate trunk group if there is one */
7051 trunkgroup = pris[*span].mastertrunkgroup;
7052 if (trunkgroup) {
7053 /* Select a specific trunk group */
7054 for (x = 0; x < NUM_SPANS; x++) {
7055 if (pris[x].trunkgroup == trunkgroup) {
7056 *span = x;
7057 return 0;
7060 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7061 *span = -1;
7062 } else {
7063 if (pris[*span].trunkgroup) {
7064 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7065 *span = -1;
7066 } else if (pris[*span].mastertrunkgroup) {
7067 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7068 *span = -1;
7069 } else {
7070 if (si->totalchans == 31) { /* if it's an E1 */
7071 pris[*span].dchannels[0] = 16 + offset;
7072 } else {
7073 pris[*span].dchannels[0] = 24 + offset;
7075 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7076 pris[*span].offset = offset;
7077 pris[*span].span = *span + 1;
7080 return 0;
7083 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7085 DAHDI_SPANINFO si;
7086 DAHDI_PARAMS p;
7087 int fd;
7088 int span;
7089 int ospan=0;
7090 int x,y;
7091 for (x = 0; x < NUM_SPANS; x++) {
7092 if (pris[x].trunkgroup == trunkgroup) {
7093 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7094 return -1;
7097 for (y = 0; y < NUM_DCHANS; y++) {
7098 if (!channels[y])
7099 break;
7100 memset(&si, 0, sizeof(si));
7101 memset(&p, 0, sizeof(p));
7102 #ifdef HAVE_ZAPTEL
7103 fd = open("/dev/zap/channel", O_RDWR);
7104 #else
7105 fd = open("/dev/dahdi/channel", O_RDWR);
7106 #endif
7107 if (fd < 0) {
7108 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7109 return -1;
7111 x = channels[y];
7112 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7113 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7114 dahdi_close(fd);
7115 return -1;
7117 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7118 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7119 return -1;
7121 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7122 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7123 dahdi_close(fd);
7124 return -1;
7126 span = p.spanno - 1;
7127 if (pris[span].trunkgroup) {
7128 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7129 dahdi_close(fd);
7130 return -1;
7132 if (pris[span].pvts[0]) {
7133 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7134 dahdi_close(fd);
7135 return -1;
7137 if (!y) {
7138 pris[span].trunkgroup = trunkgroup;
7139 pris[span].offset = channels[y] - p.chanpos;
7140 ospan = span;
7142 pris[ospan].dchannels[y] = channels[y];
7143 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7144 pris[span].span = span + 1;
7145 dahdi_close(fd);
7147 return 0;
7150 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7152 if (pris[span].mastertrunkgroup) {
7153 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);
7154 return -1;
7156 pris[span].mastertrunkgroup = trunkgroup;
7157 pris[span].prilogicalspan = logicalspan;
7158 return 0;
7161 #endif
7163 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7165 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7166 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7167 char fn[80];
7168 #if 1
7169 DAHDI_BUFFERINFO bi;
7170 #endif
7171 DAHDI_SPANINFO si;
7172 int res;
7173 int span=0;
7174 int here = 0;
7175 int x;
7176 struct dahdi_pvt **wlist;
7177 struct dahdi_pvt **wend;
7178 DAHDI_PARAMS p;
7180 wlist = &iflist;
7181 wend = &ifend;
7183 #ifdef HAVE_PRI
7184 if (pri) {
7185 wlist = &pri->crvs;
7186 wend = &pri->crvend;
7188 #endif
7190 tmp2 = *wlist;
7191 prev = NULL;
7193 while (tmp2) {
7194 if (!tmp2->destroy) {
7195 if (tmp2->channel == channel) {
7196 tmp = tmp2;
7197 here = 1;
7198 break;
7200 if (tmp2->channel > channel) {
7201 break;
7204 prev = tmp2;
7205 tmp2 = tmp2->next;
7208 if (!here && !reloading) {
7209 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7210 destroy_dahdi_pvt(&tmp);
7211 return NULL;
7213 ast_mutex_init(&tmp->lock);
7214 ifcount++;
7215 for (x = 0; x < 3; x++)
7216 tmp->subs[x].dfd = -1;
7217 tmp->channel = channel;
7220 if (tmp) {
7221 int chan_sig = conf->chan.sig;
7222 if (!here) {
7223 if ((channel != CHAN_PSEUDO) && !pri) {
7224 snprintf(fn, sizeof(fn), "%d", channel);
7225 /* Open non-blocking */
7226 if (!here)
7227 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7228 /* Allocate a DAHDI structure */
7229 if (tmp->subs[SUB_REAL].dfd < 0) {
7230 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);
7231 destroy_dahdi_pvt(&tmp);
7232 return NULL;
7234 memset(&p, 0, sizeof(p));
7235 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7236 if (res < 0) {
7237 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7238 destroy_dahdi_pvt(&tmp);
7239 return NULL;
7241 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7242 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));
7243 destroy_dahdi_pvt(&tmp);
7244 return NULL;
7246 tmp->law = p.curlaw;
7247 tmp->span = p.spanno;
7248 span = p.spanno - 1;
7249 } else {
7250 if (channel == CHAN_PSEUDO)
7251 chan_sig = 0;
7252 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7253 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7254 return NULL;
7257 #ifdef HAVE_PRI
7258 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7259 int offset;
7260 int myswitchtype;
7261 int matchesdchan;
7262 int x,y;
7263 offset = 0;
7264 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7265 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7266 destroy_dahdi_pvt(&tmp);
7267 return NULL;
7269 if (span >= NUM_SPANS) {
7270 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7271 destroy_dahdi_pvt(&tmp);
7272 return NULL;
7273 } else {
7274 si.spanno = 0;
7275 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7276 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7277 destroy_dahdi_pvt(&tmp);
7278 return NULL;
7280 /* Store the logical span first based upon the real span */
7281 tmp->logicalspan = pris[span].prilogicalspan;
7282 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7283 if (span < 0) {
7284 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7285 destroy_dahdi_pvt(&tmp);
7286 return NULL;
7288 if (chan_sig == SIG_PRI)
7289 myswitchtype = conf->pri.switchtype;
7290 else
7291 myswitchtype = PRI_SWITCH_GR303_TMC;
7292 /* Make sure this isn't a d-channel */
7293 matchesdchan=0;
7294 for (x = 0; x < NUM_SPANS; x++) {
7295 for (y = 0; y < NUM_DCHANS; y++) {
7296 if (pris[x].dchannels[y] == tmp->channel) {
7297 matchesdchan = 1;
7298 break;
7302 offset = p.chanpos;
7303 if (!matchesdchan) {
7304 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7305 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7306 destroy_dahdi_pvt(&tmp);
7307 return NULL;
7309 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7310 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7311 destroy_dahdi_pvt(&tmp);
7312 return NULL;
7314 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7315 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7316 destroy_dahdi_pvt(&tmp);
7317 return NULL;
7319 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7320 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7321 destroy_dahdi_pvt(&tmp);
7322 return NULL;
7324 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7325 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7326 destroy_dahdi_pvt(&tmp);
7327 return NULL;
7329 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7330 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7331 destroy_dahdi_pvt(&tmp);
7332 return NULL;
7334 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7335 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7336 destroy_dahdi_pvt(&tmp);
7337 return NULL;
7339 if (pris[span].numchans >= MAX_CHANNELS) {
7340 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7341 pris[span].trunkgroup);
7342 destroy_dahdi_pvt(&tmp);
7343 return NULL;
7345 pris[span].nodetype = conf->pri.nodetype;
7346 pris[span].switchtype = myswitchtype;
7347 pris[span].nsf = conf->pri.nsf;
7348 pris[span].dialplan = conf->pri.dialplan;
7349 pris[span].localdialplan = conf->pri.localdialplan;
7350 pris[span].pvts[pris[span].numchans++] = tmp;
7351 pris[span].minunused = conf->pri.minunused;
7352 pris[span].minidle = conf->pri.minidle;
7353 pris[span].overlapdial = conf->pri.overlapdial;
7354 #ifdef HAVE_PRI_INBANDRELEASE
7355 pris[span].inbandrelease = conf->pri.inbandrelease;
7356 #endif
7357 pris[span].facilityenable = conf->pri.facilityenable;
7358 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7359 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7360 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7361 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7362 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7363 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7364 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7365 pris[span].resetinterval = conf->pri.resetinterval;
7367 tmp->pri = &pris[span];
7368 tmp->prioffset = offset;
7369 tmp->call = NULL;
7370 } else {
7371 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7372 destroy_dahdi_pvt(&tmp);
7373 return NULL;
7376 } else {
7377 tmp->prioffset = 0;
7379 #endif
7380 } else {
7381 chan_sig = tmp->sig;
7382 memset(&p, 0, sizeof(p));
7383 if (tmp->subs[SUB_REAL].dfd > -1)
7384 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7386 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7387 switch (chan_sig) {
7388 case SIG_FXSKS:
7389 case SIG_FXSLS:
7390 case SIG_EM:
7391 case SIG_EM_E1:
7392 case SIG_EMWINK:
7393 case SIG_FEATD:
7394 case SIG_FEATDMF:
7395 case SIG_FEATDMF_TA:
7396 case SIG_FEATB:
7397 case SIG_E911:
7398 case SIG_SF:
7399 case SIG_SFWINK:
7400 case SIG_FGC_CAMA:
7401 case SIG_FGC_CAMAMF:
7402 case SIG_SF_FEATD:
7403 case SIG_SF_FEATDMF:
7404 case SIG_SF_FEATB:
7405 p.starttime = 250;
7406 break;
7409 if (tmp->radio) {
7410 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7411 p.channo = channel;
7412 p.rxwinktime = 1;
7413 p.rxflashtime = 1;
7414 p.starttime = 1;
7415 p.debouncetime = 5;
7417 if (!tmp->radio) {
7418 p.channo = channel;
7419 /* Override timing settings based on config file */
7420 if (conf->timing.prewinktime >= 0)
7421 p.prewinktime = conf->timing.prewinktime;
7422 if (conf->timing.preflashtime >= 0)
7423 p.preflashtime = conf->timing.preflashtime;
7424 if (conf->timing.winktime >= 0)
7425 p.winktime = conf->timing.winktime;
7426 if (conf->timing.flashtime >= 0)
7427 p.flashtime = conf->timing.flashtime;
7428 if (conf->timing.starttime >= 0)
7429 p.starttime = conf->timing.starttime;
7430 if (conf->timing.rxwinktime >= 0)
7431 p.rxwinktime = conf->timing.rxwinktime;
7432 if (conf->timing.rxflashtime >= 0)
7433 p.rxflashtime = conf->timing.rxflashtime;
7434 if (conf->timing.debouncetime >= 0)
7435 p.debouncetime = conf->timing.debouncetime;
7438 /* dont set parms on a pseudo-channel (or CRV) */
7439 if (tmp->subs[SUB_REAL].dfd >= 0)
7441 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7442 if (res < 0) {
7443 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7444 destroy_dahdi_pvt(&tmp);
7445 return NULL;
7448 #if 1
7449 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7450 memset(&bi, 0, sizeof(bi));
7451 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7452 if (!res) {
7453 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7454 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7455 bi.numbufs = numbufs;
7456 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7457 if (res < 0) {
7458 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7460 } else
7461 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7463 #endif
7464 tmp->immediate = conf->chan.immediate;
7465 tmp->transfertobusy = conf->chan.transfertobusy;
7466 tmp->sig = chan_sig;
7467 tmp->outsigmod = conf->chan.outsigmod;
7468 tmp->ringt_base = ringt_base;
7469 tmp->firstradio = 0;
7470 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7471 tmp->permcallwaiting = conf->chan.callwaiting;
7472 else
7473 tmp->permcallwaiting = 0;
7474 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7475 tmp->destroy = 0;
7476 tmp->drings = drings;
7477 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7478 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7479 tmp->threewaycalling = conf->chan.threewaycalling;
7480 tmp->adsi = conf->chan.adsi;
7481 tmp->use_smdi = conf->chan.use_smdi;
7482 tmp->permhidecallerid = conf->chan.hidecallerid;
7483 tmp->callreturn = conf->chan.callreturn;
7484 tmp->echocancel = conf->chan.echocancel;
7485 tmp->echotraining = conf->chan.echotraining;
7486 tmp->pulse = conf->chan.pulse;
7487 if (tmp->echocancel)
7488 tmp->echocanbridged = conf->chan.echocanbridged;
7489 else {
7490 if (conf->chan.echocanbridged)
7491 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7492 tmp->echocanbridged = 0;
7494 tmp->busydetect = conf->chan.busydetect;
7495 tmp->busycount = conf->chan.busycount;
7496 tmp->busy_tonelength = conf->chan.busy_tonelength;
7497 tmp->busy_quietlength = conf->chan.busy_quietlength;
7498 tmp->callprogress = conf->chan.callprogress;
7499 tmp->cancallforward = conf->chan.cancallforward;
7500 tmp->dtmfrelax = conf->chan.dtmfrelax;
7501 tmp->callwaiting = tmp->permcallwaiting;
7502 tmp->hidecallerid = tmp->permhidecallerid;
7503 tmp->channel = channel;
7504 tmp->stripmsd = conf->chan.stripmsd;
7505 tmp->use_callerid = conf->chan.use_callerid;
7506 tmp->cid_signalling = conf->chan.cid_signalling;
7507 tmp->cid_start = conf->chan.cid_start;
7508 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7509 tmp->restrictcid = conf->chan.restrictcid;
7510 tmp->use_callingpres = conf->chan.use_callingpres;
7511 tmp->priindication_oob = conf->chan.priindication_oob;
7512 tmp->priexclusive = conf->chan.priexclusive;
7513 if (tmp->usedistinctiveringdetection) {
7514 if (!tmp->use_callerid) {
7515 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7516 tmp->use_callerid = 1;
7520 if (tmp->cid_signalling == CID_SIG_SMDI) {
7521 if (!tmp->use_smdi) {
7522 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7523 tmp->use_smdi = 1;
7526 if (tmp->use_smdi) {
7527 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7528 if (!(tmp->smdi_iface)) {
7529 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7530 tmp->use_smdi = 0;
7534 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7535 tmp->amaflags = conf->chan.amaflags;
7536 if (!here) {
7537 tmp->confno = -1;
7538 tmp->propconfno = -1;
7540 tmp->canpark = conf->chan.canpark;
7541 tmp->transfer = conf->chan.transfer;
7542 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7543 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7544 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7545 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7546 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7547 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7548 tmp->cid_ton = 0;
7549 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7550 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7551 tmp->msgstate = -1;
7552 tmp->group = conf->chan.group;
7553 tmp->callgroup = conf->chan.callgroup;
7554 tmp->pickupgroup= conf->chan.pickupgroup;
7555 tmp->rxgain = conf->chan.rxgain;
7556 tmp->txgain = conf->chan.txgain;
7557 tmp->tonezone = conf->chan.tonezone;
7558 tmp->onhooktime = time(NULL);
7559 if (tmp->subs[SUB_REAL].dfd > -1) {
7560 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7561 if (tmp->dsp)
7562 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7563 update_conf(tmp);
7564 if (!here) {
7565 if (chan_sig != SIG_PRI)
7566 /* Hang it up to be sure it's good */
7567 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7569 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7570 #ifdef HAVE_PRI
7571 /* the dchannel is down so put the channel in alarm */
7572 if (tmp->pri && !pri_is_up(tmp->pri))
7573 tmp->inalarm = 1;
7574 else
7575 tmp->inalarm = 0;
7576 #endif
7577 memset(&si, 0, sizeof(si));
7578 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7579 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7580 destroy_dahdi_pvt(&tmp);
7581 return NULL;
7583 if (si.alarms) tmp->inalarm = 1;
7586 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
7587 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
7588 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
7589 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
7592 if (tmp && !here) {
7593 /* nothing on the iflist */
7594 if (!*wlist) {
7595 *wlist = tmp;
7596 tmp->prev = NULL;
7597 tmp->next = NULL;
7598 *wend = tmp;
7599 } else {
7600 /* at least one member on the iflist */
7601 struct dahdi_pvt *working = *wlist;
7603 /* check if we maybe have to put it on the begining */
7604 if (working->channel > tmp->channel) {
7605 tmp->next = *wlist;
7606 tmp->prev = NULL;
7607 (*wlist)->prev = tmp;
7608 *wlist = tmp;
7609 } else {
7610 /* go through all the members and put the member in the right place */
7611 while (working) {
7612 /* in the middle */
7613 if (working->next) {
7614 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
7615 tmp->next = working->next;
7616 tmp->prev = working;
7617 working->next->prev = tmp;
7618 working->next = tmp;
7619 break;
7621 } else {
7622 /* the last */
7623 if (working->channel < tmp->channel) {
7624 working->next = tmp;
7625 tmp->next = NULL;
7626 tmp->prev = working;
7627 *wend = tmp;
7628 break;
7631 working = working->next;
7636 return tmp;
7639 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
7641 int res;
7642 DAHDI_PARAMS par;
7644 /* First, check group matching */
7645 if (groupmatch) {
7646 if ((p->group & groupmatch) != groupmatch)
7647 return 0;
7648 *groupmatched = 1;
7650 /* Check to see if we have a channel match */
7651 if (channelmatch != -1) {
7652 if (p->channel != channelmatch)
7653 return 0;
7654 *channelmatched = 1;
7656 /* We're at least busy at this point */
7657 if (busy) {
7658 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
7659 *busy = 1;
7661 /* If do not disturb, definitely not */
7662 if (p->dnd)
7663 return 0;
7664 /* If guard time, definitely not */
7665 if (p->guardtime && (time(NULL) < p->guardtime))
7666 return 0;
7668 /* If no owner definitely available */
7669 if (!p->owner) {
7670 #ifdef HAVE_PRI
7671 /* Trust PRI */
7672 if (p->pri) {
7673 if (p->resetting || p->call)
7674 return 0;
7675 else
7676 return 1;
7678 #endif
7679 if (!(p->radio || (p->oprmode < 0)))
7681 if (!p->sig || (p->sig == SIG_FXSLS))
7682 return 1;
7683 /* Check hook state */
7684 if (p->subs[SUB_REAL].dfd > -1)
7685 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
7686 else {
7687 /* Assume not off hook on CVRS */
7688 res = 0;
7689 par.rxisoffhook = 0;
7691 if (res) {
7692 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
7693 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
7694 /* When "onhook" that means no battery on the line, and thus
7695 it is out of service..., if it's on a TDM card... If it's a channel
7696 bank, there is no telling... */
7697 if (par.rxbits > -1)
7698 return 1;
7699 if (par.rxisoffhook)
7700 return 1;
7701 else
7702 #ifdef DAHDI_CHECK_HOOKSTATE
7703 return 0;
7704 #else
7705 return 1;
7706 #endif
7707 } else if (par.rxisoffhook) {
7708 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
7709 /* Not available when the other end is off hook */
7710 return 0;
7713 return 1;
7716 /* If it's not an FXO, forget about call wait */
7717 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
7718 return 0;
7720 if (!p->callwaiting) {
7721 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7722 return 0;
7725 if (p->subs[SUB_CALLWAIT].dfd > -1) {
7726 /* If there is already a call waiting call, then we can't take a second one */
7727 return 0;
7730 if ((p->owner->_state != AST_STATE_UP) &&
7731 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
7732 /* If the current call is not up, then don't allow the call */
7733 return 0;
7735 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
7736 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7737 return 0;
7739 /* We're cool */
7740 return 1;
7743 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
7745 struct dahdi_pvt *p;
7746 DAHDI_BUFFERINFO bi;
7747 int res;
7749 if ((p = ast_malloc(sizeof(*p)))) {
7750 memcpy(p, src, sizeof(struct dahdi_pvt));
7751 ast_mutex_init(&p->lock);
7752 #ifdef HAVE_ZAPTEL
7753 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
7754 #else
7755 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
7756 #endif
7757 /* Allocate a DAHDI structure */
7758 if (p->subs[SUB_REAL].dfd < 0) {
7759 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
7760 destroy_dahdi_pvt(&p);
7761 return NULL;
7763 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7764 if (!res) {
7765 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7766 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7767 bi.numbufs = numbufs;
7768 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7769 if (res < 0) {
7770 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
7772 } else
7773 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
7775 p->destroy = 1;
7776 p->next = iflist;
7777 p->prev = NULL;
7778 iflist = p;
7779 if (iflist->next)
7780 iflist->next->prev = p;
7781 return p;
7785 #ifdef HAVE_PRI
7786 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
7788 int x;
7789 if (backwards)
7790 x = pri->numchans;
7791 else
7792 x = 0;
7793 for (;;) {
7794 if (backwards && (x < 0))
7795 break;
7796 if (!backwards && (x >= pri->numchans))
7797 break;
7798 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7799 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7800 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7801 return x;
7803 if (backwards)
7804 x--;
7805 else
7806 x++;
7808 return -1;
7810 #endif
7812 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
7814 ast_group_t groupmatch = 0;
7815 int channelmatch = -1;
7816 int roundrobin = 0;
7817 int callwait = 0;
7818 int busy = 0;
7819 struct dahdi_pvt *p;
7820 struct ast_channel *tmp = NULL;
7821 char *dest=NULL;
7822 int x;
7823 char *s;
7824 char opt=0;
7825 int res=0, y=0;
7826 int backwards = 0;
7827 #ifdef HAVE_PRI
7828 int crv;
7829 int bearer = -1;
7830 int trunkgroup;
7831 struct dahdi_pri *pri=NULL;
7832 #endif
7833 struct dahdi_pvt *exit, *start, *end;
7834 ast_mutex_t *lock;
7835 int channelmatched = 0;
7836 int groupmatched = 0;
7838 /* Assume we're locking the iflock */
7839 lock = &iflock;
7840 start = iflist;
7841 end = ifend;
7842 if (data) {
7843 dest = ast_strdupa((char *)data);
7844 } else {
7845 ast_log(LOG_WARNING, "Channel requested with no data\n");
7846 return NULL;
7848 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
7849 /* Retrieve the group number */
7850 char *stringp=NULL;
7851 stringp=dest + 1;
7852 s = strsep(&stringp, "/");
7853 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7854 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
7855 return NULL;
7857 groupmatch = ((ast_group_t) 1 << x);
7858 if (toupper(dest[0]) == 'G') {
7859 if (dest[0] == 'G') {
7860 backwards = 1;
7861 p = ifend;
7862 } else
7863 p = iflist;
7864 } else {
7865 if (dest[0] == 'R') {
7866 backwards = 1;
7867 p = round_robin[x]?round_robin[x]->prev:ifend;
7868 if (!p)
7869 p = ifend;
7870 } else {
7871 p = round_robin[x]?round_robin[x]->next:iflist;
7872 if (!p)
7873 p = iflist;
7875 roundrobin = 1;
7877 } else {
7878 char *stringp=NULL;
7879 stringp=dest;
7880 s = strsep(&stringp, "/");
7881 p = iflist;
7882 if (!strcasecmp(s, "pseudo")) {
7883 /* Special case for pseudo */
7884 x = CHAN_PSEUDO;
7885 channelmatch = x;
7887 #ifdef HAVE_PRI
7888 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
7889 if ((trunkgroup < 1) || (crv < 1)) {
7890 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
7891 return NULL;
7893 res--;
7894 for (x = 0; x < NUM_SPANS; x++) {
7895 if (pris[x].trunkgroup == trunkgroup) {
7896 pri = pris + x;
7897 lock = &pri->lock;
7898 start = pri->crvs;
7899 end = pri->crvend;
7900 break;
7903 if (!pri) {
7904 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
7905 return NULL;
7907 channelmatch = crv;
7908 p = pris[x].crvs;
7910 #endif
7911 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7912 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
7913 return NULL;
7914 } else {
7915 channelmatch = x;
7918 /* Search for an unowned channel */
7919 ast_mutex_lock(lock);
7920 exit = p;
7921 while (p && !tmp) {
7922 if (roundrobin)
7923 round_robin[x] = p;
7924 #if 0
7925 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
7926 #endif
7928 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
7929 if (option_debug)
7930 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
7931 if (p->inalarm)
7932 goto next;
7934 callwait = (p->owner != NULL);
7935 #ifdef HAVE_PRI
7936 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
7937 if (p->sig != SIG_FXSKS) {
7938 /* Gotta find an actual channel to use for this
7939 CRV if this isn't a callwait */
7940 bearer = pri_find_empty_chan(pri, 0);
7941 if (bearer < 0) {
7942 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
7943 p = NULL;
7944 break;
7946 pri_assign_bearer(p, pri, pri->pvts[bearer]);
7947 } else {
7948 if (alloc_sub(p, 0)) {
7949 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
7950 p = NULL;
7951 break;
7952 } else
7953 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
7954 p->pri = pri;
7957 #endif
7958 if (p->channel == CHAN_PSEUDO) {
7959 p = chandup(p);
7960 if (!p) {
7961 break;
7964 if (p->owner) {
7965 if (alloc_sub(p, SUB_CALLWAIT)) {
7966 p = NULL;
7967 break;
7970 p->outgoing = 1;
7971 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
7972 #ifdef HAVE_PRI
7973 if (p->bearer) {
7974 /* Log owner to bearer channel, too */
7975 p->bearer->owner = tmp;
7977 #endif
7978 /* Make special notes */
7979 if (res > 1) {
7980 if (opt == 'c') {
7981 /* Confirm answer */
7982 p->confirmanswer = 1;
7983 } else if (opt == 'r') {
7984 /* Distinctive ring */
7985 if (res < 3)
7986 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
7987 else
7988 p->distinctivering = y;
7989 } else if (opt == 'd') {
7990 /* If this is an ISDN call, make it digital */
7991 p->digital = 1;
7992 if (tmp)
7993 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
7994 } else {
7995 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
7998 /* Note if the call is a call waiting call */
7999 if (tmp && callwait)
8000 tmp->cdrflags |= AST_CDR_CALLWAIT;
8001 break;
8003 next:
8004 if (backwards) {
8005 p = p->prev;
8006 if (!p)
8007 p = end;
8008 } else {
8009 p = p->next;
8010 if (!p)
8011 p = start;
8013 /* stop when you roll to the one that we started from */
8014 if (p == exit)
8015 break;
8017 ast_mutex_unlock(lock);
8018 restart_monitor();
8019 if (callwait)
8020 *cause = AST_CAUSE_BUSY;
8021 else if (!tmp) {
8022 if (channelmatched) {
8023 if (busy)
8024 *cause = AST_CAUSE_BUSY;
8025 } else if (groupmatched) {
8026 *cause = AST_CAUSE_CONGESTION;
8030 return tmp;
8034 #ifdef HAVE_PRI
8035 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8037 struct dahdi_pvt *p;
8038 p = pri->crvs;
8039 while (p) {
8040 if (p->channel == crv)
8041 return p;
8042 p = p->next;
8044 return NULL;
8048 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8050 int x;
8051 int span = PRI_SPAN(channel);
8052 int spanfd;
8053 DAHDI_PARAMS param;
8054 int principle = -1;
8055 int explicit = PRI_EXPLICIT(channel);
8056 channel = PRI_CHANNEL(channel);
8058 if (!explicit) {
8059 spanfd = pri_active_dchan_fd(pri);
8060 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8061 return -1;
8062 span = pris[param.spanno - 1].prilogicalspan;
8065 for (x = 0; x < pri->numchans; x++) {
8066 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8067 principle = x;
8068 break;
8072 return principle;
8075 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8077 int x;
8078 struct dahdi_pvt *crv;
8079 if (!c) {
8080 if (principle < 0)
8081 return -1;
8082 return principle;
8084 if ((principle > -1) &&
8085 (principle < pri->numchans) &&
8086 (pri->pvts[principle]) &&
8087 (pri->pvts[principle]->call == c))
8088 return principle;
8089 /* First, check for other bearers */
8090 for (x = 0; x < pri->numchans; x++) {
8091 if (!pri->pvts[x])
8092 continue;
8093 if (pri->pvts[x]->call == c) {
8094 /* Found our call */
8095 if (principle != x) {
8096 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8098 if (option_verbose > 2)
8099 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8100 old->channel, new->channel);
8101 if (new->owner) {
8102 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8103 old->channel, new->channel, new->channel);
8104 return -1;
8106 /* Fix it all up now */
8107 new->owner = old->owner;
8108 old->owner = NULL;
8109 if (new->owner) {
8110 ast_string_field_build(new->owner, name,
8111 "DAHDI/%d:%d-%d", pri->trunkgroup,
8112 new->channel, 1);
8113 new->owner->tech_pvt = new;
8114 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8115 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8116 old->subs[SUB_REAL].owner = NULL;
8117 } else
8118 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);
8119 new->call = old->call;
8120 old->call = NULL;
8122 /* Copy any DSP that may be present */
8123 new->dsp = old->dsp;
8124 new->dsp_features = old->dsp_features;
8125 old->dsp = NULL;
8126 old->dsp_features = 0;
8128 return principle;
8131 /* Now check for a CRV with no bearer */
8132 crv = pri->crvs;
8133 while (crv) {
8134 if (crv->call == c) {
8135 /* This is our match... Perform some basic checks */
8136 if (crv->bearer)
8137 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8138 else if (pri->pvts[principle]->owner)
8139 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8140 else {
8141 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8142 wakeup the potential sleeper */
8143 dahdi_close(crv->subs[SUB_REAL].dfd);
8144 pri->pvts[principle]->call = crv->call;
8145 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8146 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8147 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8148 pri->trunkgroup, crv->channel);
8149 wakeup_sub(crv, SUB_REAL, pri);
8151 return principle;
8153 crv = crv->next;
8155 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8156 return -1;
8159 static void *do_idle_thread(void *vchan)
8161 struct ast_channel *chan = vchan;
8162 struct dahdi_pvt *pvt = chan->tech_pvt;
8163 struct ast_frame *f;
8164 char ex[80];
8165 /* Wait up to 30 seconds for an answer */
8166 int newms, ms = 30000;
8167 if (option_verbose > 2)
8168 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8169 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8170 if (ast_call(chan, ex, 0)) {
8171 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8172 ast_hangup(chan);
8173 return NULL;
8175 while ((newms = ast_waitfor(chan, ms)) > 0) {
8176 f = ast_read(chan);
8177 if (!f) {
8178 /* Got hangup */
8179 break;
8181 if (f->frametype == AST_FRAME_CONTROL) {
8182 switch (f->subclass) {
8183 case AST_CONTROL_ANSWER:
8184 /* Launch the PBX */
8185 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8186 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8187 chan->priority = 1;
8188 if (option_verbose > 3)
8189 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8190 ast_pbx_run(chan);
8191 /* It's already hungup, return immediately */
8192 return NULL;
8193 case AST_CONTROL_BUSY:
8194 if (option_verbose > 3)
8195 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8196 break;
8197 case AST_CONTROL_CONGESTION:
8198 if (option_verbose > 3)
8199 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8200 break;
8203 ast_frfree(f);
8204 ms = newms;
8206 /* Hangup the channel since nothing happend */
8207 ast_hangup(chan);
8208 return NULL;
8211 #ifndef PRI_RESTART
8212 #error "Upgrade your libpri"
8213 #endif
8214 static void dahdi_pri_message(struct pri *pri, char *s)
8216 int x, y;
8217 int dchan = -1, span = -1;
8218 int dchancount = 0;
8220 if (pri) {
8221 for (x = 0; x < NUM_SPANS; x++) {
8222 for (y = 0; y < NUM_DCHANS; y++) {
8223 if (pris[x].dchans[y])
8224 dchancount++;
8226 if (pris[x].dchans[y] == pri)
8227 dchan = y;
8229 if (dchan >= 0) {
8230 span = x;
8231 break;
8233 dchancount = 0;
8235 if ((dchan >= 0) && (span >= 0)) {
8236 if (dchancount > 1)
8237 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
8238 else
8239 ast_verbose("%s", s);
8240 } else
8241 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8242 } else
8243 ast_verbose("%s", s);
8245 ast_mutex_lock(&pridebugfdlock);
8247 if (pridebugfd >= 0)
8248 write(pridebugfd, s, strlen(s));
8250 ast_mutex_unlock(&pridebugfdlock);
8253 static void dahdi_pri_error(struct pri *pri, char *s)
8255 int x, y;
8256 int dchan = -1, span = -1;
8257 int dchancount = 0;
8259 if (pri) {
8260 for (x = 0; x < NUM_SPANS; x++) {
8261 for (y = 0; y < NUM_DCHANS; y++) {
8262 if (pris[x].dchans[y])
8263 dchancount++;
8265 if (pris[x].dchans[y] == pri)
8266 dchan = y;
8268 if (dchan >= 0) {
8269 span = x;
8270 break;
8272 dchancount = 0;
8274 if ((dchan >= 0) && (span >= 0)) {
8275 if (dchancount > 1)
8276 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8277 else
8278 ast_log(LOG_ERROR, "%s", s);
8279 } else
8280 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8281 } else
8282 ast_log(LOG_ERROR, "%s", s);
8284 ast_mutex_lock(&pridebugfdlock);
8286 if (pridebugfd >= 0)
8287 write(pridebugfd, s, strlen(s));
8289 ast_mutex_unlock(&pridebugfdlock);
8292 static int pri_check_restart(struct dahdi_pri *pri)
8294 do {
8295 pri->resetpos++;
8296 } while ((pri->resetpos < pri->numchans) &&
8297 (!pri->pvts[pri->resetpos] ||
8298 pri->pvts[pri->resetpos]->call ||
8299 pri->pvts[pri->resetpos]->resetting));
8300 if (pri->resetpos < pri->numchans) {
8301 /* Mark the channel as resetting and restart it */
8302 pri->pvts[pri->resetpos]->resetting = 1;
8303 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8304 } else {
8305 pri->resetting = 0;
8306 time(&pri->lastreset);
8308 return 0;
8311 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
8313 int x;
8314 int redo;
8315 ast_mutex_unlock(&pri->lock);
8316 ast_mutex_lock(&p->lock);
8317 do {
8318 redo = 0;
8319 for (x = 0; x < 3; x++) {
8320 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
8321 redo++;
8322 DEADLOCK_AVOIDANCE(&p->lock);
8324 if (p->subs[x].owner) {
8325 ast_queue_hangup(p->subs[x].owner);
8326 ast_mutex_unlock(&p->subs[x].owner->lock);
8329 } while (redo);
8330 ast_mutex_unlock(&p->lock);
8331 ast_mutex_lock(&pri->lock);
8332 return 0;
8335 static char * redirectingreason2str(int redirectingreason)
8337 switch (redirectingreason) {
8338 case 0:
8339 return "UNKNOWN";
8340 case 1:
8341 return "BUSY";
8342 case 2:
8343 return "NO_REPLY";
8344 case 0xF:
8345 return "UNCONDITIONAL";
8346 default:
8347 return "NOREDIRECT";
8351 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
8353 switch (plan) {
8354 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8355 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
8356 break;
8357 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8358 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
8359 break;
8360 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8361 snprintf(buf, size, "%s%s", pri->localprefix, number);
8362 break;
8363 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8364 snprintf(buf, size, "%s%s", pri->privateprefix, number);
8365 break;
8366 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8367 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
8368 break;
8369 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8370 snprintf(buf, size, "%s", number);
8371 break;
8375 static int dahdi_setlaw(int dfd, int law)
8377 int res;
8378 res = ioctl(dfd, DAHDI_SETLAW, &law);
8379 if (res)
8380 return res;
8381 return 0;
8384 static void *pri_dchannel(void *vpri)
8386 struct dahdi_pri *pri = vpri;
8387 pri_event *e;
8388 struct pollfd fds[NUM_DCHANS];
8389 int res;
8390 int chanpos = 0;
8391 int x;
8392 int haveidles;
8393 int activeidles;
8394 int nextidle = -1;
8395 struct ast_channel *c;
8396 struct timeval tv, lowest, *next;
8397 struct timeval lastidle = { 0, 0 };
8398 int doidling=0;
8399 char *cc;
8400 char idlen[80];
8401 struct ast_channel *idle;
8402 pthread_t p;
8403 time_t t;
8404 int i, which=-1;
8405 int numdchans;
8406 int cause=0;
8407 struct dahdi_pvt *crv;
8408 pthread_t threadid;
8409 pthread_attr_t attr;
8410 char ani2str[6];
8411 char plancallingnum[256];
8412 char plancallingani[256];
8413 char calledtonstr[10];
8415 gettimeofday(&lastidle, NULL);
8416 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
8417 /* Need to do idle dialing, check to be sure though */
8418 cc = strchr(pri->idleext, '@');
8419 if (cc) {
8420 *cc = '\0';
8421 cc++;
8422 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
8423 #if 0
8424 /* Extensions may not be loaded yet */
8425 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
8426 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
8427 else
8428 #endif
8429 doidling = 1;
8430 } else
8431 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
8433 for (;;) {
8434 for (i = 0; i < NUM_DCHANS; i++) {
8435 if (!pri->dchannels[i])
8436 break;
8437 fds[i].fd = pri->fds[i];
8438 fds[i].events = POLLIN | POLLPRI;
8439 fds[i].revents = 0;
8441 numdchans = i;
8442 time(&t);
8443 ast_mutex_lock(&pri->lock);
8444 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
8445 if (pri->resetting && pri_is_up(pri)) {
8446 if (pri->resetpos < 0)
8447 pri_check_restart(pri);
8448 } else {
8449 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
8450 pri->resetting = 1;
8451 pri->resetpos = -1;
8455 /* Look for any idle channels if appropriate */
8456 if (doidling && pri_is_up(pri)) {
8457 nextidle = -1;
8458 haveidles = 0;
8459 activeidles = 0;
8460 for (x = pri->numchans; x >= 0; x--) {
8461 if (pri->pvts[x] && !pri->pvts[x]->owner &&
8462 !pri->pvts[x]->call) {
8463 if (haveidles < pri->minunused) {
8464 haveidles++;
8465 } else if (!pri->pvts[x]->resetting) {
8466 nextidle = x;
8467 break;
8469 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
8470 activeidles++;
8472 if (nextidle > -1) {
8473 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
8474 /* Don't create a new idle call more than once per second */
8475 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
8476 idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
8477 if (idle) {
8478 pri->pvts[nextidle]->isidlecall = 1;
8479 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
8480 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
8481 dahdi_hangup(idle);
8483 } else
8484 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
8485 gettimeofday(&lastidle, NULL);
8487 } else if ((haveidles < pri->minunused) &&
8488 (activeidles > pri->minidle)) {
8489 /* Mark something for hangup if there is something
8490 that can be hungup */
8491 for (x = pri->numchans; x >= 0; x--) {
8492 /* find a candidate channel */
8493 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
8494 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8495 haveidles++;
8496 /* Stop if we have enough idle channels or
8497 can't spare any more active idle ones */
8498 if ((haveidles >= pri->minunused) ||
8499 (activeidles <= pri->minidle))
8500 break;
8505 /* Start with reasonable max */
8506 lowest = ast_tv(60, 0);
8507 for (i = 0; i < NUM_DCHANS; i++) {
8508 /* Find lowest available d-channel */
8509 if (!pri->dchannels[i])
8510 break;
8511 if ((next = pri_schedule_next(pri->dchans[i]))) {
8512 /* We need relative time here */
8513 tv = ast_tvsub(*next, ast_tvnow());
8514 if (tv.tv_sec < 0) {
8515 tv = ast_tv(0,0);
8517 if (doidling || pri->resetting) {
8518 if (tv.tv_sec > 1) {
8519 tv = ast_tv(1, 0);
8521 } else {
8522 if (tv.tv_sec > 60) {
8523 tv = ast_tv(60, 0);
8526 } else if (doidling || pri->resetting) {
8527 /* Make sure we stop at least once per second if we're
8528 monitoring idle channels */
8529 tv = ast_tv(1,0);
8530 } else {
8531 /* Don't poll for more than 60 seconds */
8532 tv = ast_tv(60, 0);
8534 if (!i || ast_tvcmp(tv, lowest) < 0) {
8535 lowest = tv;
8538 ast_mutex_unlock(&pri->lock);
8540 e = NULL;
8541 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
8543 ast_mutex_lock(&pri->lock);
8544 if (!res) {
8545 for (which = 0; which < NUM_DCHANS; which++) {
8546 if (!pri->dchans[which])
8547 break;
8548 /* Just a timeout, run the scheduler */
8549 e = pri_schedule_run(pri->dchans[which]);
8550 if (e)
8551 break;
8553 } else if (res > -1) {
8554 for (which = 0; which < NUM_DCHANS; which++) {
8555 if (!pri->dchans[which])
8556 break;
8557 if (fds[which].revents & POLLPRI) {
8558 /* Check for an event */
8559 x = 0;
8560 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
8561 if (x)
8562 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);
8563 /* Keep track of alarm state */
8564 if (x == DAHDI_EVENT_ALARM) {
8565 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8566 pri_find_dchan(pri);
8567 } else if (x == DAHDI_EVENT_NOALARM) {
8568 pri->dchanavail[which] |= DCHAN_NOTINALARM;
8569 pri_restart(pri->dchans[which]);
8572 if (option_debug)
8573 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
8574 } else if (fds[which].revents & POLLIN) {
8575 e = pri_check_event(pri->dchans[which]);
8577 if (e)
8578 break;
8580 } else if (errno != EINTR)
8581 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8583 if (e) {
8584 if (pri->debug)
8585 pri_dump_event(pri->dchans[which], e);
8587 if (e->e != PRI_EVENT_DCHAN_DOWN) {
8588 if (!(pri->dchanavail[which] & DCHAN_UP)) {
8589 if (option_verbose > 1)
8590 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8592 pri->dchanavail[which] |= DCHAN_UP;
8593 } else {
8594 if (pri->dchanavail[which] & DCHAN_UP) {
8595 if (option_verbose > 1)
8596 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8598 pri->dchanavail[which] &= ~DCHAN_UP;
8601 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
8602 /* Must be an NFAS group that has the secondary dchan active */
8603 pri->pri = pri->dchans[which];
8605 switch (e->e) {
8606 case PRI_EVENT_DCHAN_UP:
8607 if (!pri->pri) pri_find_dchan(pri);
8609 /* Note presense of D-channel */
8610 time(&pri->lastreset);
8612 /* Restart in 5 seconds */
8613 if (pri->resetinterval > -1) {
8614 pri->lastreset -= pri->resetinterval;
8615 pri->lastreset += 5;
8617 pri->resetting = 0;
8618 /* Take the channels from inalarm condition */
8619 for (i = 0; i < pri->numchans; i++)
8620 if (pri->pvts[i]) {
8621 pri->pvts[i]->inalarm = 0;
8623 break;
8624 case PRI_EVENT_DCHAN_DOWN:
8625 pri_find_dchan(pri);
8626 if (!pri_is_up(pri)) {
8627 pri->resetting = 0;
8628 /* Hangup active channels and put them in alarm mode */
8629 for (i = 0; i < pri->numchans; i++) {
8630 struct dahdi_pvt *p = pri->pvts[i];
8631 if (p) {
8632 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8633 /* T309 is not enabled : hangup calls when alarm occurs */
8634 if (p->call) {
8635 if (p->pri && p->pri->pri) {
8636 pri_hangup(p->pri->pri, p->call, -1);
8637 pri_destroycall(p->pri->pri, p->call);
8638 p->call = NULL;
8639 } else
8640 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8642 if (p->realcall) {
8643 pri_hangup_all(p->realcall, pri);
8644 } else if (p->owner)
8645 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8647 p->inalarm = 1;
8651 break;
8652 case PRI_EVENT_RESTART:
8653 if (e->restart.channel > -1) {
8654 chanpos = pri_find_principle(pri, e->restart.channel);
8655 if (chanpos < 0)
8656 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8657 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8658 else {
8659 if (option_verbose > 2)
8660 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
8661 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8662 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8663 if (pri->pvts[chanpos]->call) {
8664 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
8665 pri->pvts[chanpos]->call = NULL;
8667 /* Force soft hangup if appropriate */
8668 if (pri->pvts[chanpos]->realcall)
8669 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8670 else if (pri->pvts[chanpos]->owner)
8671 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8672 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8674 } else {
8675 if (option_verbose > 2)
8676 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
8677 for (x = 0; x < pri->numchans; x++)
8678 if (pri->pvts[x]) {
8679 ast_mutex_lock(&pri->pvts[x]->lock);
8680 if (pri->pvts[x]->call) {
8681 pri_destroycall(pri->pri, pri->pvts[x]->call);
8682 pri->pvts[x]->call = NULL;
8684 if (pri->pvts[chanpos]->realcall)
8685 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8686 else if (pri->pvts[x]->owner)
8687 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8688 ast_mutex_unlock(&pri->pvts[x]->lock);
8691 break;
8692 case PRI_EVENT_KEYPAD_DIGIT:
8693 chanpos = pri_find_principle(pri, e->digit.channel);
8694 if (chanpos < 0) {
8695 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8696 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
8697 } else {
8698 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
8699 if (chanpos > -1) {
8700 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8701 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8702 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
8703 /* how to do that */
8704 int digitlen = strlen(e->digit.digits);
8705 char digit;
8706 int i;
8707 for (i = 0; i < digitlen; i++) {
8708 digit = e->digit.digits[i];
8710 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8711 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8715 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8718 break;
8720 case PRI_EVENT_INFO_RECEIVED:
8721 chanpos = pri_find_principle(pri, e->ring.channel);
8722 if (chanpos < 0) {
8723 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
8724 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8725 } else {
8726 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8727 if (chanpos > -1) {
8728 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8729 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8730 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8731 /* how to do that */
8732 int digitlen = strlen(e->ring.callednum);
8733 char digit;
8734 int i;
8735 for (i = 0; i < digitlen; i++) {
8736 digit = e->ring.callednum[i];
8738 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8739 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8743 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8746 break;
8747 case PRI_EVENT_RING:
8748 crv = NULL;
8749 if (e->ring.channel == -1)
8750 chanpos = pri_find_empty_chan(pri, 1);
8751 else
8752 chanpos = pri_find_principle(pri, e->ring.channel);
8753 /* if no channel specified find one empty */
8754 if (chanpos < 0) {
8755 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8756 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8757 } else {
8758 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8759 if (pri->pvts[chanpos]->owner) {
8760 if (pri->pvts[chanpos]->call == e->ring.call) {
8761 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8762 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8763 break;
8764 } else {
8765 /* This is where we handle initial glare */
8766 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8767 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8768 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8769 chanpos = -1;
8772 if (chanpos > -1)
8773 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8775 if ((chanpos < 0) && (e->ring.flexible))
8776 chanpos = pri_find_empty_chan(pri, 1);
8777 if (chanpos > -1) {
8778 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8779 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8780 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8781 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8782 if (crv)
8783 ast_mutex_lock(&crv->lock);
8784 if (!crv || crv->owner) {
8785 pri->pvts[chanpos]->call = NULL;
8786 if (crv) {
8787 if (crv->owner)
8788 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8789 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);
8790 } else
8791 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);
8792 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8793 if (crv)
8794 ast_mutex_unlock(&crv->lock);
8795 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8796 break;
8799 pri->pvts[chanpos]->call = e->ring.call;
8800 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8801 if (pri->pvts[chanpos]->use_callerid) {
8802 ast_shrink_phone_number(plancallingnum);
8803 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
8804 #ifdef PRI_ANI
8805 if (!ast_strlen_zero(e->ring.callingani)) {
8806 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
8807 ast_shrink_phone_number(plancallingani);
8808 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
8809 } else {
8810 pri->pvts[chanpos]->cid_ani[0] = '\0';
8812 #endif
8813 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
8814 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8815 } else {
8816 pri->pvts[chanpos]->cid_num[0] = '\0';
8817 pri->pvts[chanpos]->cid_ani[0] = '\0';
8818 pri->pvts[chanpos]->cid_name[0] = '\0';
8819 pri->pvts[chanpos]->cid_ton = 0;
8821 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8822 e->ring.redirectingnum, e->ring.callingplanrdnis);
8823 /* If immediate=yes go to s|1 */
8824 if (pri->pvts[chanpos]->immediate) {
8825 if (option_verbose > 2)
8826 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8827 pri->pvts[chanpos]->exten[0] = 's';
8828 pri->pvts[chanpos]->exten[1] = '\0';
8830 /* Get called number */
8831 else if (!ast_strlen_zero(e->ring.callednum)) {
8832 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8833 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8834 } else if (pri->overlapdial)
8835 pri->pvts[chanpos]->exten[0] = '\0';
8836 else {
8837 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8838 pri->pvts[chanpos]->exten[0] = 's';
8839 pri->pvts[chanpos]->exten[1] = '\0';
8841 /* Set DNID on all incoming calls -- even immediate */
8842 if (!ast_strlen_zero(e->ring.callednum))
8843 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8844 /* No number yet, but received "sending complete"? */
8845 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8846 if (option_verbose > 2)
8847 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8848 pri->pvts[chanpos]->exten[0] = 's';
8849 pri->pvts[chanpos]->exten[1] = '\0';
8851 /* Make sure extension exists (or in overlap dial mode, can exist) */
8852 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8853 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8854 /* Setup law */
8855 int law;
8856 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
8857 /* Set to audio mode at this point */
8858 law = 1;
8859 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
8860 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
8862 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
8863 law = DAHDI_LAW_ALAW;
8864 else
8865 law = DAHDI_LAW_MULAW;
8866 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
8867 if (res < 0)
8868 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
8869 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8870 if (res < 0)
8871 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
8872 if (e->ring.complete || !pri->overlapdial) {
8873 /* Just announce proceeding */
8874 pri->pvts[chanpos]->proceeding = 1;
8875 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8876 } else {
8877 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
8878 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8879 else
8880 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8882 /* Get the use_callingpres state */
8883 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
8885 /* Start PBX */
8886 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8887 /* Release the PRI lock while we create the channel */
8888 ast_mutex_unlock(&pri->lock);
8889 if (crv) {
8890 /* Set bearer and such */
8891 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
8892 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8893 pri->pvts[chanpos]->owner = &inuse;
8894 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
8895 } else {
8896 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8899 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8901 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
8902 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8904 if (e->ring.ani2 >= 0) {
8905 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
8906 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8909 #ifdef SUPPORT_USERUSER
8910 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8911 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8913 #endif
8915 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8916 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8917 if (e->ring.redirectingreason >= 0)
8918 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8920 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8921 ast_mutex_lock(&pri->lock);
8923 pthread_attr_init(&attr);
8924 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
8925 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
8926 if (option_verbose > 2)
8927 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8928 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
8929 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8930 } else {
8931 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8932 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8933 if (c)
8934 ast_hangup(c);
8935 else {
8936 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8937 pri->pvts[chanpos]->call = NULL;
8940 pthread_attr_destroy(&attr);
8941 } else {
8942 ast_mutex_unlock(&pri->lock);
8943 /* Release PRI lock while we create the channel */
8944 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
8945 if (c) {
8946 char calledtonstr[10];
8948 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8950 if (e->ring.ani2 >= 0) {
8951 snprintf(ani2str, 5, "%d", e->ring.ani2);
8952 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8955 #ifdef SUPPORT_USERUSER
8956 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8957 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8959 #endif
8961 if (e->ring.redirectingreason >= 0)
8962 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8964 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8965 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8967 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8968 ast_mutex_lock(&pri->lock);
8970 if (option_verbose > 2)
8971 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8972 plancallingnum, pri->pvts[chanpos]->exten,
8973 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8974 dahdi_enable_ec(pri->pvts[chanpos]);
8975 } else {
8977 ast_mutex_lock(&pri->lock);
8979 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8980 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8981 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8982 pri->pvts[chanpos]->call = NULL;
8985 } else {
8986 if (option_verbose > 2)
8987 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
8988 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
8989 pri->pvts[chanpos]->prioffset, pri->span);
8990 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
8991 pri->pvts[chanpos]->call = NULL;
8992 pri->pvts[chanpos]->exten[0] = '\0';
8994 if (crv)
8995 ast_mutex_unlock(&crv->lock);
8996 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8997 } else {
8998 if (e->ring.flexible)
8999 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
9000 else
9001 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
9003 break;
9004 case PRI_EVENT_RINGING:
9005 chanpos = pri_find_principle(pri, e->ringing.channel);
9006 if (chanpos < 0) {
9007 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9008 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9009 } else {
9010 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9011 if (chanpos < 0) {
9012 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9013 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9014 } else {
9015 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9016 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9017 dahdi_enable_ec(pri->pvts[chanpos]);
9018 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9019 pri->pvts[chanpos]->alerting = 1;
9020 } else
9021 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9022 #ifdef PRI_PROGRESS_MASK
9023 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9024 #else
9025 if (e->ringing.progress == 8) {
9026 #endif
9027 /* Now we can do call progress detection */
9028 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9029 /* RINGING detection isn't required because we got ALERTING signal */
9030 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9031 pri->pvts[chanpos]->dsp_features = 0;
9035 #ifdef SUPPORT_USERUSER
9036 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9037 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9038 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9039 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9040 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9042 #endif
9044 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9047 break;
9048 case PRI_EVENT_PROGRESS:
9049 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9050 chanpos = pri_find_principle(pri, e->proceeding.channel);
9051 if (chanpos > -1) {
9052 #ifdef PRI_PROGRESS_MASK
9053 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9054 #else
9055 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9056 #endif
9057 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9059 if (e->proceeding.cause > -1) {
9060 if (option_verbose > 2)
9061 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9063 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9064 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9065 if (pri->pvts[chanpos]->owner) {
9066 if (option_verbose > 2)
9067 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9069 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9070 f.subclass = AST_CONTROL_BUSY;
9075 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9076 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9077 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9078 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9079 #ifdef PRI_PROGRESS_MASK
9080 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9081 #else
9082 if (e->proceeding.progress == 8) {
9083 #endif
9084 /* Now we can do call progress detection */
9085 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9086 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9087 pri->pvts[chanpos]->dsp_features = 0;
9090 pri->pvts[chanpos]->progress = 1;
9091 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9094 break;
9095 case PRI_EVENT_PROCEEDING:
9096 chanpos = pri_find_principle(pri, e->proceeding.channel);
9097 if (chanpos > -1) {
9098 if (!pri->pvts[chanpos]->proceeding) {
9099 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9101 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9102 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9103 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9104 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9105 #ifdef PRI_PROGRESS_MASK
9106 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9107 #else
9108 if (e->proceeding.progress == 8) {
9109 #endif
9110 /* Now we can do call progress detection */
9111 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9112 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9113 pri->pvts[chanpos]->dsp_features = 0;
9115 /* Bring voice path up */
9116 f.subclass = AST_CONTROL_PROGRESS;
9117 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9119 pri->pvts[chanpos]->proceeding = 1;
9120 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9123 break;
9124 case PRI_EVENT_FACNAME:
9125 chanpos = pri_find_principle(pri, e->facname.channel);
9126 if (chanpos < 0) {
9127 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9128 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9129 } else {
9130 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
9131 if (chanpos < 0) {
9132 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
9133 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9134 } else {
9135 /* Re-use *69 field for PRI */
9136 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9137 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
9138 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
9139 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
9140 dahdi_enable_ec(pri->pvts[chanpos]);
9141 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9144 break;
9145 case PRI_EVENT_ANSWER:
9146 chanpos = pri_find_principle(pri, e->answer.channel);
9147 if (chanpos < 0) {
9148 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
9149 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9150 } else {
9151 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
9152 if (chanpos < 0) {
9153 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
9154 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9155 } else {
9156 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9157 /* Now we can do call progress detection */
9159 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9160 * By this time, we need DTMF detection and other features that were previously disabled
9161 * -- Matt F */
9162 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9163 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9164 pri->pvts[chanpos]->dsp_features = 0;
9166 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
9167 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
9168 x = DAHDI_START;
9169 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
9170 if (res < 0) {
9171 if (errno != EINPROGRESS) {
9172 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
9175 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9176 pri->pvts[chanpos]->dialing = 1;
9177 /* Send any "w" waited stuff */
9178 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
9179 if (res < 0) {
9180 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
9181 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9182 } else
9183 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9184 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9185 } else if (pri->pvts[chanpos]->confirmanswer) {
9186 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9187 } else {
9188 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9189 /* Enable echo cancellation if it's not on already */
9190 dahdi_enable_ec(pri->pvts[chanpos]);
9193 #ifdef SUPPORT_USERUSER
9194 if (!ast_strlen_zero(e->answer.useruserinfo)) {
9195 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9196 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9197 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
9198 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9200 #endif
9202 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9205 break;
9206 case PRI_EVENT_HANGUP:
9207 chanpos = pri_find_principle(pri, e->hangup.channel);
9208 if (chanpos < 0) {
9209 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
9210 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9211 } else {
9212 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9213 if (chanpos > -1) {
9214 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9215 if (!pri->pvts[chanpos]->alreadyhungup) {
9216 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9217 pri->pvts[chanpos]->alreadyhungup = 1;
9218 if (pri->pvts[chanpos]->realcall)
9219 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9220 else if (pri->pvts[chanpos]->owner) {
9221 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9222 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9223 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9224 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9225 else {
9226 switch (e->hangup.cause) {
9227 case PRI_CAUSE_USER_BUSY:
9228 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9229 break;
9230 case PRI_CAUSE_CALL_REJECTED:
9231 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9232 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9233 case PRI_CAUSE_SWITCH_CONGESTION:
9234 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9235 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9236 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9237 break;
9238 default:
9239 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9243 if (option_verbose > 2)
9244 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9245 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9246 } else {
9247 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9248 pri->pvts[chanpos]->call = NULL;
9250 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9251 if (option_verbose > 2)
9252 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9253 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9254 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9255 pri->pvts[chanpos]->resetting = 1;
9257 if (e->hangup.aoc_units > -1)
9258 if (option_verbose > 2)
9259 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9260 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9262 #ifdef SUPPORT_USERUSER
9263 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
9264 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9265 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9266 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9267 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9269 #endif
9271 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9272 } else {
9273 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9274 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9277 break;
9278 #ifndef PRI_EVENT_HANGUP_REQ
9279 #error please update libpri
9280 #endif
9281 case PRI_EVENT_HANGUP_REQ:
9282 chanpos = pri_find_principle(pri, e->hangup.channel);
9283 if (chanpos < 0) {
9284 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9285 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9286 } else {
9287 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9288 if (chanpos > -1) {
9289 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9290 if (pri->pvts[chanpos]->realcall)
9291 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9292 else if (pri->pvts[chanpos]->owner) {
9293 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9294 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9295 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9296 else {
9297 switch (e->hangup.cause) {
9298 case PRI_CAUSE_USER_BUSY:
9299 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9300 break;
9301 case PRI_CAUSE_CALL_REJECTED:
9302 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9303 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9304 case PRI_CAUSE_SWITCH_CONGESTION:
9305 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9306 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9307 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9308 break;
9309 default:
9310 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9313 if (option_verbose > 2)
9314 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);
9315 if (e->hangup.aoc_units > -1)
9316 if (option_verbose > 2)
9317 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9318 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9319 } else {
9320 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9321 pri->pvts[chanpos]->call = NULL;
9323 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9324 if (option_verbose > 2)
9325 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9326 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9327 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9328 pri->pvts[chanpos]->resetting = 1;
9331 #ifdef SUPPORT_USERUSER
9332 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9333 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9334 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9335 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9336 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9338 #endif
9340 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9341 } else {
9342 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);
9345 break;
9346 case PRI_EVENT_HANGUP_ACK:
9347 chanpos = pri_find_principle(pri, e->hangup.channel);
9348 if (chanpos < 0) {
9349 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9350 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9351 } else {
9352 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9353 if (chanpos > -1) {
9354 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9355 pri->pvts[chanpos]->call = NULL;
9356 pri->pvts[chanpos]->resetting = 0;
9357 if (pri->pvts[chanpos]->owner) {
9358 if (option_verbose > 2)
9359 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);
9362 #ifdef SUPPORT_USERUSER
9363 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9364 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9365 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9366 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9367 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9369 #endif
9371 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9374 break;
9375 case PRI_EVENT_CONFIG_ERR:
9376 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
9377 break;
9378 case PRI_EVENT_RESTART_ACK:
9379 chanpos = pri_find_principle(pri, e->restartack.channel);
9380 if (chanpos < 0) {
9381 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9382 channel number, so we have to figure it out... This must be why
9383 everybody resets exactly a channel at a time. */
9384 for (x = 0; x < pri->numchans; x++) {
9385 if (pri->pvts[x] && pri->pvts[x]->resetting) {
9386 chanpos = x;
9387 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9388 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
9389 pri->pvts[chanpos]->prioffset, pri->span);
9390 if (pri->pvts[chanpos]->realcall)
9391 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9392 else if (pri->pvts[chanpos]->owner) {
9393 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
9394 pri->pvts[chanpos]->prioffset, pri->span);
9395 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9397 pri->pvts[chanpos]->resetting = 0;
9398 if (option_verbose > 2)
9399 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9400 pri->pvts[chanpos]->prioffset, pri->span);
9401 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9402 if (pri->resetting)
9403 pri_check_restart(pri);
9404 break;
9407 if (chanpos < 0) {
9408 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
9409 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9411 } else {
9412 if (pri->pvts[chanpos]) {
9413 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9414 if (pri->pvts[chanpos]->realcall)
9415 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9416 else if (pri->pvts[chanpos]->owner) {
9417 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
9418 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9419 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9421 pri->pvts[chanpos]->resetting = 0;
9422 if (option_verbose > 2)
9423 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9424 pri->pvts[chanpos]->prioffset, pri->span);
9425 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9426 if (pri->resetting)
9427 pri_check_restart(pri);
9430 break;
9431 case PRI_EVENT_SETUP_ACK:
9432 chanpos = pri_find_principle(pri, e->setup_ack.channel);
9433 if (chanpos < 0) {
9434 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9435 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
9436 } else {
9437 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
9438 if (chanpos > -1) {
9439 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9440 pri->pvts[chanpos]->setup_ack = 1;
9441 /* Send any queued digits */
9442 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
9443 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
9444 pri_information(pri->pri, pri->pvts[chanpos]->call,
9445 pri->pvts[chanpos]->dialdest[x]);
9447 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9448 } else
9449 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
9451 break;
9452 case PRI_EVENT_NOTIFY:
9453 chanpos = pri_find_principle(pri, e->notify.channel);
9454 if (chanpos < 0) {
9455 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9456 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
9457 } else {
9458 struct ast_frame f = { AST_FRAME_CONTROL, };
9459 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9460 switch (e->notify.info) {
9461 case PRI_NOTIFY_REMOTE_HOLD:
9462 f.subclass = AST_CONTROL_HOLD;
9463 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9464 break;
9465 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9466 f.subclass = AST_CONTROL_UNHOLD;
9467 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9468 break;
9470 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9472 break;
9473 default:
9474 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9477 ast_mutex_unlock(&pri->lock);
9479 /* Never reached */
9480 return NULL;
9483 static int start_pri(struct dahdi_pri *pri)
9485 int res, x;
9486 DAHDI_PARAMS p;
9487 DAHDI_BUFFERINFO bi;
9488 DAHDI_SPANINFO si;
9489 int i;
9491 for (i = 0; i < NUM_DCHANS; i++) {
9492 if (!pri->dchannels[i])
9493 break;
9494 #ifdef HAVE_ZAPTEL
9495 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
9496 #else
9497 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
9498 #endif
9499 x = pri->dchannels[i];
9500 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
9501 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
9502 return -1;
9504 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
9505 if (res) {
9506 dahdi_close(pri->fds[i]);
9507 pri->fds[i] = -1;
9508 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
9509 return -1;
9511 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
9512 dahdi_close(pri->fds[i]);
9513 pri->fds[i] = -1;
9514 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x);
9515 return -1;
9517 memset(&si, 0, sizeof(si));
9518 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
9519 if (res) {
9520 dahdi_close(pri->fds[i]);
9521 pri->fds[i] = -1;
9522 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
9524 if (!si.alarms)
9525 pri->dchanavail[i] |= DCHAN_NOTINALARM;
9526 else
9527 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
9528 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
9529 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
9530 bi.numbufs = 32;
9531 bi.bufsize = 1024;
9532 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
9533 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
9534 dahdi_close(pri->fds[i]);
9535 pri->fds[i] = -1;
9536 return -1;
9538 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9539 /* Force overlap dial if we're doing GR-303! */
9540 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9541 pri->overlapdial = 1;
9542 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
9543 #ifdef HAVE_PRI_INBANDRELEASE
9544 pri_set_inbandrelease(pri->dchans[i], pri->inbandrelease);
9545 #endif
9546 /* Enslave to master if appropriate */
9547 if (i)
9548 pri_enslave(pri->dchans[0], pri->dchans[i]);
9549 if (!pri->dchans[i]) {
9550 dahdi_close(pri->fds[i]);
9551 pri->fds[i] = -1;
9552 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
9553 return -1;
9555 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
9556 pri_set_nsf(pri->dchans[i], pri->nsf);
9557 #ifdef PRI_GETSET_TIMERS
9558 for (x = 0; x < PRI_MAX_TIMERS; x++) {
9559 if (pritimers[x] != 0)
9560 pri_set_timer(pri->dchans[i], x, pritimers[x]);
9562 #endif
9564 /* Assume primary is the one we use */
9565 pri->pri = pri->dchans[0];
9566 pri->resetpos = -1;
9567 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
9568 for (i = 0; i < NUM_DCHANS; i++) {
9569 if (!pri->dchannels[i])
9570 break;
9571 dahdi_close(pri->fds[i]);
9572 pri->fds[i] = -1;
9574 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
9575 return -1;
9577 return 0;
9580 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
9582 int which, span;
9583 char *ret = NULL;
9585 if (pos != rpos)
9586 return ret;
9588 for (which = span = 0; span < NUM_SPANS; span++) {
9589 if (pris[span].pri && ++which > state) {
9590 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
9591 break;
9594 return ret;
9597 static char *complete_span_4(const char *line, const char *word, int pos, int state)
9599 return complete_span_helper(line,word,pos,state,3);
9602 static char *complete_span_5(const char *line, const char *word, int pos, int state)
9604 return complete_span_helper(line,word,pos,state,4);
9607 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9609 int myfd;
9611 if (!strncasecmp(argv[1], "set", 3)) {
9612 if (argc < 5)
9613 return RESULT_SHOWUSAGE;
9615 if (ast_strlen_zero(argv[4]))
9616 return RESULT_SHOWUSAGE;
9618 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
9619 if (myfd < 0) {
9620 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9621 return RESULT_SUCCESS;
9624 ast_mutex_lock(&pridebugfdlock);
9626 if (pridebugfd >= 0)
9627 close(pridebugfd);
9629 pridebugfd = myfd;
9630 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9632 ast_mutex_unlock(&pridebugfdlock);
9634 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9635 } else {
9636 /* Assume it is unset */
9637 ast_mutex_lock(&pridebugfdlock);
9638 close(pridebugfd);
9639 pridebugfd = -1;
9640 ast_cli(fd, "PRI debug output to file disabled\n");
9641 ast_mutex_unlock(&pridebugfdlock);
9644 return RESULT_SUCCESS;
9647 #ifdef HAVE_PRI_VERSION
9648 static int handle_pri_version(int fd, int agc, char *argv[]) {
9649 ast_cli(fd, "libpri version: %s\n", pri_get_version());
9650 return RESULT_SUCCESS;
9652 #endif
9654 static int handle_pri_debug(int fd, int argc, char *argv[])
9656 int span;
9657 int x;
9658 if (argc < 4) {
9659 return RESULT_SHOWUSAGE;
9661 span = atoi(argv[3]);
9662 if ((span < 1) || (span > NUM_SPANS)) {
9663 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
9664 return RESULT_SUCCESS;
9666 if (!pris[span-1].pri) {
9667 ast_cli(fd, "No PRI running on span %d\n", span);
9668 return RESULT_SUCCESS;
9670 for (x = 0; x < NUM_DCHANS; x++) {
9671 if (pris[span-1].dchans[x])
9672 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9673 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9674 PRI_DEBUG_Q921_STATE);
9676 ast_cli(fd, "Enabled debugging on span %d\n", span);
9677 return RESULT_SUCCESS;
9682 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9684 int span;
9685 int x;
9686 if (argc < 5)
9687 return RESULT_SHOWUSAGE;
9688 span = atoi(argv[4]);
9689 if ((span < 1) || (span > NUM_SPANS)) {
9690 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9691 return RESULT_SUCCESS;
9693 if (!pris[span-1].pri) {
9694 ast_cli(fd, "No PRI running on span %d\n", span);
9695 return RESULT_SUCCESS;
9697 for (x = 0; x < NUM_DCHANS; x++) {
9698 if (pris[span-1].dchans[x])
9699 pri_set_debug(pris[span-1].dchans[x], 0);
9701 ast_cli(fd, "Disabled debugging on span %d\n", span);
9702 return RESULT_SUCCESS;
9705 static int handle_pri_really_debug(int fd, int argc, char *argv[])
9707 int span;
9708 int x;
9709 if (argc < 5)
9710 return RESULT_SHOWUSAGE;
9711 span = atoi(argv[4]);
9712 if ((span < 1) || (span > NUM_SPANS)) {
9713 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9714 return RESULT_SUCCESS;
9716 if (!pris[span-1].pri) {
9717 ast_cli(fd, "No PRI running on span %d\n", span);
9718 return RESULT_SUCCESS;
9720 for (x = 0; x < NUM_DCHANS; x++) {
9721 if (pris[span-1].dchans[x])
9722 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9723 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9724 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
9726 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
9727 return RESULT_SUCCESS;
9730 static void build_status(char *s, size_t len, int status, int active)
9732 if (!s || len < 1) {
9733 return;
9735 s[0] = '\0';
9736 if (status & DCHAN_PROVISIONED)
9737 strncat(s, "Provisioned, ", len - strlen(s) - 1);
9738 if (!(status & DCHAN_NOTINALARM))
9739 strncat(s, "In Alarm, ", len - strlen(s) - 1);
9740 if (status & DCHAN_UP)
9741 strncat(s, "Up", len - strlen(s) - 1);
9742 else
9743 strncat(s, "Down", len - strlen(s) - 1);
9744 if (active)
9745 strncat(s, ", Active", len - strlen(s) - 1);
9746 else
9747 strncat(s, ", Standby", len - strlen(s) - 1);
9748 s[len - 1] = '\0';
9751 static int handle_pri_show_spans(int fd, int argc, char *argv[])
9753 int span;
9754 int x;
9755 char status[256];
9756 if (argc != 3)
9757 return RESULT_SHOWUSAGE;
9759 for (span = 0; span < NUM_SPANS; span++) {
9760 if (pris[span].pri) {
9761 for (x = 0; x < NUM_DCHANS; x++) {
9762 if (pris[span].dchannels[x]) {
9763 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
9764 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
9769 return RESULT_SUCCESS;
9772 static int handle_pri_show_span(int fd, int argc, char *argv[])
9774 int span;
9775 int x;
9776 char status[256];
9777 if (argc < 4)
9778 return RESULT_SHOWUSAGE;
9779 span = atoi(argv[3]);
9780 if ((span < 1) || (span > NUM_SPANS)) {
9781 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
9782 return RESULT_SUCCESS;
9784 if (!pris[span-1].pri) {
9785 ast_cli(fd, "No PRI running on span %d\n", span);
9786 return RESULT_SUCCESS;
9788 for (x = 0; x < NUM_DCHANS; x++) {
9789 if (pris[span-1].dchannels[x]) {
9790 #ifdef PRI_DUMP_INFO_STR
9791 char *info_str = NULL;
9792 #endif
9793 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
9794 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
9795 ast_cli(fd, "Status: %s\n", status);
9796 #ifdef PRI_DUMP_INFO_STR
9797 info_str = pri_dump_info_str(pris[span-1].pri);
9798 if (info_str) {
9799 ast_cli(fd, "%s", info_str);
9800 free(info_str);
9802 #else
9803 pri_dump_info(pris[span-1].pri);
9804 #endif
9805 ast_cli(fd, "\n");
9808 return RESULT_SUCCESS;
9811 static int handle_pri_show_debug(int fd, int argc, char *argv[])
9813 int x;
9814 int span;
9815 int count=0;
9816 int debug=0;
9818 for (span = 0; span < NUM_SPANS; span++) {
9819 if (pris[span].pri) {
9820 for (x = 0; x < NUM_DCHANS; x++) {
9821 debug = 0;
9822 if (pris[span].dchans[x]) {
9823 debug = pri_get_debug(pris[span].dchans[x]);
9824 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" );
9825 count++;
9831 ast_mutex_lock(&pridebugfdlock);
9832 if (pridebugfd >= 0)
9833 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9834 ast_mutex_unlock(&pridebugfdlock);
9836 if (!count)
9837 ast_cli(fd, "No debug set or no PRI running\n");
9838 return RESULT_SUCCESS;
9841 static const char pri_debug_help[] =
9842 "Usage: pri debug span <span>\n"
9843 " Enables debugging on a given PRI span\n";
9845 static const char pri_no_debug_help[] =
9846 "Usage: pri no debug span <span>\n"
9847 " Disables debugging on a given PRI span\n";
9849 static const char pri_really_debug_help[] =
9850 "Usage: pri intensive debug span <span>\n"
9851 " Enables debugging down to the Q.921 level\n";
9853 static const char pri_show_span_help[] =
9854 "Usage: pri show span <span>\n"
9855 " Displays PRI Information on a given PRI span\n";
9857 static const char pri_show_spans_help[] =
9858 "Usage: pri show spans\n"
9859 " Displays PRI Information\n";
9861 static struct ast_cli_entry dahdi_pri_cli[] = {
9862 { { "pri", "debug", "span", NULL },
9863 handle_pri_debug, "Enables PRI debugging on a span",
9864 pri_debug_help, complete_span_4 },
9866 { { "pri", "no", "debug", "span", NULL },
9867 handle_pri_no_debug, "Disables PRI debugging on a span",
9868 pri_no_debug_help, complete_span_5 },
9870 { { "pri", "intense", "debug", "span", NULL },
9871 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
9872 pri_really_debug_help, complete_span_5 },
9874 { { "pri", "show", "spans", NULL },
9875 handle_pri_show_spans, "Displays PRI Information",
9876 pri_show_spans_help },
9878 { { "pri", "show", "span", NULL },
9879 handle_pri_show_span, "Displays PRI Information",
9880 pri_show_span_help, complete_span_4 },
9882 { { "pri", "show", "debug", NULL },
9883 handle_pri_show_debug, "Displays current PRI debug settings" },
9885 { { "pri", "set", "debug", "file", NULL },
9886 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
9888 { { "pri", "unset", "debug", "file", NULL },
9889 handle_pri_set_debug_file, "Ends PRI debug output to file" },
9891 #ifdef HAVE_PRI_VERSION
9892 { { "pri", "show", "version", NULL },
9893 handle_pri_version, "Displays version of libpri" },
9894 #endif
9897 #endif /* HAVE_PRI */
9899 static int dahdi_destroy_channel(int fd, int argc, char **argv)
9901 int channel;
9903 if (argc != 4)
9904 return RESULT_SHOWUSAGE;
9906 channel = atoi(argv[3]);
9908 return dahdi_destroy_channel_bynum(channel);
9911 static int setup_dahdi(int reload);
9912 static int dahdi_restart(void)
9914 if (option_verbose > 0)
9915 ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading DAHDI configuration.\n");
9916 while (iflist) {
9917 if (option_debug)
9918 ast_log(LOG_DEBUG, "Destroying DAHDI channel no. %d\n", iflist->channel);
9919 /* Also updates iflist: */
9920 destroy_channel(NULL, iflist, 1);
9922 if (option_debug)
9923 ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
9924 if (setup_dahdi(0) != 0) {
9925 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
9926 return 1;
9928 return 0;
9931 static int dahdi_restart_cmd(int fd, int argc, char **argv)
9933 if (argc != 2) {
9934 return RESULT_SHOWUSAGE;
9937 if (dahdi_restart() != 0)
9938 return RESULT_FAILURE;
9939 return RESULT_SUCCESS;
9942 static int action_dahdirestart(struct mansession *s, const struct message *m)
9944 if (dahdi_restart() != 0) {
9945 astman_send_error(s, m, "Failed rereading DAHDI configuration");
9946 return 1;
9948 astman_send_ack(s, m, "DAHDIRestart: Success");
9949 return 0;
9952 static int dahdi_show_channels(int fd, int argc, char **argv)
9954 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9955 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9956 struct dahdi_pvt *tmp = NULL;
9957 char tmps[20] = "";
9958 ast_mutex_t *lock;
9959 struct dahdi_pvt *start;
9960 #ifdef HAVE_PRI
9961 int trunkgroup;
9962 struct dahdi_pri *pri = NULL;
9963 int x;
9964 #endif
9966 lock = &iflock;
9967 start = iflist;
9969 #ifdef HAVE_PRI
9970 if (argc == 4) {
9971 if ((trunkgroup = atoi(argv[3])) < 1)
9972 return RESULT_SHOWUSAGE;
9973 for (x = 0; x < NUM_SPANS; x++) {
9974 if (pris[x].trunkgroup == trunkgroup) {
9975 pri = pris + x;
9976 break;
9979 if (pri) {
9980 start = pri->crvs;
9981 lock = &pri->lock;
9982 } else {
9983 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
9984 return RESULT_FAILURE;
9986 } else
9987 #endif
9988 if (argc != 3)
9989 return RESULT_SHOWUSAGE;
9991 ast_mutex_lock(lock);
9992 #ifdef HAVE_PRI
9993 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
9994 #else
9995 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
9996 #endif
9998 tmp = start;
9999 while (tmp) {
10000 if (tmp->channel > 0) {
10001 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10002 } else
10003 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10004 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10005 tmp = tmp->next;
10007 ast_mutex_unlock(lock);
10008 return RESULT_SUCCESS;
10009 #undef FORMAT
10010 #undef FORMAT2
10013 static int dahdi_show_channel(int fd, int argc, char **argv)
10015 int channel;
10016 struct dahdi_pvt *tmp = NULL;
10017 DAHDI_CONFINFO ci;
10018 DAHDI_PARAMS ps;
10019 int x;
10020 ast_mutex_t *lock;
10021 struct dahdi_pvt *start;
10022 #ifdef HAVE_PRI
10023 char *c;
10024 int trunkgroup;
10025 struct dahdi_pri *pri=NULL;
10026 #endif
10028 lock = &iflock;
10029 start = iflist;
10031 if (argc != 4)
10032 return RESULT_SHOWUSAGE;
10033 #ifdef HAVE_PRI
10034 if ((c = strchr(argv[3], ':'))) {
10035 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10036 return RESULT_SHOWUSAGE;
10037 if ((trunkgroup < 1) || (channel < 1))
10038 return RESULT_SHOWUSAGE;
10039 for (x = 0; x < NUM_SPANS; x++) {
10040 if (pris[x].trunkgroup == trunkgroup) {
10041 pri = pris + x;
10042 break;
10045 if (pri) {
10046 start = pri->crvs;
10047 lock = &pri->lock;
10048 } else {
10049 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10050 return RESULT_FAILURE;
10052 } else
10053 #endif
10054 channel = atoi(argv[3]);
10056 ast_mutex_lock(lock);
10057 tmp = start;
10058 while (tmp) {
10059 if (tmp->channel == channel) {
10060 #ifdef HAVE_PRI
10061 if (pri)
10062 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10063 else
10064 #endif
10065 ast_cli(fd, "Channel: %d\n", tmp->channel);
10066 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10067 ast_cli(fd, "Span: %d\n", tmp->span);
10068 ast_cli(fd, "Extension: %s\n", tmp->exten);
10069 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10070 ast_cli(fd, "Context: %s\n", tmp->context);
10071 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10072 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10073 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10074 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10075 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10076 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10077 ast_cli(fd, "Radio: %d\n", tmp->radio);
10078 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10079 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)" : "");
10080 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)" : "");
10081 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)" : "");
10082 ast_cli(fd, "Confno: %d\n", tmp->confno);
10083 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10084 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10085 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10086 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10087 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10088 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10089 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10090 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10091 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10092 if (tmp->master)
10093 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10094 for (x = 0; x < MAX_SLAVES; x++) {
10095 if (tmp->slaves[x])
10096 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10098 #ifdef HAVE_PRI
10099 if (tmp->pri) {
10100 ast_cli(fd, "PRI Flags: ");
10101 if (tmp->resetting)
10102 ast_cli(fd, "Resetting ");
10103 if (tmp->call)
10104 ast_cli(fd, "Call ");
10105 if (tmp->bearer)
10106 ast_cli(fd, "Bearer ");
10107 ast_cli(fd, "\n");
10108 if (tmp->logicalspan)
10109 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10110 else
10111 ast_cli(fd, "PRI Logical Span: Implicit\n");
10114 #endif
10115 memset(&ci, 0, sizeof(ci));
10116 ps.channo = tmp->channel;
10117 if (tmp->subs[SUB_REAL].dfd > -1) {
10118 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10119 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10121 #ifdef DAHDI_GETCONFMUTE
10122 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10123 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10125 #endif
10126 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10127 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10128 } else {
10129 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10132 ast_mutex_unlock(lock);
10133 return RESULT_SUCCESS;
10135 tmp = tmp->next;
10138 ast_cli(fd, "Unable to find given channel %d\n", channel);
10139 ast_mutex_unlock(lock);
10140 return RESULT_FAILURE;
10143 static char dahdi_show_cadences_usage[] =
10144 "Usage: dahdi show cadences\n"
10145 " Shows all cadences currently defined\n";
10147 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10149 int i, j;
10150 for (i = 0; i < num_cadence; i++) {
10151 char output[1024];
10152 char tmp[16], tmp2[64];
10153 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10154 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10156 for (j = 0; j < 16; j++) {
10157 if (cadences[i].ringcadence[j] == 0)
10158 break;
10159 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10160 if (cidrings[i] * 2 - 1 == j)
10161 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10162 else
10163 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10164 if (j != 0)
10165 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10166 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10168 ast_cli(fd,"%s\n",output);
10170 return 0;
10173 /* Based on irqmiss.c */
10174 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10175 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10176 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10178 int span;
10179 int res;
10180 char alarms[50];
10182 int ctl;
10183 DAHDI_SPANINFO s;
10185 #ifdef HAVE_ZAPTEL
10186 ctl = open("/dev/zap/ctl", O_RDWR);
10187 #else
10188 ctl = open("/dev/dahdi/ctl", O_RDWR);
10189 #endif
10190 if (ctl < 0) {
10191 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10192 ast_cli(fd, "No DAHDI interface found.\n");
10193 return RESULT_FAILURE;
10195 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10197 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10198 s.spanno = span;
10199 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10200 if (res) {
10201 continue;
10203 alarms[0] = '\0';
10204 if (s.alarms > 0) {
10205 if (s.alarms & DAHDI_ALARM_BLUE)
10206 strcat(alarms, "BLU/");
10207 if (s.alarms & DAHDI_ALARM_YELLOW)
10208 strcat(alarms, "YEL/");
10209 if (s.alarms & DAHDI_ALARM_RED)
10210 strcat(alarms, "RED/");
10211 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10212 strcat(alarms, "LB/");
10213 if (s.alarms & DAHDI_ALARM_RECOVER)
10214 strcat(alarms, "REC/");
10215 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10216 strcat(alarms, "NOP/");
10217 if (!strlen(alarms))
10218 strcat(alarms, "UUU/");
10219 if (strlen(alarms)) {
10220 /* Strip trailing / */
10221 alarms[strlen(alarms) - 1] = '\0';
10223 } else {
10224 if (s.numchans)
10225 strcpy(alarms, "OK");
10226 else
10227 strcpy(alarms, "UNCONFIGURED");
10230 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10232 close(ctl);
10234 return RESULT_SUCCESS;
10235 #undef FORMAT
10236 #undef FORMAT2
10239 static char show_channels_usage[] =
10240 "Usage: dahdi show channels\n"
10241 " Shows a list of available channels\n";
10243 static char show_channel_usage[] =
10244 "Usage: dahdi show channel <chan num>\n"
10245 " Detailed information about a given channel\n";
10247 static char dahdi_show_status_usage[] =
10248 "Usage: dahdi show status\n"
10249 " Shows a list of DAHDI cards with status\n";
10251 static char destroy_channel_usage[] =
10252 "Usage: dahdi destroy channel <chan num>\n"
10253 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10255 static char dahdi_restart_usage[] =
10256 "Usage: dahdi restart\n"
10257 " Restarts the DAHDI channels: destroys them all and then\n"
10258 " re-reads them from chan_dahdi.conf.\n"
10259 " Note that this will STOP any running CALL on DAHDI channels.\n"
10262 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10263 { "zap", "show", "cadences", NULL },
10264 handle_dahdi_show_cadences, NULL,
10265 NULL };
10267 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10268 { "zap", "show", "channels", NULL },
10269 dahdi_show_channels, NULL,
10270 NULL };
10272 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10273 { "zap", "show", "channel", NULL },
10274 dahdi_show_channel, NULL,
10275 NULL };
10277 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10278 { "zap", "destroy", "channel", NULL },
10279 dahdi_destroy_channel, NULL,
10280 NULL };
10282 static struct ast_cli_entry cli_zap_restart_deprecated = {
10283 { "zap", "restart", NULL },
10284 dahdi_restart_cmd, NULL,
10285 NULL };
10287 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10288 { "zap", "show", "status", NULL },
10289 dahdi_show_status, NULL,
10290 NULL };
10292 static struct ast_cli_entry dahdi_cli[] = {
10293 { { "dahdi", "show", "cadences", NULL },
10294 handle_dahdi_show_cadences, "List cadences",
10295 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10297 { { "dahdi", "show", "channels", NULL},
10298 dahdi_show_channels, "Show active DAHDI channels",
10299 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10301 { { "dahdi", "show", "channel", NULL},
10302 dahdi_show_channel, "Show information on a channel",
10303 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10305 { { "dahdi", "destroy", "channel", NULL},
10306 dahdi_destroy_channel, "Destroy a channel",
10307 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10309 { { "dahdi", "restart", NULL},
10310 dahdi_restart_cmd, "Fully restart DAHDI channels",
10311 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10313 { { "dahdi", "show", "status", NULL},
10314 dahdi_show_status, "Show all DAHDI cards status",
10315 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10318 #define TRANSFER 0
10319 #define HANGUP 1
10321 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10323 if (p) {
10324 switch (mode) {
10325 case TRANSFER:
10326 p->fake_event = DAHDI_EVENT_WINKFLASH;
10327 break;
10328 case HANGUP:
10329 p->fake_event = DAHDI_EVENT_ONHOOK;
10330 break;
10331 default:
10332 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10335 return 0;
10337 static struct dahdi_pvt *find_channel(int channel)
10339 struct dahdi_pvt *p = iflist;
10340 while (p) {
10341 if (p->channel == channel) {
10342 break;
10344 p = p->next;
10346 return p;
10349 static int action_dahdidndon(struct mansession *s, const struct message *m)
10351 struct dahdi_pvt *p = NULL;
10352 const char *channel = astman_get_header(m, "DAHDIChannel");
10354 if (ast_strlen_zero(channel)) {
10355 astman_send_error(s, m, "No channel specified");
10356 return 0;
10358 p = find_channel(atoi(channel));
10359 if (!p) {
10360 astman_send_error(s, m, "No such channel");
10361 return 0;
10363 p->dnd = 1;
10364 astman_send_ack(s, m, "DND Enabled");
10365 return 0;
10368 static int action_dahdidndoff(struct mansession *s, const struct message *m)
10370 struct dahdi_pvt *p = NULL;
10371 const char *channel = astman_get_header(m, "DAHDIChannel");
10373 if (ast_strlen_zero(channel)) {
10374 astman_send_error(s, m, "No channel specified");
10375 return 0;
10377 p = find_channel(atoi(channel));
10378 if (!p) {
10379 astman_send_error(s, m, "No such channel");
10380 return 0;
10382 p->dnd = 0;
10383 astman_send_ack(s, m, "DND Disabled");
10384 return 0;
10387 static int action_transfer(struct mansession *s, const struct message *m)
10389 struct dahdi_pvt *p = NULL;
10390 const char *channel = astman_get_header(m, "DAHDIChannel");
10392 if (ast_strlen_zero(channel)) {
10393 astman_send_error(s, m, "No channel specified");
10394 return 0;
10396 p = find_channel(atoi(channel));
10397 if (!p) {
10398 astman_send_error(s, m, "No such channel");
10399 return 0;
10401 dahdi_fake_event(p,TRANSFER);
10402 astman_send_ack(s, m, "DAHDITransfer");
10403 return 0;
10406 static int action_transferhangup(struct mansession *s, const struct message *m)
10408 struct dahdi_pvt *p = NULL;
10409 const char *channel = astman_get_header(m, "DAHDIChannel");
10411 if (ast_strlen_zero(channel)) {
10412 astman_send_error(s, m, "No channel specified");
10413 return 0;
10415 p = find_channel(atoi(channel));
10416 if (!p) {
10417 astman_send_error(s, m, "No such channel");
10418 return 0;
10420 dahdi_fake_event(p,HANGUP);
10421 astman_send_ack(s, m, "DAHDIHangup");
10422 return 0;
10425 static int action_dahdidialoffhook(struct mansession *s, const struct message *m)
10427 struct dahdi_pvt *p = NULL;
10428 const char *channel = astman_get_header(m, "DAHDIChannel");
10429 const char *number = astman_get_header(m, "Number");
10430 int i;
10432 if (ast_strlen_zero(channel)) {
10433 astman_send_error(s, m, "No channel specified");
10434 return 0;
10436 if (ast_strlen_zero(number)) {
10437 astman_send_error(s, m, "No number specified");
10438 return 0;
10440 p = find_channel(atoi(channel));
10441 if (!p) {
10442 astman_send_error(s, m, "No such channel");
10443 return 0;
10445 if (!p->owner) {
10446 astman_send_error(s, m, "Channel does not have it's owner");
10447 return 0;
10449 for (i = 0; i < strlen(number); i++) {
10450 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10451 dahdi_queue_frame(p, &f, NULL);
10453 astman_send_ack(s, m, "DAHDIDialOffhook");
10454 return 0;
10457 static int action_dahdishowchannels(struct mansession *s, const struct message *m)
10459 struct dahdi_pvt *tmp = NULL;
10460 const char *id = astman_get_header(m, "ActionID");
10461 char idText[256] = "";
10463 astman_send_ack(s, m, "DAHDI channel status will follow");
10464 if (!ast_strlen_zero(id))
10465 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10467 ast_mutex_lock(&iflock);
10469 tmp = iflist;
10470 while (tmp) {
10471 if (tmp->channel > 0) {
10472 int alarm = get_alarms(tmp);
10473 astman_append(s,
10474 "Event: DAHDIShowChannels\r\n"
10475 "Channel: %d\r\n"
10476 "Signalling: %s\r\n"
10477 "Context: %s\r\n"
10478 "DND: %s\r\n"
10479 "Alarm: %s\r\n"
10480 "%s"
10481 "\r\n",
10482 tmp->channel, sig2str(tmp->sig), tmp->context,
10483 tmp->dnd ? "Enabled" : "Disabled",
10484 alarm2str(alarm), idText);
10487 tmp = tmp->next;
10490 ast_mutex_unlock(&iflock);
10492 astman_append(s,
10493 "Event: DAHDIShowChannelsComplete\r\n"
10494 "%s"
10495 "\r\n",
10496 idText);
10497 return 0;
10500 static int __unload_module(void)
10502 int x;
10503 struct dahdi_pvt *p, *pl;
10505 #ifdef HAVE_PRI
10506 int i;
10507 for (i = 0; i < NUM_SPANS; i++) {
10508 if (pris[i].master != AST_PTHREADT_NULL)
10509 pthread_cancel(pris[i].master);
10511 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10512 ast_unregister_application(dahdi_send_keypad_facility_app);
10513 #endif
10514 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10515 ast_manager_unregister( "DAHDIDialOffhook" );
10516 ast_manager_unregister( "DAHDIHangup" );
10517 ast_manager_unregister( "DAHDITransfer" );
10518 ast_manager_unregister( "DAHDIDNDoff" );
10519 ast_manager_unregister( "DAHDIDNDon" );
10520 ast_manager_unregister("DAHDIShowChannels");
10521 ast_manager_unregister("DAHDIRestart");
10522 ast_channel_unregister(&dahdi_tech);
10523 ast_mutex_lock(&iflock);
10524 /* Hangup all interfaces if they have an owner */
10525 p = iflist;
10526 while (p) {
10527 if (p->owner)
10528 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10529 p = p->next;
10531 ast_mutex_unlock(&iflock);
10532 ast_mutex_lock(&monlock);
10533 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10534 pthread_cancel(monitor_thread);
10535 pthread_kill(monitor_thread, SIGURG);
10536 pthread_join(monitor_thread, NULL);
10538 monitor_thread = AST_PTHREADT_STOP;
10539 ast_mutex_unlock(&monlock);
10541 ast_mutex_lock(&iflock);
10542 /* Destroy all the interfaces and free their memory */
10543 p = iflist;
10544 while (p) {
10545 /* Free any callerid */
10546 if (p->cidspill)
10547 free(p->cidspill);
10548 /* Close the DAHDI thingy */
10549 if (p->subs[SUB_REAL].dfd > -1)
10550 dahdi_close(p->subs[SUB_REAL].dfd);
10551 pl = p;
10552 p = p->next;
10553 x = pl->channel;
10554 /* Free associated memory */
10555 if (pl)
10556 destroy_dahdi_pvt(&pl);
10557 ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10559 iflist = NULL;
10560 ifcount = 0;
10561 ast_mutex_unlock(&iflock);
10562 #ifdef HAVE_PRI
10563 for (i = 0; i < NUM_SPANS; i++) {
10564 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10565 pthread_join(pris[i].master, NULL);
10566 dahdi_close(pris[i].fds[i]);
10568 #endif
10569 return 0;
10572 static int unload_module(void)
10574 #ifdef HAVE_PRI
10575 int y;
10576 for (y = 0; y < NUM_SPANS; y++)
10577 ast_mutex_destroy(&pris[y].lock);
10578 #endif
10579 return __unload_module();
10582 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10584 char *c, *chan;
10585 int x, start, finish;
10586 struct dahdi_pvt *tmp;
10587 #ifdef HAVE_PRI
10588 struct dahdi_pri *pri;
10589 int trunkgroup, y;
10590 #endif
10592 if ((reload == 0) && (conf->chan.sig < 0)) {
10593 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10594 return -1;
10597 c = ast_strdupa(value);
10599 #ifdef HAVE_PRI
10600 pri = NULL;
10601 if (iscrv) {
10602 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10603 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10604 return -1;
10606 if (trunkgroup < 1) {
10607 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10608 return -1;
10610 c += y;
10611 for (y = 0; y < NUM_SPANS; y++) {
10612 if (pris[y].trunkgroup == trunkgroup) {
10613 pri = pris + y;
10614 break;
10617 if (!pri) {
10618 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10619 return -1;
10622 #endif
10624 while ((chan = strsep(&c, ","))) {
10625 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10626 /* Range */
10627 } else if (sscanf(chan, "%d", &start)) {
10628 /* Just one */
10629 finish = start;
10630 } else if (!strcasecmp(chan, "pseudo")) {
10631 finish = start = CHAN_PSEUDO;
10632 if (found_pseudo)
10633 *found_pseudo = 1;
10634 } else {
10635 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10636 return -1;
10638 if (finish < start) {
10639 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10640 x = finish;
10641 finish = start;
10642 start = x;
10645 for (x = start; x <= finish; x++) {
10646 #ifdef HAVE_PRI
10647 tmp = mkintf(x, conf, pri, reload);
10648 #else
10649 tmp = mkintf(x, conf, NULL, reload);
10650 #endif
10652 if (tmp) {
10653 if (option_verbose > 2) {
10654 #ifdef HAVE_PRI
10655 if (pri)
10656 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10657 else
10658 #endif
10659 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10661 } else {
10662 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10663 (reload == 1) ? "reconfigure" : "register", value);
10664 return -1;
10669 return 0;
10672 /** The length of the parameters list of 'dahdichan'.
10673 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10674 #define MAX_CHANLIST_LEN 80
10675 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10677 struct dahdi_pvt *tmp;
10678 char *ringc; /* temporary string for parsing the dring number. */
10679 int y;
10680 int found_pseudo = 0;
10681 char dahdichan[MAX_CHANLIST_LEN] = {};
10683 for (; v; v = v->next) {
10684 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10685 continue;
10687 /* Create the interface list */
10688 if (!strcasecmp(v->name, "channel")
10689 #ifdef HAVE_PRI
10690 || !strcasecmp(v->name, "crv")
10691 #endif
10693 int iscrv;
10694 if (skipchannels)
10695 continue;
10696 iscrv = !strcasecmp(v->name, "crv");
10697 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
10698 return -1;
10699 } else if (!strcasecmp(v->name, "dahdichan")) {
10700 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
10701 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
10702 if (ast_true(v->value))
10703 confp->chan.usedistinctiveringdetection = 1;
10704 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
10705 if (ast_true(v->value))
10706 distinctiveringaftercid = 1;
10707 } else if (!strcasecmp(v->name, "dring1context")) {
10708 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
10709 } else if (!strcasecmp(v->name, "dring2context")) {
10710 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
10711 } else if (!strcasecmp(v->name, "dring3context")) {
10712 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
10713 } else if (!strcasecmp(v->name, "dring1")) {
10714 ringc = v->value;
10715 sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
10716 } else if (!strcasecmp(v->name, "dring2")) {
10717 ringc = v->value;
10718 sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
10719 } else if (!strcasecmp(v->name, "dring3")) {
10720 ringc = v->value;
10721 sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
10722 } else if (!strcasecmp(v->name, "usecallerid")) {
10723 confp->chan.use_callerid = ast_true(v->value);
10724 } else if (!strcasecmp(v->name, "cidsignalling")) {
10725 if (!strcasecmp(v->value, "bell"))
10726 confp->chan.cid_signalling = CID_SIG_BELL;
10727 else if (!strcasecmp(v->value, "v23"))
10728 confp->chan.cid_signalling = CID_SIG_V23;
10729 else if (!strcasecmp(v->value, "dtmf"))
10730 confp->chan.cid_signalling = CID_SIG_DTMF;
10731 else if (!strcasecmp(v->value, "smdi"))
10732 confp->chan.cid_signalling = CID_SIG_SMDI;
10733 else if (!strcasecmp(v->value, "v23_jp"))
10734 confp->chan.cid_signalling = CID_SIG_V23_JP;
10735 else if (ast_true(v->value))
10736 confp->chan.cid_signalling = CID_SIG_BELL;
10737 } else if (!strcasecmp(v->name, "cidstart")) {
10738 if (!strcasecmp(v->value, "ring"))
10739 confp->chan.cid_start = CID_START_RING;
10740 else if (!strcasecmp(v->value, "polarity"))
10741 confp->chan.cid_start = CID_START_POLARITY;
10742 else if (ast_true(v->value))
10743 confp->chan.cid_start = CID_START_RING;
10744 } else if (!strcasecmp(v->name, "threewaycalling")) {
10745 confp->chan.threewaycalling = ast_true(v->value);
10746 } else if (!strcasecmp(v->name, "cancallforward")) {
10747 confp->chan.cancallforward = ast_true(v->value);
10748 } else if (!strcasecmp(v->name, "relaxdtmf")) {
10749 if (ast_true(v->value))
10750 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
10751 else
10752 confp->chan.dtmfrelax = 0;
10753 } else if (!strcasecmp(v->name, "mailbox")) {
10754 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
10755 } else if (!strcasecmp(v->name, "hasvoicemail")) {
10756 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
10757 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
10759 } else if (!strcasecmp(v->name, "adsi")) {
10760 confp->chan.adsi = ast_true(v->value);
10761 } else if (!strcasecmp(v->name, "usesmdi")) {
10762 confp->chan.use_smdi = ast_true(v->value);
10763 } else if (!strcasecmp(v->name, "smdiport")) {
10764 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
10765 } else if (!strcasecmp(v->name, "transfer")) {
10766 confp->chan.transfer = ast_true(v->value);
10767 } else if (!strcasecmp(v->name, "canpark")) {
10768 confp->chan.canpark = ast_true(v->value);
10769 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
10770 confp->chan.echocanbridged = ast_true(v->value);
10771 } else if (!strcasecmp(v->name, "busydetect")) {
10772 confp->chan.busydetect = ast_true(v->value);
10773 } else if (!strcasecmp(v->name, "busycount")) {
10774 confp->chan.busycount = atoi(v->value);
10775 } else if (!strcasecmp(v->name, "busypattern")) {
10776 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
10777 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
10779 } else if (!strcasecmp(v->name, "callprogress")) {
10780 if (ast_true(v->value))
10781 confp->chan.callprogress |= 1;
10782 else
10783 confp->chan.callprogress &= ~1;
10784 } else if (!strcasecmp(v->name, "faxdetect")) {
10785 if (!strcasecmp(v->value, "incoming")) {
10786 confp->chan.callprogress |= 4;
10787 confp->chan.callprogress &= ~2;
10788 } else if (!strcasecmp(v->value, "outgoing")) {
10789 confp->chan.callprogress &= ~4;
10790 confp->chan.callprogress |= 2;
10791 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
10792 confp->chan.callprogress |= 6;
10793 else
10794 confp->chan.callprogress &= ~6;
10795 } else if (!strcasecmp(v->name, "echocancel")) {
10796 if (!ast_strlen_zero(v->value)) {
10797 y = atoi(v->value);
10798 } else
10799 y = 0;
10800 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
10801 confp->chan.echocancel = y;
10802 else {
10803 confp->chan.echocancel = ast_true(v->value);
10804 if (confp->chan.echocancel)
10805 confp->chan.echocancel=128;
10807 } else if (!strcasecmp(v->name, "echotraining")) {
10808 if (sscanf(v->value, "%d", &y) == 1) {
10809 if ((y < 10) || (y > 4000)) {
10810 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
10811 } else {
10812 confp->chan.echotraining = y;
10814 } else if (ast_true(v->value)) {
10815 confp->chan.echotraining = 400;
10816 } else
10817 confp->chan.echotraining = 0;
10818 } else if (!strcasecmp(v->name, "hidecallerid")) {
10819 confp->chan.hidecallerid = ast_true(v->value);
10820 } else if (!strcasecmp(v->name, "hidecalleridname")) {
10821 confp->chan.hidecalleridname = ast_true(v->value);
10822 } else if (!strcasecmp(v->name, "pulsedial")) {
10823 confp->chan.pulse = ast_true(v->value);
10824 } else if (!strcasecmp(v->name, "callreturn")) {
10825 confp->chan.callreturn = ast_true(v->value);
10826 } else if (!strcasecmp(v->name, "callwaiting")) {
10827 confp->chan.callwaiting = ast_true(v->value);
10828 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
10829 confp->chan.callwaitingcallerid = ast_true(v->value);
10830 } else if (!strcasecmp(v->name, "context")) {
10831 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
10832 } else if (!strcasecmp(v->name, "language")) {
10833 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
10834 } else if (!strcasecmp(v->name, "progzone")) {
10835 ast_copy_string(progzone, v->value, sizeof(progzone));
10836 } else if (!strcasecmp(v->name, "mohinterpret")
10837 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
10838 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
10839 } else if (!strcasecmp(v->name, "mohsuggest")) {
10840 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
10841 } else if (!strcasecmp(v->name, "stripmsd")) {
10842 confp->chan.stripmsd = atoi(v->value);
10843 } else if (!strcasecmp(v->name, "jitterbuffers")) {
10844 numbufs = atoi(v->value);
10845 } else if (!strcasecmp(v->name, "group")) {
10846 confp->chan.group = ast_get_group(v->value);
10847 } else if (!strcasecmp(v->name, "callgroup")) {
10848 confp->chan.callgroup = ast_get_group(v->value);
10849 } else if (!strcasecmp(v->name, "pickupgroup")) {
10850 confp->chan.pickupgroup = ast_get_group(v->value);
10851 } else if (!strcasecmp(v->name, "immediate")) {
10852 confp->chan.immediate = ast_true(v->value);
10853 } else if (!strcasecmp(v->name, "transfertobusy")) {
10854 confp->chan.transfertobusy = ast_true(v->value);
10855 } else if (!strcasecmp(v->name, "rxgain")) {
10856 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
10857 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
10859 } else if (!strcasecmp(v->name, "txgain")) {
10860 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
10861 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
10863 } else if (!strcasecmp(v->name, "tonezone")) {
10864 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
10865 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
10867 } else if (!strcasecmp(v->name, "callerid")) {
10868 if (!strcasecmp(v->value, "asreceived")) {
10869 confp->chan.cid_num[0] = '\0';
10870 confp->chan.cid_name[0] = '\0';
10871 } else {
10872 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
10874 } else if (!strcasecmp(v->name, "fullname")) {
10875 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
10876 } else if (!strcasecmp(v->name, "cid_number")) {
10877 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
10878 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
10879 confp->chan.dahditrcallerid = ast_true(v->value);
10880 } else if (!strcasecmp(v->name, "restrictcid")) {
10881 confp->chan.restrictcid = ast_true(v->value);
10882 } else if (!strcasecmp(v->name, "usecallingpres")) {
10883 confp->chan.use_callingpres = ast_true(v->value);
10884 } else if (!strcasecmp(v->name, "accountcode")) {
10885 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
10886 } else if (!strcasecmp(v->name, "amaflags")) {
10887 y = ast_cdr_amaflags2int(v->value);
10888 if (y < 0)
10889 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
10890 else
10891 confp->chan.amaflags = y;
10892 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
10893 confp->chan.polarityonanswerdelay = atoi(v->value);
10894 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
10895 confp->chan.answeronpolarityswitch = ast_true(v->value);
10896 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
10897 confp->chan.hanguponpolarityswitch = ast_true(v->value);
10898 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
10899 confp->chan.sendcalleridafter = atoi(v->value);
10900 } else if (!reload){
10901 if (!strcasecmp(v->name, "signalling")) {
10902 confp->chan.outsigmod = -1;
10903 if (!strcasecmp(v->value, "em")) {
10904 confp->chan.sig = SIG_EM;
10905 } else if (!strcasecmp(v->value, "em_e1")) {
10906 confp->chan.sig = SIG_EM_E1;
10907 } else if (!strcasecmp(v->value, "em_w")) {
10908 confp->chan.sig = SIG_EMWINK;
10909 confp->chan.radio = 0;
10910 } else if (!strcasecmp(v->value, "fxs_ls")) {
10911 confp->chan.sig = SIG_FXSLS;
10912 confp->chan.radio = 0;
10913 } else if (!strcasecmp(v->value, "fxs_gs")) {
10914 confp->chan.sig = SIG_FXSGS;
10915 confp->chan.radio = 0;
10916 } else if (!strcasecmp(v->value, "fxs_ks")) {
10917 confp->chan.sig = SIG_FXSKS;
10918 confp->chan.radio = 0;
10919 } else if (!strcasecmp(v->value, "fxo_ls")) {
10920 confp->chan.sig = SIG_FXOLS;
10921 confp->chan.radio = 0;
10922 } else if (!strcasecmp(v->value, "fxo_gs")) {
10923 confp->chan.sig = SIG_FXOGS;
10924 confp->chan.radio = 0;
10925 } else if (!strcasecmp(v->value, "fxo_ks")) {
10926 confp->chan.sig = SIG_FXOKS;
10927 confp->chan.radio = 0;
10928 } else if (!strcasecmp(v->value, "fxs_rx")) {
10929 confp->chan.sig = SIG_FXSKS;
10930 confp->chan.radio = 1;
10931 } else if (!strcasecmp(v->value, "fxo_rx")) {
10932 confp->chan.sig = SIG_FXOLS;
10933 confp->chan.radio = 1;
10934 } else if (!strcasecmp(v->value, "fxs_tx")) {
10935 confp->chan.sig = SIG_FXSLS;
10936 confp->chan.radio = 1;
10937 } else if (!strcasecmp(v->value, "fxo_tx")) {
10938 confp->chan.sig = SIG_FXOGS;
10939 confp->chan.radio = 1;
10940 } else if (!strcasecmp(v->value, "em_rx")) {
10941 confp->chan.sig = SIG_EM;
10942 confp->chan.radio = 1;
10943 } else if (!strcasecmp(v->value, "em_tx")) {
10944 confp->chan.sig = SIG_EM;
10945 confp->chan.radio = 1;
10946 } else if (!strcasecmp(v->value, "em_rxtx")) {
10947 confp->chan.sig = SIG_EM;
10948 confp->chan.radio = 2;
10949 } else if (!strcasecmp(v->value, "em_txrx")) {
10950 confp->chan.sig = SIG_EM;
10951 confp->chan.radio = 2;
10952 } else if (!strcasecmp(v->value, "sf")) {
10953 confp->chan.sig = SIG_SF;
10954 confp->chan.radio = 0;
10955 } else if (!strcasecmp(v->value, "sf_w")) {
10956 confp->chan.sig = SIG_SFWINK;
10957 confp->chan.radio = 0;
10958 } else if (!strcasecmp(v->value, "sf_featd")) {
10959 confp->chan.sig = SIG_FEATD;
10960 confp->chan.radio = 0;
10961 } else if (!strcasecmp(v->value, "sf_featdmf")) {
10962 confp->chan.sig = SIG_FEATDMF;
10963 confp->chan.radio = 0;
10964 } else if (!strcasecmp(v->value, "sf_featb")) {
10965 confp->chan.sig = SIG_SF_FEATB;
10966 confp->chan.radio = 0;
10967 } else if (!strcasecmp(v->value, "sf")) {
10968 confp->chan.sig = SIG_SF;
10969 confp->chan.radio = 0;
10970 } else if (!strcasecmp(v->value, "sf_rx")) {
10971 confp->chan.sig = SIG_SF;
10972 confp->chan.radio = 1;
10973 } else if (!strcasecmp(v->value, "sf_tx")) {
10974 confp->chan.sig = SIG_SF;
10975 confp->chan.radio = 1;
10976 } else if (!strcasecmp(v->value, "sf_rxtx")) {
10977 confp->chan.sig = SIG_SF;
10978 confp->chan.radio = 2;
10979 } else if (!strcasecmp(v->value, "sf_txrx")) {
10980 confp->chan.sig = SIG_SF;
10981 confp->chan.radio = 2;
10982 } else if (!strcasecmp(v->value, "featd")) {
10983 confp->chan.sig = SIG_FEATD;
10984 confp->chan.radio = 0;
10985 } else if (!strcasecmp(v->value, "featdmf")) {
10986 confp->chan.sig = SIG_FEATDMF;
10987 confp->chan.radio = 0;
10988 } else if (!strcasecmp(v->value, "featdmf_ta")) {
10989 confp->chan.sig = SIG_FEATDMF_TA;
10990 confp->chan.radio = 0;
10991 } else if (!strcasecmp(v->value, "e911")) {
10992 confp->chan.sig = SIG_E911;
10993 confp->chan.radio = 0;
10994 } else if (!strcasecmp(v->value, "fgccama")) {
10995 confp->chan.sig = SIG_FGC_CAMA;
10996 confp->chan.radio = 0;
10997 } else if (!strcasecmp(v->value, "fgccamamf")) {
10998 confp->chan.sig = SIG_FGC_CAMAMF;
10999 confp->chan.radio = 0;
11000 } else if (!strcasecmp(v->value, "featb")) {
11001 confp->chan.sig = SIG_FEATB;
11002 confp->chan.radio = 0;
11003 #ifdef HAVE_PRI
11004 } else if (!strcasecmp(v->value, "pri_net")) {
11005 confp->chan.radio = 0;
11006 confp->chan.sig = SIG_PRI;
11007 confp->pri.nodetype = PRI_NETWORK;
11008 } else if (!strcasecmp(v->value, "pri_cpe")) {
11009 confp->chan.sig = SIG_PRI;
11010 confp->chan.radio = 0;
11011 confp->pri.nodetype = PRI_CPE;
11012 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11013 confp->chan.sig = SIG_GR303FXOKS;
11014 confp->chan.radio = 0;
11015 confp->pri.nodetype = PRI_NETWORK;
11016 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11017 confp->chan.sig = SIG_GR303FXSKS;
11018 confp->chan.radio = 0;
11019 confp->pri.nodetype = PRI_CPE;
11020 #endif
11021 } else {
11022 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11024 } else if (!strcasecmp(v->name, "outsignalling")) {
11025 if (!strcasecmp(v->value, "em")) {
11026 confp->chan.outsigmod = SIG_EM;
11027 } else if (!strcasecmp(v->value, "em_e1")) {
11028 confp->chan.outsigmod = SIG_EM_E1;
11029 } else if (!strcasecmp(v->value, "em_w")) {
11030 confp->chan.outsigmod = SIG_EMWINK;
11031 } else if (!strcasecmp(v->value, "sf")) {
11032 confp->chan.outsigmod = SIG_SF;
11033 } else if (!strcasecmp(v->value, "sf_w")) {
11034 confp->chan.outsigmod = SIG_SFWINK;
11035 } else if (!strcasecmp(v->value, "sf_featd")) {
11036 confp->chan.outsigmod = SIG_FEATD;
11037 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11038 confp->chan.outsigmod = SIG_FEATDMF;
11039 } else if (!strcasecmp(v->value, "sf_featb")) {
11040 confp->chan.outsigmod = SIG_SF_FEATB;
11041 } else if (!strcasecmp(v->value, "sf")) {
11042 confp->chan.outsigmod = SIG_SF;
11043 } else if (!strcasecmp(v->value, "featd")) {
11044 confp->chan.outsigmod = SIG_FEATD;
11045 } else if (!strcasecmp(v->value, "featdmf")) {
11046 confp->chan.outsigmod = SIG_FEATDMF;
11047 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11048 confp->chan.outsigmod = SIG_FEATDMF_TA;
11049 } else if (!strcasecmp(v->value, "e911")) {
11050 confp->chan.outsigmod = SIG_E911;
11051 } else if (!strcasecmp(v->value, "fgccama")) {
11052 confp->chan.outsigmod = SIG_FGC_CAMA;
11053 } else if (!strcasecmp(v->value, "fgccamamf")) {
11054 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11055 } else if (!strcasecmp(v->value, "featb")) {
11056 confp->chan.outsigmod = SIG_FEATB;
11057 } else {
11058 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11060 #ifdef HAVE_PRI
11061 } else if (!strcasecmp(v->name, "pridialplan")) {
11062 if (!strcasecmp(v->value, "national")) {
11063 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11064 } else if (!strcasecmp(v->value, "unknown")) {
11065 confp->pri.dialplan = PRI_UNKNOWN + 1;
11066 } else if (!strcasecmp(v->value, "private")) {
11067 confp->pri.dialplan = PRI_PRIVATE + 1;
11068 } else if (!strcasecmp(v->value, "international")) {
11069 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11070 } else if (!strcasecmp(v->value, "local")) {
11071 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11072 } else if (!strcasecmp(v->value, "dynamic")) {
11073 confp->pri.dialplan = -1;
11074 } else {
11075 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11077 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11078 if (!strcasecmp(v->value, "national")) {
11079 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11080 } else if (!strcasecmp(v->value, "unknown")) {
11081 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11082 } else if (!strcasecmp(v->value, "private")) {
11083 confp->pri.localdialplan = PRI_PRIVATE + 1;
11084 } else if (!strcasecmp(v->value, "international")) {
11085 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11086 } else if (!strcasecmp(v->value, "local")) {
11087 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11088 } else if (!strcasecmp(v->value, "dynamic")) {
11089 confp->pri.localdialplan = -1;
11090 } else {
11091 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11093 } else if (!strcasecmp(v->name, "switchtype")) {
11094 if (!strcasecmp(v->value, "national"))
11095 confp->pri.switchtype = PRI_SWITCH_NI2;
11096 else if (!strcasecmp(v->value, "ni1"))
11097 confp->pri.switchtype = PRI_SWITCH_NI1;
11098 else if (!strcasecmp(v->value, "dms100"))
11099 confp->pri.switchtype = PRI_SWITCH_DMS100;
11100 else if (!strcasecmp(v->value, "4ess"))
11101 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11102 else if (!strcasecmp(v->value, "5ess"))
11103 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11104 else if (!strcasecmp(v->value, "euroisdn"))
11105 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11106 else if (!strcasecmp(v->value, "qsig"))
11107 confp->pri.switchtype = PRI_SWITCH_QSIG;
11108 else {
11109 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11110 return -1;
11112 } else if (!strcasecmp(v->name, "nsf")) {
11113 if (!strcasecmp(v->value, "sdn"))
11114 confp->pri.nsf = PRI_NSF_SDN;
11115 else if (!strcasecmp(v->value, "megacom"))
11116 confp->pri.nsf = PRI_NSF_MEGACOM;
11117 else if (!strcasecmp(v->value, "tollfreemegacom"))
11118 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11119 else if (!strcasecmp(v->value, "accunet"))
11120 confp->pri.nsf = PRI_NSF_ACCUNET;
11121 else if (!strcasecmp(v->value, "none"))
11122 confp->pri.nsf = PRI_NSF_NONE;
11123 else {
11124 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11125 confp->pri.nsf = PRI_NSF_NONE;
11127 } else if (!strcasecmp(v->name, "priindication")) {
11128 if (!strcasecmp(v->value, "outofband"))
11129 confp->chan.priindication_oob = 1;
11130 else if (!strcasecmp(v->value, "inband"))
11131 confp->chan.priindication_oob = 0;
11132 else
11133 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11134 v->value, v->lineno);
11135 } else if (!strcasecmp(v->name, "priexclusive")) {
11136 confp->chan.priexclusive = ast_true(v->value);
11137 } else if (!strcasecmp(v->name, "internationalprefix")) {
11138 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11139 } else if (!strcasecmp(v->name, "nationalprefix")) {
11140 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11141 } else if (!strcasecmp(v->name, "localprefix")) {
11142 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11143 } else if (!strcasecmp(v->name, "privateprefix")) {
11144 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11145 } else if (!strcasecmp(v->name, "unknownprefix")) {
11146 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11147 } else if (!strcasecmp(v->name, "resetinterval")) {
11148 if (!strcasecmp(v->value, "never"))
11149 confp->pri.resetinterval = -1;
11150 else if (atoi(v->value) >= 60)
11151 confp->pri.resetinterval = atoi(v->value);
11152 else
11153 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11154 v->value, v->lineno);
11155 } else if (!strcasecmp(v->name, "minunused")) {
11156 confp->pri.minunused = atoi(v->value);
11157 } else if (!strcasecmp(v->name, "minidle")) {
11158 confp->pri.minidle = atoi(v->value);
11159 } else if (!strcasecmp(v->name, "idleext")) {
11160 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11161 } else if (!strcasecmp(v->name, "idledial")) {
11162 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11163 } else if (!strcasecmp(v->name, "overlapdial")) {
11164 confp->pri.overlapdial = ast_true(v->value);
11165 #ifdef HAVE_PRI_INBANDRELEASE
11166 } else if (!strcasecmp(v->name, "inbandrelease")) {
11167 confp->pri.inbandrelease = ast_true(v->value);
11168 #endif
11169 } else if (!strcasecmp(v->name, "pritimer")) {
11170 #ifdef PRI_GETSET_TIMERS
11171 char *timerc, *c;
11172 int timer, timeridx;
11173 c = v->value;
11174 timerc = strsep(&c, ",");
11175 if (timerc) {
11176 timer = atoi(c);
11177 if (!timer)
11178 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11179 else {
11180 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11181 pritimers[timeridx] = timer;
11182 else
11183 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11185 } else
11186 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11188 } else if (!strcasecmp(v->name, "facilityenable")) {
11189 confp->pri.facilityenable = ast_true(v->value);
11190 #endif /* PRI_GETSET_TIMERS */
11191 #endif /* HAVE_PRI */
11192 } else if (!strcasecmp(v->name, "cadence")) {
11193 /* setup to scan our argument */
11194 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11195 int i;
11196 struct dahdi_ring_cadence new_cadence;
11197 int cid_location = -1;
11198 int firstcadencepos = 0;
11199 char original_args[80];
11200 int cadence_is_ok = 1;
11202 ast_copy_string(original_args, v->value, sizeof(original_args));
11203 /* 16 cadences allowed (8 pairs) */
11204 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]);
11206 /* Cadence must be even (on/off) */
11207 if (element_count % 2 == 1) {
11208 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11209 cadence_is_ok = 0;
11212 /* Ring cadences cannot be negative */
11213 for (i = 0; i < element_count; i++) {
11214 if (c[i] == 0) {
11215 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11216 cadence_is_ok = 0;
11217 break;
11218 } else if (c[i] < 0) {
11219 if (i % 2 == 1) {
11220 /* Silence duration, negative possibly okay */
11221 if (cid_location == -1) {
11222 cid_location = i;
11223 c[i] *= -1;
11224 } else {
11225 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11226 cadence_is_ok = 0;
11227 break;
11229 } else {
11230 if (firstcadencepos == 0) {
11231 firstcadencepos = i; /* only recorded to avoid duplicate specification */
11232 /* duration will be passed negative to the DAHDI driver */
11233 } else {
11234 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11235 cadence_is_ok = 0;
11236 break;
11242 /* Substitute our scanned cadence */
11243 for (i = 0; i < 16; i++) {
11244 new_cadence.ringcadence[i] = c[i];
11247 if (cadence_is_ok) {
11248 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11249 if (element_count < 2) {
11250 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11251 } else {
11252 if (cid_location == -1) {
11253 /* user didn't say; default to first pause */
11254 cid_location = 1;
11255 } else {
11256 /* convert element_index to cidrings value */
11257 cid_location = (cid_location + 1) / 2;
11259 /* ---we like their cadence; try to install it--- */
11260 if (!user_has_defined_cadences++)
11261 /* this is the first user-defined cadence; clear the default user cadences */
11262 num_cadence = 0;
11263 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11264 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11265 else {
11266 cadences[num_cadence] = new_cadence;
11267 cidrings[num_cadence++] = cid_location;
11268 if (option_verbose > 2)
11269 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11273 } else if (!strcasecmp(v->name, "ringtimeout")) {
11274 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11275 } else if (!strcasecmp(v->name, "prewink")) {
11276 confp->timing.prewinktime = atoi(v->value);
11277 } else if (!strcasecmp(v->name, "preflash")) {
11278 confp->timing.preflashtime = atoi(v->value);
11279 } else if (!strcasecmp(v->name, "wink")) {
11280 confp->timing.winktime = atoi(v->value);
11281 } else if (!strcasecmp(v->name, "flash")) {
11282 confp->timing.flashtime = atoi(v->value);
11283 } else if (!strcasecmp(v->name, "start")) {
11284 confp->timing.starttime = atoi(v->value);
11285 } else if (!strcasecmp(v->name, "rxwink")) {
11286 confp->timing.rxwinktime = atoi(v->value);
11287 } else if (!strcasecmp(v->name, "rxflash")) {
11288 confp->timing.rxflashtime = atoi(v->value);
11289 } else if (!strcasecmp(v->name, "debounce")) {
11290 confp->timing.debouncetime = atoi(v->value);
11291 } else if (!strcasecmp(v->name, "toneduration")) {
11292 int toneduration;
11293 int ctlfd;
11294 int res;
11295 DAHDI_DIAL_PARAMS dps;
11297 #ifdef HAVE_ZAPTEL
11298 ctlfd = open("/dev/zap/ctl", O_RDWR);
11299 #else
11300 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11301 #endif
11303 if (ctlfd == -1) {
11304 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11305 return -1;
11308 toneduration = atoi(v->value);
11309 if (toneduration > -1) {
11310 memset(&dps, 0, sizeof(dps));
11312 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11313 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11314 if (res < 0) {
11315 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11316 return -1;
11319 close(ctlfd);
11320 } else if (!strcasecmp(v->name, "defaultcic")) {
11321 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11322 } else if (!strcasecmp(v->name, "defaultozz")) {
11323 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11325 } else if (!skipchannels)
11326 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11328 if (dahdichan[0]) {
11329 /* The user has set 'dahdichan' */
11330 /*< \todo pass proper line number instead of 0 */
11331 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11332 return -1;
11335 /*< \todo why check for the pseudo in the per-channel section.
11336 * Any actual use for manual setup of the pseudo channel? */
11337 if (!found_pseudo && reload == 0) {
11338 /* Make sure pseudo isn't a member of any groups if
11339 we're automatically making it. */
11341 confp->chan.group = 0;
11342 confp->chan.callgroup = 0;
11343 confp->chan.pickupgroup = 0;
11345 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11347 if (tmp) {
11348 if (option_verbose > 2)
11349 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11350 } else {
11351 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11354 return 0;
11357 static int setup_dahdi(int reload)
11359 struct ast_config *cfg;
11360 struct ast_variable *v;
11361 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11362 int res;
11364 #ifdef HAVE_PRI
11365 char *c;
11366 int spanno;
11367 int i, x;
11368 int logicalspan;
11369 int trunkgroup;
11370 int dchannels[NUM_DCHANS];
11371 #endif
11373 #ifdef HAVE_ZAPTEL
11374 cfg = ast_config_load("zapata.conf");
11375 #else
11376 cfg = ast_config_load(config);
11377 #endif
11378 /* Error if we have no config file... */
11379 if (!cfg) {
11380 ast_log(LOG_ERROR, "Unable to load either config %s or zapata.conf\n", config);
11381 return 0;
11384 /* It's a little silly to lock it, but we mind as well just to be sure */
11385 ast_mutex_lock(&iflock);
11386 #ifdef HAVE_PRI
11387 if (!reload) {
11388 /* Process trunkgroups first */
11389 v = ast_variable_browse(cfg, "trunkgroups");
11390 while (v) {
11391 if (!strcasecmp(v->name, "trunkgroup")) {
11392 trunkgroup = atoi(v->value);
11393 if (trunkgroup > 0) {
11394 if ((c = strchr(v->value, ','))) {
11395 i = 0;
11396 memset(dchannels, 0, sizeof(dchannels));
11397 while (c && (i < NUM_DCHANS)) {
11398 dchannels[i] = atoi(c + 1);
11399 if (dchannels[i] < 0) {
11400 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);
11401 } else
11402 i++;
11403 c = strchr(c + 1, ',');
11405 if (i) {
11406 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11407 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);
11408 } else if (option_verbose > 1)
11409 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");
11410 } else
11411 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11412 } else
11413 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11414 } else
11415 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11416 } else if (!strcasecmp(v->name, "spanmap")) {
11417 spanno = atoi(v->value);
11418 if (spanno > 0) {
11419 if ((c = strchr(v->value, ','))) {
11420 trunkgroup = atoi(c + 1);
11421 if (trunkgroup > 0) {
11422 if ((c = strchr(c + 1, ',')))
11423 logicalspan = atoi(c + 1);
11424 else
11425 logicalspan = 0;
11426 if (logicalspan >= 0) {
11427 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11428 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11429 } else if (option_verbose > 1)
11430 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11431 } else
11432 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);
11433 } else
11434 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11435 } else
11436 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11437 } else
11438 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11439 } else {
11440 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11442 v = v->next;
11445 #endif
11447 /* Copy the default jb config over global_jbconf */
11448 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11450 v = ast_variable_browse(cfg, "channels");
11451 res = process_dahdi(&conf, "", v, reload, 0);
11452 ast_mutex_unlock(&iflock);
11453 ast_config_destroy(cfg);
11454 if (res)
11455 return res;
11456 cfg = ast_config_load("users.conf");
11457 if (cfg) {
11458 char *cat;
11459 const char *chans;
11460 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11461 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11462 if (!strcasecmp(cat, "general"))
11463 continue;
11464 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11465 if (!ast_strlen_zero(chans)) {
11466 struct dahdi_chan_conf sect_conf;
11467 memcpy(&sect_conf, &conf, sizeof(sect_conf));
11469 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11472 ast_config_destroy(cfg);
11474 #ifdef HAVE_PRI
11475 if (!reload) {
11476 for (x = 0; x < NUM_SPANS; x++) {
11477 if (pris[x].pvts[0]) {
11478 if (start_pri(pris + x)) {
11479 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11480 return -1;
11481 } else if (option_verbose > 1)
11482 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11486 #endif
11487 /* And start the monitor for the first time */
11488 restart_monitor();
11489 return 0;
11492 static int load_module(void)
11494 int res;
11496 #ifdef HAVE_PRI
11497 int y,i;
11498 memset(pris, 0, sizeof(pris));
11499 for (y = 0; y < NUM_SPANS; y++) {
11500 ast_mutex_init(&pris[y].lock);
11501 pris[y].offset = -1;
11502 pris[y].master = AST_PTHREADT_NULL;
11503 for (i = 0; i < NUM_DCHANS; i++)
11504 pris[y].fds[i] = -1;
11506 pri_set_error(dahdi_pri_error);
11507 pri_set_message(dahdi_pri_message);
11508 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11509 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11510 #endif
11511 res = setup_dahdi(0);
11512 /* Make sure we can register our DAHDI channel type */
11513 if (res)
11514 return AST_MODULE_LOAD_DECLINE;
11515 if (ast_channel_register(&dahdi_tech)) {
11516 ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
11517 __unload_module();
11518 return -1;
11520 #ifdef HAVE_PRI
11521 ast_string_field_init(&inuse, 16);
11522 ast_string_field_set(&inuse, name, "GR-303InUse");
11523 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11524 #endif
11525 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11527 memset(round_robin, 0, sizeof(round_robin));
11528 ast_manager_register("DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
11529 ast_manager_register("DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
11530 ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
11531 ast_manager_register("DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
11532 ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
11533 ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
11534 ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
11536 return res;
11539 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11541 #define END_SILENCE_LEN 400
11542 #define HEADER_MS 50
11543 #define TRAILER_MS 5
11544 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11545 #define ASCII_BYTES_PER_CHAR 80
11547 unsigned char *buf,*mybuf;
11548 struct dahdi_pvt *p = c->tech_pvt;
11549 struct pollfd fds[1];
11550 int size,res,fd,len,x;
11551 int bytes=0;
11552 /* Initial carrier (imaginary) */
11553 float cr = 1.0;
11554 float ci = 0.0;
11555 float scont = 0.0;
11556 int index;
11558 index = dahdi_get_index(c, p, 0);
11559 if (index < 0) {
11560 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11561 return -1;
11563 if (!text[0]) return(0); /* if nothing to send, dont */
11564 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
11565 if (p->mate)
11566 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11567 else
11568 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11569 if (!buf)
11570 return -1;
11571 mybuf = buf;
11572 if (p->mate) {
11573 int codec = AST_LAW(p);
11574 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
11575 PUT_CLID_MARKMS;
11577 /* Put actual message */
11578 for (x = 0; text[x]; x++) {
11579 PUT_CLID(text[x]);
11581 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
11582 PUT_CLID_MARKMS;
11584 len = bytes;
11585 buf = mybuf;
11586 } else {
11587 len = tdd_generate(p->tdd, buf, text);
11588 if (len < 1) {
11589 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11590 free(mybuf);
11591 return -1;
11594 memset(buf + len, 0x7f, END_SILENCE_LEN);
11595 len += END_SILENCE_LEN;
11596 fd = p->subs[index].dfd;
11597 while (len) {
11598 if (ast_check_hangup(c)) {
11599 free(mybuf);
11600 return -1;
11602 size = len;
11603 if (size > READ_SIZE)
11604 size = READ_SIZE;
11605 fds[0].fd = fd;
11606 fds[0].events = POLLOUT | POLLPRI;
11607 fds[0].revents = 0;
11608 res = poll(fds, 1, -1);
11609 if (!res) {
11610 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11611 continue;
11613 /* if got exception */
11614 if (fds[0].revents & POLLPRI) {
11615 ast_free(mybuf);
11616 return -1;
11618 if (!(fds[0].revents & POLLOUT)) {
11619 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11620 continue;
11622 res = write(fd, buf, size);
11623 if (res != size) {
11624 if (res == -1) {
11625 free(mybuf);
11626 return -1;
11628 if (option_debug)
11629 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11630 break;
11632 len -= size;
11633 buf += size;
11635 free(mybuf);
11636 return(0);
11640 static int reload(void)
11642 int res = 0;
11644 res = setup_dahdi(1);
11645 if (res) {
11646 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
11647 return -1;
11649 return 0;
11652 /* This is a workaround so that menuselect displays a proper description
11653 * AST_MODULE_INFO(, , "DAHDI Telephony"
11656 #ifdef DAHDI_PRI
11657 #define tdesc "DAHDI Telephony w/PRI"
11658 #else
11659 #define tdesc "DAHDI Telephony"
11660 #endif
11662 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
11663 .load = load_module,
11664 .unload = unload_module,
11665 .reload = reload,