make some more changes to the dahdi/zap channel name support stuff to ensure allthe...
[asterisk-bristuff.git] / channels / chan_dahdi.c
blobe1acd1bd382ce10cb2b2626c6cabf38e3c799330
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 #ifndef DAHDI_TONEDETECT
120 /* Work around older code with no tone detect */
121 #define DAHDI_EVENT_DTMFDOWN 0
122 #define DAHDI_EVENT_DTMFUP 0
123 #endif
125 /* define this to send PRI user-user information elements */
126 #undef SUPPORT_USERUSER
128 /*!
129 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
130 * the user hangs up to reset the state machine so ring works properly.
131 * This is used to be able to support kewlstart by putting the zhone in
132 * groundstart mode since their forward disconnect supervision is entirely
133 * broken even though their documentation says it isn't and their support
134 * is entirely unwilling to provide any assistance with their channel banks
135 * even though their web site says they support their products for life.
137 /* #define ZHONE_HACK */
139 /*! \note
140 * Define if you want to check the hook state for an FXO (FXS signalled) interface
141 * before dialing on it. Certain FXO interfaces always think they're out of
142 * service with this method however.
144 /* #define DAHDI_CHECK_HOOKSTATE */
146 /*! \brief Typically, how many rings before we should send Caller*ID */
147 #define DEFAULT_CIDRINGS 1
149 #define CHANNEL_PSEUDO -12
151 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
153 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
154 #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))
156 static const char tdesc[] = "DAHDI Telephony Driver"
157 #ifdef HAVE_PRI
158 " w/PRI"
159 #endif
162 #define SIG_EM DAHDI_SIG_EM
163 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
164 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
165 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
166 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
167 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
168 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
169 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
170 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
171 #define SIG_FXSLS DAHDI_SIG_FXSLS
172 #define SIG_FXSGS DAHDI_SIG_FXSGS
173 #define SIG_FXSKS DAHDI_SIG_FXSKS
174 #define SIG_FXOLS DAHDI_SIG_FXOLS
175 #define SIG_FXOGS DAHDI_SIG_FXOGS
176 #define SIG_FXOKS DAHDI_SIG_FXOKS
177 #define SIG_PRI DAHDI_SIG_CLEAR
178 #define SIG_SF DAHDI_SIG_SF
179 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
180 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
181 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
182 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
183 #define SIG_EM_E1 DAHDI_SIG_EM_E1
184 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
185 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
187 #define NUM_SPANS 32
188 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
189 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
191 #define CHAN_PSEUDO -2
193 #define DCHAN_PROVISIONED (1 << 0)
194 #define DCHAN_NOTINALARM (1 << 1)
195 #define DCHAN_UP (1 << 2)
197 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
199 static char defaultcic[64] = "";
200 static char defaultozz[64] = "";
202 static char progzone[10] = "";
204 static int distinctiveringaftercid = 0;
206 static int numbufs = 4;
208 #ifdef HAVE_PRI
209 static struct ast_channel inuse;
210 #ifdef PRI_GETSET_TIMERS
211 static int pritimers[PRI_MAX_TIMERS];
212 #endif
213 static int pridebugfd = -1;
214 static char pridebugfilename[1024] = "";
215 #endif
217 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
218 static int firstdigittimeout = 16000;
220 /*! \brief How long to wait for following digits (FXO logic) */
221 static int gendigittimeout = 8000;
223 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
224 static int matchdigittimeout = 3000;
226 /*! \brief Protect the interface list (of dahdi_pvt's) */
227 AST_MUTEX_DEFINE_STATIC(iflock);
230 static int ifcount = 0;
232 #ifdef HAVE_PRI
233 AST_MUTEX_DEFINE_STATIC(pridebugfdlock);
234 #endif
236 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
237 when it's doing something critical. */
238 AST_MUTEX_DEFINE_STATIC(monlock);
240 /*! \brief This is the thread for the monitor which checks for input on the channels
241 which are not currently in use. */
242 static pthread_t monitor_thread = AST_PTHREADT_NULL;
244 static int restart_monitor(void);
246 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);
248 static int dahdi_sendtext(struct ast_channel *c, const char *text);
250 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
251 static inline int dahdi_get_event(int fd)
253 int j;
254 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
255 return -1;
256 return j;
259 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
260 static inline int dahdi_wait_event(int fd)
262 int i, j = 0;
263 i = DAHDI_IOMUX_SIGEVENT;
264 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
265 return -1;
266 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
267 return -1;
268 return j;
271 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
272 #define READ_SIZE 160
274 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
275 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
277 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
278 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
279 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
280 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
281 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
283 struct dahdi_pvt;
285 static int ringt_base = DEFAULT_RINGT;
287 #ifdef HAVE_PRI
289 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
290 #define PRI_CHANNEL(p) ((p) & 0xff)
291 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
292 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
294 struct dahdi_pri {
295 pthread_t master; /*!< Thread of master */
296 ast_mutex_t lock; /*!< Mutex */
297 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
298 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
299 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
300 int minunused; /*!< Min # of channels to keep empty */
301 int minidle; /*!< Min # of "idling" calls to keep active */
302 int nodetype; /*!< Node type */
303 int switchtype; /*!< Type of switch to emulate */
304 int nsf; /*!< Network-Specific Facilities */
305 int dialplan; /*!< Dialing plan */
306 int localdialplan; /*!< Local dialing plan */
307 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
308 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
309 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
310 char privateprefix[20]; /*!< for private dialplans */
311 char unknownprefix[20]; /*!< for unknown dialplans */
312 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
313 int trunkgroup; /*!< What our trunkgroup is */
314 int mastertrunkgroup; /*!< What trunk group is our master */
315 int prilogicalspan; /*!< Logical span number within trunk group */
316 int numchans; /*!< Num of channels we represent */
317 int overlapdial; /*!< In overlap dialing mode */
318 int facilityenable; /*!< Enable facility IEs */
319 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
320 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
321 struct pri *pri; /*!< Currently active D-channel */
322 int debug;
323 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
324 int offset;
325 int span;
326 int resetting;
327 int resetpos;
328 #ifdef HAVE_PRI_INBANDDISCONNECT
329 unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */
330 #endif
331 time_t lastreset; /*!< time when unused channels were last reset */
332 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
333 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
334 struct dahdi_pvt *crvs; /*!< Member CRV structs */
335 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
339 static struct dahdi_pri pris[NUM_SPANS];
341 #if 0
342 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
343 #else
344 #define DEFAULT_PRI_DEBUG 0
345 #endif
347 static inline void pri_rel(struct dahdi_pri *pri)
349 ast_mutex_unlock(&pri->lock);
352 #else
353 /*! Shut up the compiler */
354 struct dahdi_pri;
355 #endif
357 #define SUB_REAL 0 /*!< Active call */
358 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
359 #define SUB_THREEWAY 2 /*!< Three-way call */
361 /* Polarity states */
362 #define POLARITY_IDLE 0
363 #define POLARITY_REV 1
366 static struct dahdi_distRings drings;
368 struct distRingData {
369 int ring[3];
371 struct ringContextData {
372 char contextData[AST_MAX_CONTEXT];
374 struct dahdi_distRings {
375 struct distRingData ringnum[3];
376 struct ringContextData ringContext[3];
379 static char *subnames[] = {
380 "Real",
381 "Callwait",
382 "Threeway"
385 struct dahdi_subchannel {
386 int dfd;
387 struct ast_channel *owner;
388 int chan;
389 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
390 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
391 unsigned int needringing:1;
392 unsigned int needbusy:1;
393 unsigned int needcongestion:1;
394 unsigned int needcallerid:1;
395 unsigned int needanswer:1;
396 unsigned int needflash:1;
397 unsigned int needhold:1;
398 unsigned int needunhold:1;
399 unsigned int linear:1;
400 unsigned int inthreeway:1;
401 DAHDI_CONFINFO curconf;
404 #define CONF_USER_REAL (1 << 0)
405 #define CONF_USER_THIRDCALL (1 << 1)
407 #define MAX_SLAVES 4
409 static struct dahdi_pvt {
410 ast_mutex_t lock;
411 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
412 /*!< Up to three channels can be associated with this call */
414 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
415 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
416 DAHDI_CONFINFO saveconf; /*!< Saved conference info */
418 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
419 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
420 int inconference; /*!< If our real should be in the conference */
422 int sig; /*!< Signalling style */
423 int radio; /*!< radio type */
424 int outsigmod; /*!< Outbound Signalling style (modifier) */
425 int oprmode; /*!< "Operator Services" mode */
426 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
427 float rxgain;
428 float txgain;
429 int tonezone; /*!< tone zone for this chan, or -1 for default */
430 struct dahdi_pvt *next; /*!< Next channel in list */
431 struct dahdi_pvt *prev; /*!< Prev channel in list */
433 /* flags */
434 unsigned int adsi:1;
435 unsigned int answeronpolarityswitch:1;
436 unsigned int busydetect:1;
437 unsigned int callreturn:1;
438 unsigned int callwaiting:1;
439 unsigned int callwaitingcallerid:1;
440 unsigned int cancallforward:1;
441 unsigned int canpark:1;
442 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
443 unsigned int destroy:1;
444 unsigned int didtdd:1; /*!< flag to say its done it once */
445 unsigned int dialednone:1;
446 unsigned int dialing:1;
447 unsigned int digital:1;
448 unsigned int dnd:1;
449 unsigned int echobreak:1;
450 unsigned int echocanbridged:1;
451 unsigned int echocanon:1;
452 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
453 unsigned int firstradio:1;
454 unsigned int hanguponpolarityswitch:1;
455 unsigned int hardwaredtmf:1;
456 unsigned int hidecallerid:1;
457 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
458 unsigned int ignoredtmf:1;
459 unsigned int immediate:1; /*!< Answer before getting digits? */
460 unsigned int inalarm:1;
461 unsigned int unknown_alarm:1;
462 unsigned int mate:1; /*!< flag to say its in MATE mode */
463 unsigned int outgoing:1;
464 unsigned int overlapdial:1;
465 unsigned int permcallwaiting:1;
466 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
467 unsigned int priindication_oob:1;
468 unsigned int priexclusive:1;
469 unsigned int pulse:1;
470 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
471 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
472 unsigned int threewaycalling:1;
473 unsigned int transfer:1;
474 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
475 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
476 unsigned int usedistinctiveringdetection:1;
477 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
478 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
479 #if defined(HAVE_PRI)
480 unsigned int alerting:1;
481 unsigned int alreadyhungup:1;
482 unsigned int isidlecall:1;
483 unsigned int proceeding:1;
484 unsigned int progress:1;
485 unsigned int resetting:1;
486 unsigned int setup_ack:1;
487 #endif
488 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
489 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
491 struct dahdi_distRings drings;
493 char context[AST_MAX_CONTEXT];
494 char defcontext[AST_MAX_CONTEXT];
495 char exten[AST_MAX_EXTENSION];
496 char language[MAX_LANGUAGE];
497 char mohinterpret[MAX_MUSICCLASS];
498 char mohsuggest[MAX_MUSICCLASS];
499 #ifdef PRI_ANI
500 char cid_ani[AST_MAX_EXTENSION];
501 #endif
502 char cid_num[AST_MAX_EXTENSION];
503 int cid_ton; /*!< Type Of Number (TON) */
504 char cid_name[AST_MAX_EXTENSION];
505 char lastcid_num[AST_MAX_EXTENSION];
506 char lastcid_name[AST_MAX_EXTENSION];
507 char *origcid_num; /*!< malloced original callerid */
508 char *origcid_name; /*!< malloced original callerid */
509 char callwait_num[AST_MAX_EXTENSION];
510 char callwait_name[AST_MAX_EXTENSION];
511 char rdnis[AST_MAX_EXTENSION];
512 char dnid[AST_MAX_EXTENSION];
513 ast_group_t group;
514 int law;
515 int confno; /*!< Our conference */
516 int confusers; /*!< Who is using our conference */
517 int propconfno; /*!< Propagated conference number */
518 ast_group_t callgroup;
519 ast_group_t pickupgroup;
520 int channel; /*!< Channel Number or CRV */
521 int span; /*!< Span number */
522 time_t guardtime; /*!< Must wait this much time before using for new call */
523 int cid_signalling; /*!< CID signalling type bell202 or v23 */
524 int cid_start; /*!< CID start indicator, polarity or ring */
525 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
526 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
527 int cidcwexpire; /*!< When to expire our muting for CID/CW */
528 unsigned char *cidspill;
529 int cidpos;
530 int cidlen;
531 int ringt;
532 int ringt_base;
533 int stripmsd;
534 int callwaitcas;
535 int callwaitrings;
536 int echocancel;
537 int echotraining;
538 char echorest[20];
539 int busycount;
540 int busy_tonelength;
541 int busy_quietlength;
542 int callprogress;
543 struct timeval flashtime; /*!< Last flash-hook time */
544 struct ast_dsp *dsp;
545 int cref; /*!< Call reference number */
546 DAHDI_DIAL_OPERATION dop;
547 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
548 char finaldial[64];
549 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
550 int amaflags; /*!< AMA Flags */
551 struct tdd_state *tdd; /*!< TDD flag */
552 char call_forward[AST_MAX_EXTENSION];
553 char mailbox[AST_MAX_EXTENSION];
554 char dialdest[256];
555 int onhooktime;
556 int msgstate;
557 int distinctivering; /*!< Which distinctivering to use */
558 int cidrings; /*!< Which ring to deliver CID on */
559 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
560 int fake_event;
561 int polarityonanswerdelay;
562 struct timeval polaritydelaytv;
563 int sendcalleridafter;
564 #ifdef HAVE_PRI
565 struct dahdi_pri *pri;
566 struct dahdi_pvt *bearer;
567 struct dahdi_pvt *realcall;
568 q931_call *call;
569 int prioffset;
570 int logicalspan;
571 #endif
572 int polarity;
573 int dsp_features;
574 char begindigit;
575 } *iflist = NULL, *ifend = NULL;
577 /*! \brief Channel configuration from chan_dahdi.conf .
578 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
579 * Generally there is a field here for every possible configuration item.
581 * The state of fields is saved along the parsing and whenever a 'channel'
582 * statement is reached, the current dahdi_chan_conf is used to configure the
583 * channel (struct dahdi_pvt)
585 * @seealso dahdi_chan_init for the default values.
587 struct dahdi_chan_conf {
588 struct dahdi_pvt chan;
589 #ifdef HAVE_PRI
590 struct dahdi_pri pri;
591 #endif
592 DAHDI_PARAMS timing;
594 char smdi_port[SMDI_MAX_FILENAME_LEN];
597 /** returns a new dahdi_chan_conf with default values (by-value) */
598 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
599 /* recall that if a field is not included here it is initialized
600 * to 0 or equivalent
602 struct dahdi_chan_conf conf = {
603 #ifdef HAVE_PRI
604 .pri = {
605 .nsf = PRI_NSF_NONE,
606 .switchtype = PRI_SWITCH_NI2,
607 .dialplan = PRI_NATIONAL_ISDN + 1,
608 .localdialplan = PRI_NATIONAL_ISDN + 1,
609 .nodetype = PRI_CPE,
611 .minunused = 2,
612 .idleext = "",
613 .idledial = "",
614 .internationalprefix = "",
615 .nationalprefix = "",
616 .localprefix = "",
617 .privateprefix = "",
618 .unknownprefix = "",
620 .resetinterval = 3600
622 #endif
623 .chan = {
624 .context = "default",
625 .cid_num = "",
626 .cid_name = "",
627 .mohinterpret = "default",
628 .mohsuggest = "",
629 .transfertobusy = 1,
631 .cid_signalling = CID_SIG_BELL,
632 .cid_start = CID_START_RING,
633 .dahditrcallerid = 0,
634 .use_callerid = 1,
635 .sig = -1,
636 .outsigmod = -1,
638 .tonezone = -1,
640 .echocancel = 1,
642 .busycount = 3,
644 .accountcode = "",
646 .mailbox = "",
649 .polarityonanswerdelay = 600,
651 .sendcalleridafter = DEFAULT_CIDRINGS
653 .timing = {
654 .prewinktime = -1,
655 .preflashtime = -1,
656 .winktime = -1,
657 .flashtime = -1,
658 .starttime = -1,
659 .rxwinktime = -1,
660 .rxflashtime = -1,
661 .debouncetime = -1
663 .smdi_port = "/dev/ttyS0",
666 return conf;
670 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
671 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
672 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
673 static int dahdi_sendtext(struct ast_channel *c, const char *text);
674 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
675 static int dahdi_hangup(struct ast_channel *ast);
676 static int dahdi_answer(struct ast_channel *ast);
677 static struct ast_frame *dahdi_read(struct ast_channel *ast);
678 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
679 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
680 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
681 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
682 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
683 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
685 static const struct ast_channel_tech dahdi_tech = {
686 .type = "DAHDI",
687 .description = tdesc,
688 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
689 .requester = dahdi_request,
690 .send_digit_begin = dahdi_digit_begin,
691 .send_digit_end = dahdi_digit_end,
692 .send_text = dahdi_sendtext,
693 .call = dahdi_call,
694 .hangup = dahdi_hangup,
695 .answer = dahdi_answer,
696 .read = dahdi_read,
697 .write = dahdi_write,
698 .bridge = dahdi_bridge,
699 .exception = dahdi_exception,
700 .indicate = dahdi_indicate,
701 .fixup = dahdi_fixup,
702 .setoption = dahdi_setoption,
703 .func_channel_read = dahdi_func_read,
706 static const struct ast_channel_tech zap_tech = {
707 .type = "Zap",
708 .description = tdesc,
709 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
710 .requester = dahdi_request,
711 .send_digit_begin = dahdi_digit_begin,
712 .send_digit_end = dahdi_digit_end,
713 .send_text = dahdi_sendtext,
714 .call = dahdi_call,
715 .hangup = dahdi_hangup,
716 .answer = dahdi_answer,
717 .read = dahdi_read,
718 .write = dahdi_write,
719 .bridge = dahdi_bridge,
720 .exception = dahdi_exception,
721 .indicate = dahdi_indicate,
722 .fixup = dahdi_fixup,
723 .setoption = dahdi_setoption,
724 .func_channel_read = dahdi_func_read,
727 static const struct ast_channel_tech *chan_tech;
729 #ifdef HAVE_PRI
730 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
731 #else
732 #define GET_CHANNEL(p) ((p)->channel)
733 #endif
735 struct dahdi_pvt *round_robin[32];
737 #ifdef HAVE_PRI
738 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
740 int res;
741 /* Grab the lock first */
742 do {
743 res = ast_mutex_trylock(&pri->lock);
744 if (res) {
745 DEADLOCK_AVOIDANCE(&pvt->lock);
747 } while (res);
748 /* Then break the poll */
749 pthread_kill(pri->master, SIGURG);
750 return 0;
752 #endif
754 #define NUM_CADENCE_MAX 25
755 static int num_cadence = 4;
756 static int user_has_defined_cadences = 0;
758 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
759 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
760 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
761 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
762 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
765 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
766 * is 1, the second pause is 2 and so on.
769 static int cidrings[NUM_CADENCE_MAX] = {
770 2, /*!< Right after first long ring */
771 4, /*!< Right after long part */
772 3, /*!< After third chirp */
773 2, /*!< Second spell */
776 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
777 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
779 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
780 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
782 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
784 int res;
785 if (p->subs[0].owner == ast)
786 res = 0;
787 else if (p->subs[1].owner == ast)
788 res = 1;
789 else if (p->subs[2].owner == ast)
790 res = 2;
791 else {
792 res = -1;
793 if (!nullok)
794 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
796 return res;
799 #ifdef HAVE_PRI
800 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
801 #else
802 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
803 #endif
805 #ifdef HAVE_PRI
806 if (pri)
807 ast_mutex_unlock(&pri->lock);
808 #endif
809 for (;;) {
810 if (p->subs[a].owner) {
811 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
812 DEADLOCK_AVOIDANCE(&p->lock);
813 } else {
814 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
815 ast_mutex_unlock(&p->subs[a].owner->lock);
816 break;
818 } else
819 break;
821 #ifdef HAVE_PRI
822 if (pri)
823 ast_mutex_lock(&pri->lock);
824 #endif
827 #ifdef HAVE_PRI
828 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
829 #else
830 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
831 #endif
833 /* We must unlock the PRI to avoid the possibility of a deadlock */
834 #ifdef HAVE_PRI
835 if (pri)
836 ast_mutex_unlock(&pri->lock);
837 #endif
838 for (;;) {
839 if (p->owner) {
840 if (ast_mutex_trylock(&p->owner->lock)) {
841 DEADLOCK_AVOIDANCE(&p->lock);
842 } else {
843 ast_queue_frame(p->owner, f);
844 ast_mutex_unlock(&p->owner->lock);
845 break;
847 } else
848 break;
850 #ifdef HAVE_PRI
851 if (pri)
852 ast_mutex_lock(&pri->lock);
853 #endif
856 static int restore_gains(struct dahdi_pvt *p);
858 static void swap_subs(struct dahdi_pvt *p, int a, int b)
860 int tchan;
861 int tinthreeway;
862 struct ast_channel *towner;
864 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
866 tchan = p->subs[a].chan;
867 towner = p->subs[a].owner;
868 tinthreeway = p->subs[a].inthreeway;
870 p->subs[a].chan = p->subs[b].chan;
871 p->subs[a].owner = p->subs[b].owner;
872 p->subs[a].inthreeway = p->subs[b].inthreeway;
874 p->subs[b].chan = tchan;
875 p->subs[b].owner = towner;
876 p->subs[b].inthreeway = tinthreeway;
878 if (p->subs[a].owner)
879 p->subs[a].owner->fds[0] = p->subs[a].dfd;
880 if (p->subs[b].owner)
881 p->subs[b].owner->fds[0] = p->subs[b].dfd;
882 wakeup_sub(p, a, NULL);
883 wakeup_sub(p, b, NULL);
886 static int dahdi_open(char *fn)
888 int fd;
889 int isnum;
890 int chan = 0;
891 int bs;
892 int x;
893 isnum = 1;
894 for (x = 0; x < strlen(fn); x++) {
895 if (!isdigit(fn[x])) {
896 isnum = 0;
897 break;
900 if (isnum) {
901 chan = atoi(fn);
902 if (chan < 1) {
903 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
904 return -1;
906 #ifdef HAVE_ZAPTEL
907 fn = "/dev/zap/channel";
908 #else
909 fn = "/dev/dahdi/channel";
910 #endif
912 fd = open(fn, O_RDWR | O_NONBLOCK);
913 if (fd < 0) {
914 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
915 return -1;
917 if (chan) {
918 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
919 x = errno;
920 close(fd);
921 errno = x;
922 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
923 return -1;
926 bs = READ_SIZE;
927 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
928 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
929 x = errno;
930 close(fd);
931 errno = x;
932 return -1;
934 return fd;
937 static void dahdi_close(int fd)
939 if (fd > 0)
940 close(fd);
943 static int dahdi_setlinear(int dfd, int linear)
945 int res;
946 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
947 if (res)
948 return res;
949 return 0;
953 static int alloc_sub(struct dahdi_pvt *p, int x)
955 DAHDI_BUFFERINFO bi;
956 int res;
957 if (p->subs[x].dfd < 0) {
958 #ifdef HAVE_ZAPTEL
959 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
960 #else
961 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
962 #endif
963 if (p->subs[x].dfd > -1) {
964 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
965 if (!res) {
966 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
967 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
968 bi.numbufs = numbufs;
969 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
970 if (res < 0) {
971 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
973 } else
974 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
975 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
976 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
977 dahdi_close(p->subs[x].dfd);
978 p->subs[x].dfd = -1;
979 return -1;
981 if (option_debug)
982 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
983 return 0;
984 } else
985 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
986 return -1;
988 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
989 return -1;
992 static int unalloc_sub(struct dahdi_pvt *p, int x)
994 if (!x) {
995 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
996 return -1;
998 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
999 if (p->subs[x].dfd > -1) {
1000 dahdi_close(p->subs[x].dfd);
1002 p->subs[x].dfd = -1;
1003 p->subs[x].linear = 0;
1004 p->subs[x].chan = 0;
1005 p->subs[x].owner = NULL;
1006 p->subs[x].inthreeway = 0;
1007 p->polarity = POLARITY_IDLE;
1008 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
1009 return 0;
1012 static int digit_to_dtmfindex(char digit)
1014 if (isdigit(digit))
1015 return DAHDI_TONE_DTMF_BASE + (digit - '0');
1016 else if (digit >= 'A' && digit <= 'D')
1017 return DAHDI_TONE_DTMF_A + (digit - 'A');
1018 else if (digit >= 'a' && digit <= 'd')
1019 return DAHDI_TONE_DTMF_A + (digit - 'a');
1020 else if (digit == '*')
1021 return DAHDI_TONE_DTMF_s;
1022 else if (digit == '#')
1023 return DAHDI_TONE_DTMF_p;
1024 else
1025 return -1;
1028 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1030 struct dahdi_pvt *pvt;
1031 int index;
1032 int dtmf = -1;
1034 pvt = chan->tech_pvt;
1036 ast_mutex_lock(&pvt->lock);
1038 index = dahdi_get_index(chan, pvt, 0);
1040 if ((index != SUB_REAL) || !pvt->owner)
1041 goto out;
1043 #ifdef HAVE_PRI
1044 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1045 if (pvt->setup_ack) {
1046 if (!pri_grab(pvt, pvt->pri)) {
1047 pri_information(pvt->pri->pri, pvt->call, digit);
1048 pri_rel(pvt->pri);
1049 } else
1050 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1051 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1052 int res;
1053 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1054 res = strlen(pvt->dialdest);
1055 pvt->dialdest[res++] = digit;
1056 pvt->dialdest[res] = '\0';
1058 goto out;
1060 #endif
1061 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1062 goto out;
1064 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1065 int res;
1066 DAHDI_DIAL_OPERATION zo = {
1067 .op = DAHDI_DIAL_OP_APPEND,
1068 .dialstr[0] = 'T',
1069 .dialstr[1] = digit,
1070 .dialstr[2] = 0,
1072 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1073 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1074 else
1075 pvt->dialing = 1;
1076 } else {
1077 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1078 pvt->dialing = 1;
1079 pvt->begindigit = digit;
1082 out:
1083 ast_mutex_unlock(&pvt->lock);
1085 return 0;
1088 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1090 struct dahdi_pvt *pvt;
1091 int res = 0;
1092 int index;
1093 int x;
1095 pvt = chan->tech_pvt;
1097 ast_mutex_lock(&pvt->lock);
1099 index = dahdi_get_index(chan, pvt, 0);
1101 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1102 goto out;
1104 #ifdef HAVE_PRI
1105 /* This means that the digit was already sent via PRI signalling */
1106 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1107 goto out;
1108 #endif
1110 if (pvt->begindigit) {
1111 x = -1;
1112 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1113 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1114 pvt->dialing = 0;
1115 pvt->begindigit = 0;
1118 out:
1119 ast_mutex_unlock(&pvt->lock);
1121 return res;
1124 static char *events[] = {
1125 "No event",
1126 "On hook",
1127 "Ring/Answered",
1128 "Wink/Flash",
1129 "Alarm",
1130 "No more alarm",
1131 "HDLC Abort",
1132 "HDLC Overrun",
1133 "HDLC Bad FCS",
1134 "Dial Complete",
1135 "Ringer On",
1136 "Ringer Off",
1137 "Hook Transition Complete",
1138 "Bits Changed",
1139 "Pulse Start",
1140 "Timer Expired",
1141 "Timer Ping",
1142 "Polarity Reversal",
1143 "Ring Begin",
1146 static struct {
1147 int alarm;
1148 char *name;
1149 } alarms[] = {
1150 { DAHDI_ALARM_RED, "Red Alarm" },
1151 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1152 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1153 { DAHDI_ALARM_RECOVER, "Recovering" },
1154 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1155 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1156 { DAHDI_ALARM_NONE, "None" },
1159 static char *alarm2str(int alarm)
1161 int x;
1162 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1163 if (alarms[x].alarm & alarm)
1164 return alarms[x].name;
1166 return alarm ? "Unknown Alarm" : "No Alarm";
1169 static char *event2str(int event)
1171 static char buf[256];
1172 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1173 return events[event];
1174 sprintf(buf, "Event %d", event); /* safe */
1175 return buf;
1178 #ifdef HAVE_PRI
1179 static char *dialplan2str(int dialplan)
1181 if (dialplan == -1) {
1182 return("Dynamically set dialplan in ISDN");
1184 return (pri_plan2str(dialplan));
1186 #endif
1188 static char *dahdi_sig2str(int sig)
1190 static char buf[256];
1191 switch (sig) {
1192 case SIG_EM:
1193 return "E & M Immediate";
1194 case SIG_EMWINK:
1195 return "E & M Wink";
1196 case SIG_EM_E1:
1197 return "E & M E1";
1198 case SIG_FEATD:
1199 return "Feature Group D (DTMF)";
1200 case SIG_FEATDMF:
1201 return "Feature Group D (MF)";
1202 case SIG_FEATDMF_TA:
1203 return "Feature Groud D (MF) Tandem Access";
1204 case SIG_FEATB:
1205 return "Feature Group B (MF)";
1206 case SIG_E911:
1207 return "E911 (MF)";
1208 case SIG_FGC_CAMA:
1209 return "FGC/CAMA (Dialpulse)";
1210 case SIG_FGC_CAMAMF:
1211 return "FGC/CAMA (MF)";
1212 case SIG_FXSLS:
1213 return "FXS Loopstart";
1214 case SIG_FXSGS:
1215 return "FXS Groundstart";
1216 case SIG_FXSKS:
1217 return "FXS Kewlstart";
1218 case SIG_FXOLS:
1219 return "FXO Loopstart";
1220 case SIG_FXOGS:
1221 return "FXO Groundstart";
1222 case SIG_FXOKS:
1223 return "FXO Kewlstart";
1224 case SIG_PRI:
1225 return "ISDN PRI";
1226 case SIG_SF:
1227 return "SF (Tone) Immediate";
1228 case SIG_SFWINK:
1229 return "SF (Tone) Wink";
1230 case SIG_SF_FEATD:
1231 return "SF (Tone) with Feature Group D (DTMF)";
1232 case SIG_SF_FEATDMF:
1233 return "SF (Tone) with Feature Group D (MF)";
1234 case SIG_SF_FEATB:
1235 return "SF (Tone) with Feature Group B (MF)";
1236 case SIG_GR303FXOKS:
1237 return "GR-303 with FXOKS";
1238 case SIG_GR303FXSKS:
1239 return "GR-303 with FXSKS";
1240 case 0:
1241 return "Pseudo";
1242 default:
1243 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1244 return buf;
1248 #define sig2str dahdi_sig2str
1250 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1252 /* If the conference already exists, and we're already in it
1253 don't bother doing anything */
1254 DAHDI_CONFINFO zi;
1256 memset(&zi, 0, sizeof(zi));
1257 zi.chan = 0;
1259 if (slavechannel > 0) {
1260 /* If we have only one slave, do a digital mon */
1261 zi.confmode = DAHDI_CONF_DIGITALMON;
1262 zi.confno = slavechannel;
1263 } else {
1264 if (!index) {
1265 /* Real-side and pseudo-side both participate in conference */
1266 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1267 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1268 } else
1269 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1270 zi.confno = p->confno;
1272 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1273 return 0;
1274 if (c->dfd < 0)
1275 return 0;
1276 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1277 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1278 return -1;
1280 if (slavechannel < 1) {
1281 p->confno = zi.confno;
1283 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1284 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1285 return 0;
1288 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1290 /* If they're listening to our channel, they're ours */
1291 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1292 return 1;
1293 /* If they're a talker on our (allocated) conference, they're ours */
1294 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1295 return 1;
1296 return 0;
1299 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1301 DAHDI_CONFINFO zi;
1302 if (/* Can't delete if there's no dfd */
1303 (c->dfd < 0) ||
1304 /* Don't delete from the conference if it's not our conference */
1305 !isourconf(p, c)
1306 /* Don't delete if we don't think it's conferenced at all (implied) */
1307 ) return 0;
1308 memset(&zi, 0, sizeof(zi));
1309 zi.chan = 0;
1310 zi.confno = 0;
1311 zi.confmode = 0;
1312 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1313 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1314 return -1;
1316 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1317 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1318 return 0;
1321 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1323 int x;
1324 int useslavenative;
1325 struct dahdi_pvt *slave = NULL;
1326 /* Start out optimistic */
1327 useslavenative = 1;
1328 /* Update conference state in a stateless fashion */
1329 for (x = 0; x < 3; x++) {
1330 /* Any three-way calling makes slave native mode *definitely* out
1331 of the question */
1332 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1333 useslavenative = 0;
1335 /* If we don't have any 3-way calls, check to see if we have
1336 precisely one slave */
1337 if (useslavenative) {
1338 for (x = 0; x < MAX_SLAVES; x++) {
1339 if (p->slaves[x]) {
1340 if (slave) {
1341 /* Whoops already have a slave! No
1342 slave native and stop right away */
1343 slave = NULL;
1344 useslavenative = 0;
1345 break;
1346 } else {
1347 /* We have one slave so far */
1348 slave = p->slaves[x];
1353 /* If no slave, slave native definitely out */
1354 if (!slave)
1355 useslavenative = 0;
1356 else if (slave->law != p->law) {
1357 useslavenative = 0;
1358 slave = NULL;
1360 if (out)
1361 *out = slave;
1362 return useslavenative;
1365 static int reset_conf(struct dahdi_pvt *p)
1367 DAHDI_CONFINFO zi;
1368 memset(&zi, 0, sizeof(zi));
1369 p->confno = -1;
1370 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1371 if (p->subs[SUB_REAL].dfd > -1) {
1372 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1373 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1375 return 0;
1378 static int update_conf(struct dahdi_pvt *p)
1380 int needconf = 0;
1381 int x;
1382 int useslavenative;
1383 struct dahdi_pvt *slave = NULL;
1385 useslavenative = isslavenative(p, &slave);
1386 /* Start with the obvious, general stuff */
1387 for (x = 0; x < 3; x++) {
1388 /* Look for three way calls */
1389 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1390 conf_add(p, &p->subs[x], x, 0);
1391 needconf++;
1392 } else {
1393 conf_del(p, &p->subs[x], x);
1396 /* If we have a slave, add him to our conference now. or DAX
1397 if this is slave native */
1398 for (x = 0; x < MAX_SLAVES; x++) {
1399 if (p->slaves[x]) {
1400 if (useslavenative)
1401 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1402 else {
1403 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1404 needconf++;
1408 /* If we're supposed to be in there, do so now */
1409 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1410 if (useslavenative)
1411 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1412 else {
1413 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1414 needconf++;
1417 /* If we have a master, add ourselves to his conference */
1418 if (p->master) {
1419 if (isslavenative(p->master, NULL)) {
1420 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1421 } else {
1422 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1425 if (!needconf) {
1426 /* Nobody is left (or should be left) in our conference.
1427 Kill it. */
1428 p->confno = -1;
1430 if (option_debug)
1431 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1432 return 0;
1435 static void dahdi_enable_ec(struct dahdi_pvt *p)
1437 int x;
1438 int res;
1439 if (!p)
1440 return;
1441 if (p->echocanon) {
1442 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1443 return;
1445 if (p->digital) {
1446 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
1447 return;
1449 if (p->echocancel) {
1450 if (p->sig == SIG_PRI) {
1451 x = 1;
1452 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1453 if (res)
1454 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1456 x = p->echocancel;
1457 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1458 if (res)
1459 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1460 else {
1461 p->echocanon = 1;
1462 if (option_debug)
1463 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1465 } else if (option_debug)
1466 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1469 static void dahdi_train_ec(struct dahdi_pvt *p)
1471 int x;
1472 int res;
1473 if (p && p->echocancel && p->echotraining) {
1474 x = p->echotraining;
1475 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1476 if (res)
1477 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1478 else {
1479 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1481 } else
1482 ast_log(LOG_DEBUG, "No echo training requested\n");
1485 static void dahdi_disable_ec(struct dahdi_pvt *p)
1487 int x;
1488 int res;
1489 if (p->echocancel) {
1490 x = 0;
1491 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1492 if (res)
1493 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1494 else if (option_debug)
1495 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1497 p->echocanon = 0;
1500 static void fill_txgain(DAHDI_GAINS *g, float gain, int law)
1502 int j;
1503 int k;
1504 float linear_gain = pow(10.0, gain / 20.0);
1506 switch (law) {
1507 case DAHDI_LAW_ALAW:
1508 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1509 if (gain) {
1510 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1511 if (k > 32767) k = 32767;
1512 if (k < -32767) k = -32767;
1513 g->txgain[j] = AST_LIN2A(k);
1514 } else {
1515 g->txgain[j] = j;
1518 break;
1519 case DAHDI_LAW_MULAW:
1520 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1521 if (gain) {
1522 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1523 if (k > 32767) k = 32767;
1524 if (k < -32767) k = -32767;
1525 g->txgain[j] = AST_LIN2MU(k);
1526 } else {
1527 g->txgain[j] = j;
1530 break;
1534 static void fill_rxgain(DAHDI_GAINS *g, float gain, int law)
1536 int j;
1537 int k;
1538 float linear_gain = pow(10.0, gain / 20.0);
1540 switch (law) {
1541 case DAHDI_LAW_ALAW:
1542 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1543 if (gain) {
1544 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1545 if (k > 32767) k = 32767;
1546 if (k < -32767) k = -32767;
1547 g->rxgain[j] = AST_LIN2A(k);
1548 } else {
1549 g->rxgain[j] = j;
1552 break;
1553 case DAHDI_LAW_MULAW:
1554 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1555 if (gain) {
1556 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1557 if (k > 32767) k = 32767;
1558 if (k < -32767) k = -32767;
1559 g->rxgain[j] = AST_LIN2MU(k);
1560 } else {
1561 g->rxgain[j] = j;
1564 break;
1568 static int set_actual_txgain(int fd, int chan, float gain, int law)
1570 DAHDI_GAINS g;
1571 int res;
1573 memset(&g, 0, sizeof(g));
1574 g.chan = chan;
1575 res = ioctl(fd, DAHDI_GETGAINS, &g);
1576 if (res) {
1577 if (option_debug)
1578 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1579 return res;
1582 fill_txgain(&g, gain, law);
1584 return ioctl(fd, DAHDI_SETGAINS, &g);
1587 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1589 DAHDI_GAINS g;
1590 int res;
1592 memset(&g, 0, sizeof(g));
1593 g.chan = chan;
1594 res = ioctl(fd, DAHDI_GETGAINS, &g);
1595 if (res) {
1596 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1597 return res;
1600 fill_rxgain(&g, gain, law);
1602 return ioctl(fd, DAHDI_SETGAINS, &g);
1605 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1607 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1610 static int bump_gains(struct dahdi_pvt *p)
1612 int res;
1614 /* Bump receive gain by 5.0db */
1615 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1616 if (res) {
1617 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1618 return -1;
1621 return 0;
1624 static int restore_gains(struct dahdi_pvt *p)
1626 int res;
1628 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1629 if (res) {
1630 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1631 return -1;
1634 return 0;
1637 static inline int dahdi_set_hook(int fd, int hs)
1639 int x, res;
1641 x = hs;
1642 res = ioctl(fd, DAHDI_HOOK, &x);
1644 if (res < 0) {
1645 if (errno == EINPROGRESS)
1646 return 0;
1647 ast_log(LOG_WARNING, "dahdi hook failed: %s\n", strerror(errno));
1650 return res;
1653 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1655 int x, y, res;
1656 x = muted;
1657 if (p->sig == SIG_PRI) {
1658 y = 1;
1659 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1660 if (res)
1661 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1663 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1664 if (res < 0)
1665 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1666 return res;
1669 static int save_conference(struct dahdi_pvt *p)
1671 DAHDI_CONFINFO c;
1672 int res;
1673 if (p->saveconf.confmode) {
1674 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1675 return -1;
1677 p->saveconf.chan = 0;
1678 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1679 if (res) {
1680 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1681 p->saveconf.confmode = 0;
1682 return -1;
1684 c.chan = 0;
1685 c.confno = 0;
1686 c.confmode = DAHDI_CONF_NORMAL;
1687 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1688 if (res) {
1689 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1690 return -1;
1692 if (option_debug)
1693 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1694 return 0;
1697 static int restore_conference(struct dahdi_pvt *p)
1699 int res;
1700 if (p->saveconf.confmode) {
1701 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1702 p->saveconf.confmode = 0;
1703 if (res) {
1704 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1705 return -1;
1708 if (option_debug)
1709 ast_log(LOG_DEBUG, "Restored conferencing\n");
1710 return 0;
1713 static int send_callerid(struct dahdi_pvt *p);
1715 static int send_cwcidspill(struct dahdi_pvt *p)
1717 p->callwaitcas = 0;
1718 p->cidcwexpire = 0;
1719 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1720 return -1;
1721 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1722 /* Make sure we account for the end */
1723 p->cidlen += READ_SIZE * 4;
1724 p->cidpos = 0;
1725 send_callerid(p);
1726 if (option_verbose > 2)
1727 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1728 return 0;
1731 static int has_voicemail(struct dahdi_pvt *p)
1734 return ast_app_has_voicemail(p->mailbox, NULL);
1737 static int send_callerid(struct dahdi_pvt *p)
1739 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1740 int res;
1741 /* Take out of linear mode if necessary */
1742 if (p->subs[SUB_REAL].linear) {
1743 p->subs[SUB_REAL].linear = 0;
1744 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1746 while (p->cidpos < p->cidlen) {
1747 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1748 if (res < 0) {
1749 if (errno == EAGAIN)
1750 return 0;
1751 else {
1752 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1753 return -1;
1756 if (!res)
1757 return 0;
1758 p->cidpos += res;
1760 free(p->cidspill);
1761 p->cidspill = NULL;
1762 if (p->callwaitcas) {
1763 /* Wait for CID/CW to expire */
1764 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1765 } else
1766 restore_conference(p);
1767 return 0;
1770 static int dahdi_callwait(struct ast_channel *ast)
1772 struct dahdi_pvt *p = ast->tech_pvt;
1773 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1774 if (p->cidspill) {
1775 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1776 free(p->cidspill);
1778 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1779 return -1;
1780 save_conference(p);
1781 /* Silence */
1782 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1783 if (!p->callwaitrings && p->callwaitingcallerid) {
1784 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1785 p->callwaitcas = 1;
1786 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1787 } else {
1788 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1789 p->callwaitcas = 0;
1790 p->cidlen = 2400 + READ_SIZE * 4;
1792 p->cidpos = 0;
1793 send_callerid(p);
1795 return 0;
1798 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1800 struct dahdi_pvt *p = ast->tech_pvt;
1801 int x, res, index,mysig;
1802 char *c, *n, *l;
1803 #ifdef HAVE_PRI
1804 char *s = NULL;
1805 #endif
1806 char dest[256]; /* must be same length as p->dialdest */
1807 ast_mutex_lock(&p->lock);
1808 ast_copy_string(dest, rdest, sizeof(dest));
1809 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1810 if ((ast->_state == AST_STATE_BUSY)) {
1811 p->subs[SUB_REAL].needbusy = 1;
1812 ast_mutex_unlock(&p->lock);
1813 return 0;
1815 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1816 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1817 ast_mutex_unlock(&p->lock);
1818 return -1;
1820 p->dialednone = 0;
1821 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1823 /* Special pseudo -- automatically up */
1824 ast_setstate(ast, AST_STATE_UP);
1825 ast_mutex_unlock(&p->lock);
1826 return 0;
1828 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1829 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1830 if (res)
1831 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1832 p->outgoing = 1;
1834 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1836 mysig = p->sig;
1837 if (p->outsigmod > -1)
1838 mysig = p->outsigmod;
1840 switch (mysig) {
1841 case SIG_FXOLS:
1842 case SIG_FXOGS:
1843 case SIG_FXOKS:
1844 if (p->owner == ast) {
1845 /* Normal ring, on hook */
1847 /* Don't send audio while on hook, until the call is answered */
1848 p->dialing = 1;
1849 if (p->use_callerid) {
1850 /* Generate the Caller-ID spill if desired */
1851 if (p->cidspill) {
1852 ast_log(LOG_WARNING, "cidspill already exists??\n");
1853 free(p->cidspill);
1855 p->callwaitcas = 0;
1856 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1857 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1858 p->cidpos = 0;
1859 send_callerid(p);
1862 /* Choose proper cadence */
1863 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1864 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1865 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1866 p->cidrings = cidrings[p->distinctivering - 1];
1867 } else {
1868 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1869 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1870 p->cidrings = p->sendcalleridafter;
1873 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1874 c = strchr(dest, '/');
1875 if (c)
1876 c++;
1877 if (c && (strlen(c) < p->stripmsd)) {
1878 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1879 c = NULL;
1881 if (c) {
1882 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1883 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
1884 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
1885 } else {
1886 p->dop.dialstr[0] = '\0';
1888 x = DAHDI_RING;
1889 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
1890 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
1891 ast_mutex_unlock(&p->lock);
1892 return -1;
1894 p->dialing = 1;
1895 } else {
1896 /* Call waiting call */
1897 p->callwaitrings = 0;
1898 if (ast->cid.cid_num)
1899 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
1900 else
1901 p->callwait_num[0] = '\0';
1902 if (ast->cid.cid_name)
1903 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
1904 else
1905 p->callwait_name[0] = '\0';
1906 /* Call waiting tone instead */
1907 if (dahdi_callwait(ast)) {
1908 ast_mutex_unlock(&p->lock);
1909 return -1;
1911 /* Make ring-back */
1912 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
1913 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
1916 n = ast->cid.cid_name;
1917 l = ast->cid.cid_num;
1918 if (l)
1919 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
1920 else
1921 p->lastcid_num[0] = '\0';
1922 if (n)
1923 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
1924 else
1925 p->lastcid_name[0] = '\0';
1926 ast_setstate(ast, AST_STATE_RINGING);
1927 index = dahdi_get_index(ast, p, 0);
1928 if (index > -1) {
1929 p->subs[index].needringing = 1;
1931 break;
1932 case SIG_FXSLS:
1933 case SIG_FXSGS:
1934 case SIG_FXSKS:
1935 case SIG_EMWINK:
1936 case SIG_EM:
1937 case SIG_EM_E1:
1938 case SIG_FEATD:
1939 case SIG_FEATDMF:
1940 case SIG_E911:
1941 case SIG_FGC_CAMA:
1942 case SIG_FGC_CAMAMF:
1943 case SIG_FEATB:
1944 case SIG_SFWINK:
1945 case SIG_SF:
1946 case SIG_SF_FEATD:
1947 case SIG_SF_FEATDMF:
1948 case SIG_FEATDMF_TA:
1949 case SIG_SF_FEATB:
1950 c = strchr(dest, '/');
1951 if (c)
1952 c++;
1953 else
1954 c = "";
1955 if (strlen(c) < p->stripmsd) {
1956 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1957 ast_mutex_unlock(&p->lock);
1958 return -1;
1960 #ifdef HAVE_PRI
1961 /* Start the trunk, if not GR-303 */
1962 if (!p->pri) {
1963 #endif
1964 x = DAHDI_START;
1965 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
1966 if (res < 0) {
1967 if (errno != EINPROGRESS) {
1968 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
1969 ast_mutex_unlock(&p->lock);
1970 return -1;
1973 #ifdef HAVE_PRI
1975 #endif
1976 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
1977 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1979 c += p->stripmsd;
1981 switch (mysig) {
1982 case SIG_FEATD:
1983 l = ast->cid.cid_num;
1984 if (l)
1985 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
1986 else
1987 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
1988 break;
1989 case SIG_FEATDMF:
1990 l = ast->cid.cid_num;
1991 if (l)
1992 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
1993 else
1994 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
1995 break;
1996 case SIG_FEATDMF_TA:
1998 const char *cic, *ozz;
2000 /* If you have to go through a Tandem Access point you need to use this */
2001 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
2002 if (!ozz)
2003 ozz = defaultozz;
2004 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
2005 if (!cic)
2006 cic = defaultcic;
2007 if (!ozz || !cic) {
2008 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2009 ast_mutex_unlock(&p->lock);
2010 return -1;
2012 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
2013 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
2014 p->whichwink = 0;
2016 break;
2017 case SIG_E911:
2018 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2019 break;
2020 case SIG_FGC_CAMA:
2021 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2022 break;
2023 case SIG_FGC_CAMAMF:
2024 case SIG_FEATB:
2025 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2026 break;
2027 default:
2028 if (p->pulse)
2029 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2030 else
2031 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2032 break;
2035 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2036 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2037 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2038 p->echorest[sizeof(p->echorest) - 1] = '\0';
2039 p->echobreak = 1;
2040 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2041 } else
2042 p->echobreak = 0;
2043 if (!res) {
2044 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2045 int saveerr = errno;
2047 x = DAHDI_ONHOOK;
2048 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2049 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2050 ast_mutex_unlock(&p->lock);
2051 return -1;
2053 } else
2054 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2055 p->dialing = 1;
2056 if (ast_strlen_zero(c))
2057 p->dialednone = 1;
2058 ast_setstate(ast, AST_STATE_DIALING);
2059 break;
2060 case 0:
2061 /* Special pseudo -- automatically up*/
2062 ast_setstate(ast, AST_STATE_UP);
2063 break;
2064 case SIG_PRI:
2065 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2066 p->dialdest[0] = '\0';
2067 break;
2068 default:
2069 ast_log(LOG_DEBUG, "not yet implemented\n");
2070 ast_mutex_unlock(&p->lock);
2071 return -1;
2073 #ifdef HAVE_PRI
2074 if (p->pri) {
2075 struct pri_sr *sr;
2076 #ifdef SUPPORT_USERUSER
2077 const char *useruser;
2078 #endif
2079 int pridialplan;
2080 int dp_strip;
2081 int prilocaldialplan;
2082 int ldp_strip;
2083 int exclusive;
2084 const char *rr_str;
2085 int redirect_reason;
2087 c = strchr(dest, '/');
2088 if (c)
2089 c++;
2090 else
2091 c = dest;
2093 l = NULL;
2094 n = NULL;
2096 if (!p->hidecallerid) {
2097 l = ast->cid.cid_num;
2098 if (!p->hidecalleridname) {
2099 n = ast->cid.cid_name;
2104 if (strlen(c) < p->stripmsd) {
2105 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2106 ast_mutex_unlock(&p->lock);
2107 return -1;
2109 if (mysig != SIG_FXSKS) {
2110 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2111 s = strchr(c + p->stripmsd, 'w');
2112 if (s) {
2113 if (strlen(s) > 1)
2114 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2115 else
2116 p->dop.dialstr[0] = '\0';
2117 *s = '\0';
2118 } else {
2119 p->dop.dialstr[0] = '\0';
2122 if (pri_grab(p, p->pri)) {
2123 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2124 ast_mutex_unlock(&p->lock);
2125 return -1;
2127 if (!(p->call = pri_new_call(p->pri->pri))) {
2128 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2129 pri_rel(p->pri);
2130 ast_mutex_unlock(&p->lock);
2131 return -1;
2133 if (!(sr = pri_sr_new())) {
2134 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2135 pri_destroycall(p->pri->pri, p->call);
2136 p->call = NULL;
2137 pri_rel(p->pri);
2138 ast_mutex_unlock(&p->lock);
2139 return -1;
2141 if (p->bearer || (mysig == SIG_FXSKS)) {
2142 if (p->bearer) {
2143 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);
2144 p->bearer->call = p->call;
2145 } else
2146 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2147 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2149 p->digital = IS_DIGITAL(ast->transfercapability);
2150 /* Add support for exclusive override */
2151 if (p->priexclusive)
2152 exclusive = 1;
2153 else {
2154 /* otherwise, traditional behavior */
2155 if (p->pri->nodetype == PRI_NETWORK)
2156 exclusive = 0;
2157 else
2158 exclusive = 1;
2161 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2162 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2163 (p->digital ? -1 :
2164 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2165 if (p->pri->facilityenable)
2166 pri_facility_enable(p->pri->pri);
2168 if (option_verbose > 2)
2169 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2170 dp_strip = 0;
2171 pridialplan = p->pri->dialplan - 1;
2172 if (pridialplan == -2) { /* compute dynamically */
2173 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2174 dp_strip = strlen(p->pri->internationalprefix);
2175 pridialplan = PRI_INTERNATIONAL_ISDN;
2176 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2177 dp_strip = strlen(p->pri->nationalprefix);
2178 pridialplan = PRI_NATIONAL_ISDN;
2179 } else {
2180 pridialplan = PRI_LOCAL_ISDN;
2183 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2185 ldp_strip = 0;
2186 prilocaldialplan = p->pri->localdialplan - 1;
2187 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2188 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2189 ldp_strip = strlen(p->pri->internationalprefix);
2190 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2191 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2192 ldp_strip = strlen(p->pri->nationalprefix);
2193 prilocaldialplan = PRI_NATIONAL_ISDN;
2194 } else {
2195 prilocaldialplan = PRI_LOCAL_ISDN;
2198 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2199 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2200 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2201 if (!strcasecmp(rr_str, "UNKNOWN"))
2202 redirect_reason = 0;
2203 else if (!strcasecmp(rr_str, "BUSY"))
2204 redirect_reason = 1;
2205 else if (!strcasecmp(rr_str, "NO_REPLY"))
2206 redirect_reason = 2;
2207 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2208 redirect_reason = 15;
2209 else
2210 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2211 } else
2212 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2213 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2215 #ifdef SUPPORT_USERUSER
2216 /* User-user info */
2217 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2219 if (useruser)
2220 pri_sr_set_useruser(sr, useruser);
2221 #endif
2223 if (pri_setup(p->pri->pri, p->call, sr)) {
2224 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2225 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2226 pri_rel(p->pri);
2227 ast_mutex_unlock(&p->lock);
2228 pri_sr_free(sr);
2229 return -1;
2231 pri_sr_free(sr);
2232 ast_setstate(ast, AST_STATE_DIALING);
2233 pri_rel(p->pri);
2235 #endif
2236 ast_mutex_unlock(&p->lock);
2237 return 0;
2240 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2242 struct dahdi_pvt *p = *pvt;
2243 /* Remove channel from the list */
2244 if (p->prev)
2245 p->prev->next = p->next;
2246 if (p->next)
2247 p->next->prev = p->prev;
2248 if (p->use_smdi)
2249 ast_smdi_interface_unref(p->smdi_iface);
2250 ast_mutex_destroy(&p->lock);
2251 free(p);
2252 *pvt = NULL;
2255 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2257 int owned = 0;
2258 int i = 0;
2260 if (!now) {
2261 if (cur->owner) {
2262 owned = 1;
2265 for (i = 0; i < 3; i++) {
2266 if (cur->subs[i].owner) {
2267 owned = 1;
2270 if (!owned) {
2271 if (prev) {
2272 prev->next = cur->next;
2273 if (prev->next)
2274 prev->next->prev = prev;
2275 else
2276 ifend = prev;
2277 } else {
2278 iflist = cur->next;
2279 if (iflist)
2280 iflist->prev = NULL;
2281 else
2282 ifend = NULL;
2284 if (cur->subs[SUB_REAL].dfd > -1) {
2285 dahdi_close(cur->subs[SUB_REAL].dfd);
2287 destroy_dahdi_pvt(&cur);
2289 } else {
2290 if (prev) {
2291 prev->next = cur->next;
2292 if (prev->next)
2293 prev->next->prev = prev;
2294 else
2295 ifend = prev;
2296 } else {
2297 iflist = cur->next;
2298 if (iflist)
2299 iflist->prev = NULL;
2300 else
2301 ifend = NULL;
2303 if (cur->subs[SUB_REAL].dfd > -1) {
2304 dahdi_close(cur->subs[SUB_REAL].dfd);
2306 destroy_dahdi_pvt(&cur);
2308 return 0;
2311 #ifdef HAVE_PRI
2312 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2314 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2316 static char *dahdi_send_keypad_facility_descrip =
2317 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2318 " IE over the current channel.\n";
2320 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2322 /* Data will be our digit string */
2323 struct dahdi_pvt *p;
2324 char *digits = (char *) data;
2326 if (ast_strlen_zero(digits)) {
2327 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2328 return -1;
2331 p = (struct dahdi_pvt *)chan->tech_pvt;
2333 if (!p) {
2334 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2335 return -1;
2338 ast_mutex_lock(&p->lock);
2340 if (!p->pri || !p->call) {
2341 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2342 ast_mutex_unlock(&p->lock);
2343 return -1;
2346 if (!pri_grab(p, p->pri)) {
2347 pri_keypad_facility(p->pri->pri, p->call, digits);
2348 pri_rel(p->pri);
2349 } else {
2350 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2351 ast_mutex_unlock(&p->lock);
2352 return -1;
2355 ast_mutex_unlock(&p->lock);
2357 return 0;
2360 static int pri_is_up(struct dahdi_pri *pri)
2362 int x;
2363 for (x = 0; x < NUM_DCHANS; x++) {
2364 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2365 return 1;
2367 return 0;
2370 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2372 bearer->owner = &inuse;
2373 bearer->realcall = crv;
2374 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2375 if (crv->subs[SUB_REAL].owner)
2376 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2377 crv->bearer = bearer;
2378 crv->call = bearer->call;
2379 crv->pri = pri;
2380 return 0;
2383 static char *pri_order(int level)
2385 switch (level) {
2386 case 0:
2387 return "Primary";
2388 case 1:
2389 return "Secondary";
2390 case 2:
2391 return "Tertiary";
2392 case 3:
2393 return "Quaternary";
2394 default:
2395 return "<Unknown>";
2399 /* Returns fd of the active dchan */
2400 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2402 int x = -1;
2404 for (x = 0; x < NUM_DCHANS; x++) {
2405 if ((pri->dchans[x] == pri->pri))
2406 break;
2409 return pri->fds[x];
2412 static int pri_find_dchan(struct dahdi_pri *pri)
2414 int oldslot = -1;
2415 struct pri *old;
2416 int newslot = -1;
2417 int x;
2418 old = pri->pri;
2419 for (x = 0; x < NUM_DCHANS; x++) {
2420 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2421 newslot = x;
2422 if (pri->dchans[x] == old) {
2423 oldslot = x;
2426 if (newslot < 0) {
2427 newslot = 0;
2428 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2429 pri->dchannels[newslot]);
2431 if (old && (oldslot != newslot))
2432 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2433 pri->dchannels[oldslot], pri->dchannels[newslot]);
2434 pri->pri = pri->dchans[newslot];
2435 return 0;
2437 #endif
2439 static int dahdi_hangup(struct ast_channel *ast)
2441 int res;
2442 int index,x, law;
2443 /*static int restore_gains(struct dahdi_pvt *p);*/
2444 struct dahdi_pvt *p = ast->tech_pvt;
2445 struct dahdi_pvt *tmp = NULL;
2446 struct dahdi_pvt *prev = NULL;
2447 DAHDI_PARAMS par;
2449 if (option_debug)
2450 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2451 if (!ast->tech_pvt) {
2452 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2453 return 0;
2456 ast_mutex_lock(&p->lock);
2458 index = dahdi_get_index(ast, p, 1);
2460 if (p->sig == SIG_PRI) {
2461 x = 1;
2462 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2465 x = 0;
2466 dahdi_confmute(p, 0);
2467 restore_gains(p);
2468 if (p->origcid_num) {
2469 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2470 free(p->origcid_num);
2471 p->origcid_num = NULL;
2473 if (p->origcid_name) {
2474 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2475 free(p->origcid_name);
2476 p->origcid_name = NULL;
2478 if (p->dsp)
2479 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2480 if (p->exten)
2481 p->exten[0] = '\0';
2483 if (option_debug)
2484 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2485 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2486 p->ignoredtmf = 0;
2488 if (index > -1) {
2489 /* Real channel, do some fixup */
2490 p->subs[index].owner = NULL;
2491 p->subs[index].needanswer = 0;
2492 p->subs[index].needflash = 0;
2493 p->subs[index].needringing = 0;
2494 p->subs[index].needbusy = 0;
2495 p->subs[index].needcongestion = 0;
2496 p->subs[index].linear = 0;
2497 p->subs[index].needcallerid = 0;
2498 p->polarity = POLARITY_IDLE;
2499 dahdi_setlinear(p->subs[index].dfd, 0);
2500 if (index == SUB_REAL) {
2501 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2502 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2503 if (p->subs[SUB_CALLWAIT].inthreeway) {
2504 /* We had flipped over to answer a callwait and now it's gone */
2505 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2506 /* Move to the call-wait, but un-own us until they flip back. */
2507 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2508 unalloc_sub(p, SUB_CALLWAIT);
2509 p->owner = NULL;
2510 } else {
2511 /* The three way hung up, but we still have a call wait */
2512 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2513 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2514 unalloc_sub(p, SUB_THREEWAY);
2515 if (p->subs[SUB_REAL].inthreeway) {
2516 /* This was part of a three way call. Immediately make way for
2517 another call */
2518 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2519 p->owner = p->subs[SUB_REAL].owner;
2520 } else {
2521 /* This call hasn't been completed yet... Set owner to NULL */
2522 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2523 p->owner = NULL;
2525 p->subs[SUB_REAL].inthreeway = 0;
2527 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2528 /* Move to the call-wait and switch back to them. */
2529 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2530 unalloc_sub(p, SUB_CALLWAIT);
2531 p->owner = p->subs[SUB_REAL].owner;
2532 if (p->owner->_state != AST_STATE_UP)
2533 p->subs[SUB_REAL].needanswer = 1;
2534 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2535 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2536 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2537 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2538 unalloc_sub(p, SUB_THREEWAY);
2539 if (p->subs[SUB_REAL].inthreeway) {
2540 /* This was part of a three way call. Immediately make way for
2541 another call */
2542 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2543 p->owner = p->subs[SUB_REAL].owner;
2544 } else {
2545 /* This call hasn't been completed yet... Set owner to NULL */
2546 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2547 p->owner = NULL;
2549 p->subs[SUB_REAL].inthreeway = 0;
2551 } else if (index == SUB_CALLWAIT) {
2552 /* Ditch the holding callwait call, and immediately make it availabe */
2553 if (p->subs[SUB_CALLWAIT].inthreeway) {
2554 /* This is actually part of a three way, placed on hold. Place the third part
2555 on music on hold now */
2556 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2557 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2558 S_OR(p->mohsuggest, NULL),
2559 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2561 p->subs[SUB_THREEWAY].inthreeway = 0;
2562 /* Make it the call wait now */
2563 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2564 unalloc_sub(p, SUB_THREEWAY);
2565 } else
2566 unalloc_sub(p, SUB_CALLWAIT);
2567 } else if (index == SUB_THREEWAY) {
2568 if (p->subs[SUB_CALLWAIT].inthreeway) {
2569 /* The other party of the three way call is currently in a call-wait state.
2570 Start music on hold for them, and take the main guy out of the third call */
2571 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2572 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2573 S_OR(p->mohsuggest, NULL),
2574 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2576 p->subs[SUB_CALLWAIT].inthreeway = 0;
2578 p->subs[SUB_REAL].inthreeway = 0;
2579 /* If this was part of a three way call index, let us make
2580 another three way call */
2581 unalloc_sub(p, SUB_THREEWAY);
2582 } else {
2583 /* This wasn't any sort of call, but how are we an index? */
2584 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2588 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2589 p->owner = NULL;
2590 p->ringt = 0;
2591 p->distinctivering = 0;
2592 p->confirmanswer = 0;
2593 p->cidrings = 1;
2594 p->outgoing = 0;
2595 p->digital = 0;
2596 p->faxhandled = 0;
2597 p->pulsedial = 0;
2598 p->onhooktime = time(NULL);
2599 #ifdef HAVE_PRI
2600 p->proceeding = 0;
2601 p->progress = 0;
2602 p->alerting = 0;
2603 p->setup_ack = 0;
2604 #endif
2605 if (p->dsp) {
2606 ast_dsp_free(p->dsp);
2607 p->dsp = NULL;
2610 law = DAHDI_LAW_DEFAULT;
2611 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2612 if (res < 0)
2613 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2614 /* Perform low level hangup if no owner left */
2615 #ifdef HAVE_PRI
2616 if (p->pri) {
2617 #ifdef SUPPORT_USERUSER
2618 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2619 #endif
2621 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2622 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2623 if (!pri_grab(p, p->pri)) {
2624 if (p->alreadyhungup) {
2625 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2627 #ifdef SUPPORT_USERUSER
2628 pri_call_set_useruser(p->call, useruser);
2629 #endif
2631 pri_hangup(p->pri->pri, p->call, -1);
2632 p->call = NULL;
2633 if (p->bearer)
2634 p->bearer->call = NULL;
2635 } else {
2636 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2637 int icause = ast->hangupcause ? ast->hangupcause : -1;
2638 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2640 #ifdef SUPPORT_USERUSER
2641 pri_call_set_useruser(p->call, useruser);
2642 #endif
2644 p->alreadyhungup = 1;
2645 if (p->bearer)
2646 p->bearer->alreadyhungup = 1;
2647 if (cause) {
2648 if (atoi(cause))
2649 icause = atoi(cause);
2651 pri_hangup(p->pri->pri, p->call, icause);
2653 if (res < 0)
2654 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2655 pri_rel(p->pri);
2656 } else {
2657 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2658 res = -1;
2660 } else {
2661 if (p->bearer)
2662 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2663 p->call = NULL;
2664 res = 0;
2667 #endif
2668 if (p->sig && (p->sig != SIG_PRI))
2669 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2670 if (res < 0) {
2671 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2673 switch (p->sig) {
2674 case SIG_FXOGS:
2675 case SIG_FXOLS:
2676 case SIG_FXOKS:
2677 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2678 if (!res) {
2679 #if 0
2680 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2681 #endif
2682 /* If they're off hook, try playing congestion */
2683 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2684 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2685 else
2686 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2688 break;
2689 case SIG_FXSGS:
2690 case SIG_FXSLS:
2691 case SIG_FXSKS:
2692 /* Make sure we're not made available for at least two seconds assuming
2693 we were actually used for an inbound or outbound call. */
2694 if (ast->_state != AST_STATE_RESERVED) {
2695 time(&p->guardtime);
2696 p->guardtime += 2;
2698 break;
2699 default:
2700 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2702 if (p->cidspill)
2703 free(p->cidspill);
2704 if (p->sig)
2705 dahdi_disable_ec(p);
2706 x = 0;
2707 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2708 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2709 p->didtdd = 0;
2710 p->cidspill = NULL;
2711 p->callwaitcas = 0;
2712 p->callwaiting = p->permcallwaiting;
2713 p->hidecallerid = p->permhidecallerid;
2714 p->dialing = 0;
2715 p->rdnis[0] = '\0';
2716 update_conf(p);
2717 reset_conf(p);
2718 /* Restore data mode */
2719 if (p->sig == SIG_PRI) {
2720 x = 0;
2721 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2723 #ifdef HAVE_PRI
2724 if (p->bearer) {
2725 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2726 /* Free up the bearer channel as well, and
2727 don't use its file descriptor anymore */
2728 update_conf(p->bearer);
2729 reset_conf(p->bearer);
2730 p->bearer->owner = NULL;
2731 p->bearer->realcall = NULL;
2732 p->bearer = NULL;
2733 p->subs[SUB_REAL].dfd = -1;
2734 p->pri = NULL;
2736 #endif
2737 restart_monitor();
2740 p->callwaitingrepeat = 0;
2741 p->cidcwexpire = 0;
2742 p->oprmode = 0;
2743 ast->tech_pvt = NULL;
2744 ast_mutex_unlock(&p->lock);
2745 ast_module_unref(ast_module_info->self);
2746 if (option_verbose > 2)
2747 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2749 ast_mutex_lock(&iflock);
2750 tmp = iflist;
2751 prev = NULL;
2752 if (p->destroy) {
2753 while (tmp) {
2754 if (tmp == p) {
2755 destroy_channel(prev, tmp, 0);
2756 break;
2757 } else {
2758 prev = tmp;
2759 tmp = tmp->next;
2763 ast_mutex_unlock(&iflock);
2764 return 0;
2767 static int dahdi_answer(struct ast_channel *ast)
2769 struct dahdi_pvt *p = ast->tech_pvt;
2770 int res = 0;
2771 int index;
2772 int oldstate = ast->_state;
2773 ast_setstate(ast, AST_STATE_UP);
2774 ast_mutex_lock(&p->lock);
2775 index = dahdi_get_index(ast, p, 0);
2776 if (index < 0)
2777 index = SUB_REAL;
2778 /* nothing to do if a radio channel */
2779 if ((p->radio || (p->oprmode < 0))) {
2780 ast_mutex_unlock(&p->lock);
2781 return 0;
2783 switch (p->sig) {
2784 case SIG_FXSLS:
2785 case SIG_FXSGS:
2786 case SIG_FXSKS:
2787 p->ringt = 0;
2788 /* Fall through */
2789 case SIG_EM:
2790 case SIG_EM_E1:
2791 case SIG_EMWINK:
2792 case SIG_FEATD:
2793 case SIG_FEATDMF:
2794 case SIG_FEATDMF_TA:
2795 case SIG_E911:
2796 case SIG_FGC_CAMA:
2797 case SIG_FGC_CAMAMF:
2798 case SIG_FEATB:
2799 case SIG_SF:
2800 case SIG_SFWINK:
2801 case SIG_SF_FEATD:
2802 case SIG_SF_FEATDMF:
2803 case SIG_SF_FEATB:
2804 case SIG_FXOLS:
2805 case SIG_FXOGS:
2806 case SIG_FXOKS:
2807 /* Pick up the line */
2808 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
2809 if (p->hanguponpolarityswitch) {
2810 gettimeofday(&p->polaritydelaytv, NULL);
2812 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2813 tone_zone_play_tone(p->subs[index].dfd, -1);
2814 p->dialing = 0;
2815 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
2816 if (oldstate == AST_STATE_RINGING) {
2817 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
2818 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
2819 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2820 p->owner = p->subs[SUB_REAL].owner;
2823 if (p->sig & __DAHDI_SIG_FXS) {
2824 dahdi_enable_ec(p);
2825 dahdi_train_ec(p);
2827 break;
2828 #ifdef HAVE_PRI
2829 case SIG_PRI:
2830 /* Send a pri acknowledge */
2831 if (!pri_grab(p, p->pri)) {
2832 p->proceeding = 1;
2833 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2834 pri_rel(p->pri);
2835 } else {
2836 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2837 res = -1;
2839 break;
2840 #endif
2841 case 0:
2842 ast_mutex_unlock(&p->lock);
2843 return 0;
2844 default:
2845 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
2846 res = -1;
2848 ast_mutex_unlock(&p->lock);
2849 return res;
2852 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
2854 char *cp;
2855 signed char *scp;
2856 int x;
2857 int index;
2858 struct dahdi_pvt *p = chan->tech_pvt, *pp;
2859 struct oprmode *oprmode;
2862 /* all supported options require data */
2863 if (!data || (datalen < 1)) {
2864 errno = EINVAL;
2865 return -1;
2868 switch (option) {
2869 case AST_OPTION_TXGAIN:
2870 scp = (signed char *) data;
2871 index = dahdi_get_index(chan, p, 0);
2872 if (index < 0) {
2873 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
2874 return -1;
2876 if (option_debug)
2877 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
2878 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
2879 case AST_OPTION_RXGAIN:
2880 scp = (signed char *) data;
2881 index = dahdi_get_index(chan, p, 0);
2882 if (index < 0) {
2883 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
2884 return -1;
2886 if (option_debug)
2887 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
2888 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
2889 case AST_OPTION_TONE_VERIFY:
2890 if (!p->dsp)
2891 break;
2892 cp = (char *) data;
2893 switch (*cp) {
2894 case 1:
2895 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
2896 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
2897 break;
2898 case 2:
2899 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
2900 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
2901 break;
2902 default:
2903 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
2904 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
2905 break;
2907 break;
2908 case AST_OPTION_TDD:
2909 /* turn on or off TDD */
2910 cp = (char *) data;
2911 p->mate = 0;
2912 if (!*cp) { /* turn it off */
2913 if (option_debug)
2914 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
2915 if (p->tdd)
2916 tdd_free(p->tdd);
2917 p->tdd = 0;
2918 break;
2920 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
2921 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
2922 dahdi_disable_ec(p);
2923 /* otherwise, turn it on */
2924 if (!p->didtdd) { /* if havent done it yet */
2925 unsigned char mybuf[41000], *buf;
2926 int size, res, fd, len;
2927 struct pollfd fds[1];
2929 buf = mybuf;
2930 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
2931 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
2932 len = 40000;
2933 index = dahdi_get_index(chan, p, 0);
2934 if (index < 0) {
2935 ast_log(LOG_WARNING, "No index in TDD?\n");
2936 return -1;
2938 fd = p->subs[index].dfd;
2939 while (len) {
2940 if (ast_check_hangup(chan))
2941 return -1;
2942 size = len;
2943 if (size > READ_SIZE)
2944 size = READ_SIZE;
2945 fds[0].fd = fd;
2946 fds[0].events = POLLPRI | POLLOUT;
2947 fds[0].revents = 0;
2948 res = poll(fds, 1, -1);
2949 if (!res) {
2950 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
2951 continue;
2953 /* if got exception */
2954 if (fds[0].revents & POLLPRI)
2955 return -1;
2956 if (!(fds[0].revents & POLLOUT)) {
2957 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
2958 continue;
2960 res = write(fd, buf, size);
2961 if (res != size) {
2962 if (res == -1) return -1;
2963 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
2964 break;
2966 len -= size;
2967 buf += size;
2969 p->didtdd = 1; /* set to have done it now */
2971 if (*cp == 2) { /* Mate mode */
2972 if (p->tdd)
2973 tdd_free(p->tdd);
2974 p->tdd = 0;
2975 p->mate = 1;
2976 break;
2978 if (!p->tdd) { /* if we dont have one yet */
2979 p->tdd = tdd_new(); /* allocate one */
2981 break;
2982 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
2983 if (!p->dsp)
2984 break;
2985 cp = (char *) data;
2986 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
2987 *cp ? "ON" : "OFF", (int) *cp, chan->name);
2988 p->dtmfrelax = 0;
2989 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
2990 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
2991 break;
2992 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
2993 cp = (char *) data;
2994 if (!*cp) {
2995 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
2996 x = 0;
2997 dahdi_disable_ec(p);
2998 } else {
2999 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
3000 x = 1;
3002 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
3003 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
3004 break;
3005 case AST_OPTION_OPRMODE: /* Operator services mode */
3006 oprmode = (struct oprmode *) data;
3007 pp = oprmode->peer->tech_pvt;
3008 p->oprmode = pp->oprmode = 0;
3009 /* setup peers */
3010 p->oprpeer = pp;
3011 pp->oprpeer = p;
3012 /* setup modes, if any */
3013 if (oprmode->mode)
3015 pp->oprmode = oprmode->mode;
3016 p->oprmode = -oprmode->mode;
3018 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
3019 oprmode->mode, chan->name,oprmode->peer->name);;
3020 break;
3021 case AST_OPTION_ECHOCAN:
3022 cp = (char *) data;
3023 if (*cp) {
3024 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3025 dahdi_enable_ec(p);
3026 } else {
3027 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3028 dahdi_disable_ec(p);
3030 break;
3032 errno = 0;
3034 return 0;
3037 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3039 struct dahdi_pvt *p = chan->tech_pvt;
3041 if (!strcasecmp(data, "rxgain")) {
3042 ast_mutex_lock(&p->lock);
3043 snprintf(buf, len, "%f", p->rxgain);
3044 ast_mutex_unlock(&p->lock);
3045 } else if (!strcasecmp(data, "txgain")) {
3046 ast_mutex_lock(&p->lock);
3047 snprintf(buf, len, "%f", p->txgain);
3048 ast_mutex_unlock(&p->lock);
3049 } else {
3050 ast_copy_string(buf, "", len);
3052 return 0;
3056 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3058 /* Unlink a specific slave or all slaves/masters from a given master */
3059 int x;
3060 int hasslaves;
3061 if (!master)
3062 return;
3063 if (needlock) {
3064 ast_mutex_lock(&master->lock);
3065 if (slave) {
3066 while (ast_mutex_trylock(&slave->lock)) {
3067 DEADLOCK_AVOIDANCE(&master->lock);
3071 hasslaves = 0;
3072 for (x = 0; x < MAX_SLAVES; x++) {
3073 if (master->slaves[x]) {
3074 if (!slave || (master->slaves[x] == slave)) {
3075 /* Take slave out of the conference */
3076 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3077 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3078 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3079 master->slaves[x]->master = NULL;
3080 master->slaves[x] = NULL;
3081 } else
3082 hasslaves = 1;
3084 if (!hasslaves)
3085 master->inconference = 0;
3087 if (!slave) {
3088 if (master->master) {
3089 /* Take master out of the conference */
3090 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3091 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3092 hasslaves = 0;
3093 for (x = 0; x < MAX_SLAVES; x++) {
3094 if (master->master->slaves[x] == master)
3095 master->master->slaves[x] = NULL;
3096 else if (master->master->slaves[x])
3097 hasslaves = 1;
3099 if (!hasslaves)
3100 master->master->inconference = 0;
3102 master->master = NULL;
3104 update_conf(master);
3105 if (needlock) {
3106 if (slave)
3107 ast_mutex_unlock(&slave->lock);
3108 ast_mutex_unlock(&master->lock);
3112 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3113 int x;
3114 if (!slave || !master) {
3115 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3116 return;
3118 for (x = 0; x < MAX_SLAVES; x++) {
3119 if (!master->slaves[x]) {
3120 master->slaves[x] = slave;
3121 break;
3124 if (x >= MAX_SLAVES) {
3125 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3126 master->slaves[MAX_SLAVES - 1] = slave;
3128 if (slave->master)
3129 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3130 slave->master = master;
3132 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3135 static void disable_dtmf_detect(struct dahdi_pvt *p)
3137 #ifdef DAHDI_TONEDETECT
3138 int val;
3139 #endif
3141 p->ignoredtmf = 1;
3143 #ifdef DAHDI_TONEDETECT
3144 val = 0;
3145 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3146 #endif
3147 if (!p->hardwaredtmf && p->dsp) {
3148 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3149 ast_dsp_set_features(p->dsp, p->dsp_features);
3153 static void enable_dtmf_detect(struct dahdi_pvt *p)
3155 #ifdef DAHDI_TONEDETECT
3156 int val;
3157 #endif
3159 if (p->channel == CHAN_PSEUDO)
3160 return;
3162 p->ignoredtmf = 0;
3164 #ifdef DAHDI_TONEDETECT
3165 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3166 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3167 #endif
3168 if (!p->hardwaredtmf && p->dsp) {
3169 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3170 ast_dsp_set_features(p->dsp, p->dsp_features);
3174 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)
3176 struct ast_channel *who;
3177 struct dahdi_pvt *p0, *p1, *op0, *op1;
3178 struct dahdi_pvt *master = NULL, *slave = NULL;
3179 struct ast_frame *f;
3180 int inconf = 0;
3181 int nothingok = 1;
3182 int ofd0, ofd1;
3183 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3184 int os0 = -1, os1 = -1;
3185 int priority = 0;
3186 struct ast_channel *oc0, *oc1;
3187 enum ast_bridge_result res;
3189 #ifdef PRI_2BCT
3190 int triedtopribridge = 0;
3191 q931_call *q931c0 = NULL, *q931c1 = NULL;
3192 #endif
3194 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3195 There is code below to handle it properly until DTMF is actually seen,
3196 but due to currently unresolved issues it's ignored...
3199 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3200 return AST_BRIDGE_FAILED_NOWARN;
3202 ast_mutex_lock(&c0->lock);
3203 while (ast_mutex_trylock(&c1->lock)) {
3204 DEADLOCK_AVOIDANCE(&c0->lock);
3207 p0 = c0->tech_pvt;
3208 p1 = c1->tech_pvt;
3209 /* cant do pseudo-channels here */
3210 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3211 ast_mutex_unlock(&c0->lock);
3212 ast_mutex_unlock(&c1->lock);
3213 return AST_BRIDGE_FAILED_NOWARN;
3216 oi0 = dahdi_get_index(c0, p0, 0);
3217 oi1 = dahdi_get_index(c1, p1, 0);
3218 if ((oi0 < 0) || (oi1 < 0)) {
3219 ast_mutex_unlock(&c0->lock);
3220 ast_mutex_unlock(&c1->lock);
3221 return AST_BRIDGE_FAILED;
3224 op0 = p0 = c0->tech_pvt;
3225 op1 = p1 = c1->tech_pvt;
3226 ofd0 = c0->fds[0];
3227 ofd1 = c1->fds[0];
3228 oc0 = p0->owner;
3229 oc1 = p1->owner;
3231 if (ast_mutex_trylock(&p0->lock)) {
3232 /* Don't block, due to potential for deadlock */
3233 ast_mutex_unlock(&c0->lock);
3234 ast_mutex_unlock(&c1->lock);
3235 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3236 return AST_BRIDGE_RETRY;
3238 if (ast_mutex_trylock(&p1->lock)) {
3239 /* Don't block, due to potential for deadlock */
3240 ast_mutex_unlock(&p0->lock);
3241 ast_mutex_unlock(&c0->lock);
3242 ast_mutex_unlock(&c1->lock);
3243 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3244 return AST_BRIDGE_RETRY;
3247 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3248 if (p0->owner && p1->owner) {
3249 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3250 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3251 master = p0;
3252 slave = p1;
3253 inconf = 1;
3254 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3255 master = p1;
3256 slave = p0;
3257 inconf = 1;
3258 } else {
3259 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3260 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3261 p0->channel,
3262 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3263 p0->subs[SUB_REAL].inthreeway, p0->channel,
3264 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3265 p1->subs[SUB_REAL].inthreeway);
3267 nothingok = 0;
3269 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3270 if (p1->subs[SUB_THREEWAY].inthreeway) {
3271 master = p1;
3272 slave = p0;
3273 nothingok = 0;
3275 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3276 if (p0->subs[SUB_THREEWAY].inthreeway) {
3277 master = p0;
3278 slave = p1;
3279 nothingok = 0;
3281 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3282 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3283 don't put us in anything */
3284 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3285 master = p1;
3286 slave = p0;
3287 nothingok = 0;
3289 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3290 /* Same as previous */
3291 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3292 master = p0;
3293 slave = p1;
3294 nothingok = 0;
3297 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3298 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3299 if (master && slave) {
3300 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3301 in an active threeway call with a channel that is ringing, we should
3302 indicate ringing. */
3303 if ((oi1 == SUB_THREEWAY) &&
3304 p1->subs[SUB_THREEWAY].inthreeway &&
3305 p1->subs[SUB_REAL].owner &&
3306 p1->subs[SUB_REAL].inthreeway &&
3307 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3308 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3309 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3310 os1 = p1->subs[SUB_REAL].owner->_state;
3311 } else {
3312 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3313 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3315 if ((oi0 == SUB_THREEWAY) &&
3316 p0->subs[SUB_THREEWAY].inthreeway &&
3317 p0->subs[SUB_REAL].owner &&
3318 p0->subs[SUB_REAL].inthreeway &&
3319 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3320 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3321 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3322 os0 = p0->subs[SUB_REAL].owner->_state;
3323 } else {
3324 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3325 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3327 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3328 if (!p0->echocanbridged || !p1->echocanbridged) {
3329 /* Disable echo cancellation if appropriate */
3330 dahdi_disable_ec(p0);
3331 dahdi_disable_ec(p1);
3334 dahdi_link(slave, master);
3335 master->inconference = inconf;
3336 } else if (!nothingok)
3337 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3339 update_conf(p0);
3340 update_conf(p1);
3341 t0 = p0->subs[SUB_REAL].inthreeway;
3342 t1 = p1->subs[SUB_REAL].inthreeway;
3344 ast_mutex_unlock(&p0->lock);
3345 ast_mutex_unlock(&p1->lock);
3347 ast_mutex_unlock(&c0->lock);
3348 ast_mutex_unlock(&c1->lock);
3350 /* Native bridge failed */
3351 if ((!master || !slave) && !nothingok) {
3352 dahdi_enable_ec(p0);
3353 dahdi_enable_ec(p1);
3354 return AST_BRIDGE_FAILED;
3357 if (option_verbose > 2)
3358 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3360 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3361 disable_dtmf_detect(op0);
3363 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3364 disable_dtmf_detect(op1);
3366 for (;;) {
3367 struct ast_channel *c0_priority[2] = {c0, c1};
3368 struct ast_channel *c1_priority[2] = {c1, c0};
3370 /* Here's our main loop... Start by locking things, looking for private parts,
3371 and then balking if anything is wrong */
3372 ast_mutex_lock(&c0->lock);
3373 while (ast_mutex_trylock(&c1->lock)) {
3374 DEADLOCK_AVOIDANCE(&c0->lock);
3377 p0 = c0->tech_pvt;
3378 p1 = c1->tech_pvt;
3380 if (op0 == p0)
3381 i0 = dahdi_get_index(c0, p0, 1);
3382 if (op1 == p1)
3383 i1 = dahdi_get_index(c1, p1, 1);
3384 ast_mutex_unlock(&c0->lock);
3385 ast_mutex_unlock(&c1->lock);
3387 if (!timeoutms ||
3388 (op0 != p0) ||
3389 (op1 != p1) ||
3390 (ofd0 != c0->fds[0]) ||
3391 (ofd1 != c1->fds[0]) ||
3392 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3393 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3394 (oc0 != p0->owner) ||
3395 (oc1 != p1->owner) ||
3396 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3397 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3398 (oi0 != i0) ||
3399 (oi1 != i1)) {
3400 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3401 op0->channel, oi0, op1->channel, oi1);
3402 res = AST_BRIDGE_RETRY;
3403 goto return_from_bridge;
3406 #ifdef PRI_2BCT
3407 q931c0 = p0->call;
3408 q931c1 = p1->call;
3409 if (p0->transfer && p1->transfer
3410 && q931c0 && q931c1
3411 && !triedtopribridge) {
3412 pri_channel_bridge(q931c0, q931c1);
3413 triedtopribridge = 1;
3415 #endif
3417 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3418 if (!who) {
3419 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3420 continue;
3422 f = ast_read(who);
3423 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3424 *fo = f;
3425 *rc = who;
3426 res = AST_BRIDGE_COMPLETE;
3427 goto return_from_bridge;
3429 if (f->frametype == AST_FRAME_DTMF) {
3430 if ((who == c0) && p0->pulsedial) {
3431 ast_write(c1, f);
3432 } else if ((who == c1) && p1->pulsedial) {
3433 ast_write(c0, f);
3434 } else {
3435 *fo = f;
3436 *rc = who;
3437 res = AST_BRIDGE_COMPLETE;
3438 goto return_from_bridge;
3441 ast_frfree(f);
3443 /* Swap who gets priority */
3444 priority = !priority;
3447 return_from_bridge:
3448 if (op0 == p0)
3449 dahdi_enable_ec(p0);
3451 if (op1 == p1)
3452 dahdi_enable_ec(p1);
3454 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3455 enable_dtmf_detect(op0);
3457 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3458 enable_dtmf_detect(op1);
3460 dahdi_unlink(slave, master, 1);
3462 return res;
3465 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3467 struct dahdi_pvt *p = newchan->tech_pvt;
3468 int x;
3469 ast_mutex_lock(&p->lock);
3470 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3471 if (p->owner == oldchan) {
3472 p->owner = newchan;
3474 for (x = 0; x < 3; x++)
3475 if (p->subs[x].owner == oldchan) {
3476 if (!x)
3477 dahdi_unlink(NULL, p, 0);
3478 p->subs[x].owner = newchan;
3480 if (newchan->_state == AST_STATE_RINGING)
3481 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3482 update_conf(p);
3483 ast_mutex_unlock(&p->lock);
3484 return 0;
3487 static int dahdi_ring_phone(struct dahdi_pvt *p)
3489 int x;
3490 int res;
3491 /* Make sure our transmit state is on hook */
3492 x = 0;
3493 x = DAHDI_ONHOOK;
3494 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3495 do {
3496 x = DAHDI_RING;
3497 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3498 if (res) {
3499 switch (errno) {
3500 case EBUSY:
3501 case EINTR:
3502 /* Wait just in case */
3503 usleep(10000);
3504 continue;
3505 case EINPROGRESS:
3506 res = 0;
3507 break;
3508 default:
3509 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3510 res = 0;
3513 } while (res);
3514 return res;
3517 static void *ss_thread(void *data);
3519 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3521 static int attempt_transfer(struct dahdi_pvt *p)
3523 /* In order to transfer, we need at least one of the channels to
3524 actually be in a call bridge. We can't conference two applications
3525 together (but then, why would we want to?) */
3526 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3527 /* The three-way person we're about to transfer to could still be in MOH, so
3528 stop if now if appropriate */
3529 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3530 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3531 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3532 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3534 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3535 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3537 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3538 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3539 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3540 return -1;
3542 /* Orphan the channel after releasing the lock */
3543 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3544 unalloc_sub(p, SUB_THREEWAY);
3545 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3546 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3547 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3548 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3550 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3551 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3553 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3554 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3555 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3556 return -1;
3558 /* Three-way is now the REAL */
3559 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3560 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3561 unalloc_sub(p, SUB_THREEWAY);
3562 /* Tell the caller not to hangup */
3563 return 1;
3564 } else {
3565 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3566 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3567 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3568 return -1;
3570 return 0;
3573 static int check_for_conference(struct dahdi_pvt *p)
3575 DAHDI_CONFINFO ci;
3576 /* Fine if we already have a master, etc */
3577 if (p->master || (p->confno > -1))
3578 return 0;
3579 memset(&ci, 0, sizeof(ci));
3580 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3581 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3582 return 0;
3584 /* If we have no master and don't have a confno, then
3585 if we're in a conference, it's probably a MeetMe room or
3586 some such, so don't let us 3-way out! */
3587 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3588 if (option_verbose > 2)
3589 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3590 return 1;
3592 return 0;
3595 static int get_alarms(struct dahdi_pvt *p)
3597 int res;
3598 DAHDI_SPANINFO zi;
3599 memset(&zi, 0, sizeof(zi));
3600 zi.spanno = p->span;
3601 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi);
3602 if (res < 0) {
3603 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3604 return 0;
3606 return zi.alarms;
3609 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3611 struct dahdi_pvt *p = ast->tech_pvt;
3612 struct ast_frame *f = *dest;
3614 if (option_debug)
3615 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3617 if (p->confirmanswer) {
3618 if (option_debug)
3619 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3620 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3621 of a DTMF digit */
3622 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3623 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3624 *dest = &p->subs[index].f;
3625 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3626 p->confirmanswer = 0;
3627 } else if (p->callwaitcas) {
3628 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3629 if (option_debug)
3630 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3631 if (p->cidspill)
3632 free(p->cidspill);
3633 send_cwcidspill(p);
3635 if ((f->subclass != 'm') && (f->subclass != 'u'))
3636 p->callwaitcas = 0;
3637 p->subs[index].f.frametype = AST_FRAME_NULL;
3638 p->subs[index].f.subclass = 0;
3639 *dest = &p->subs[index].f;
3640 } else if (f->subclass == 'f') {
3641 /* Fax tone -- Handle and return NULL */
3642 if ((p->callprogress & 0x6) && !p->faxhandled) {
3643 p->faxhandled++;
3644 if (strcmp(ast->exten, "fax")) {
3645 const char *target_context = S_OR(ast->macrocontext, ast->context);
3647 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3648 if (option_verbose > 2)
3649 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3650 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3651 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3652 if (ast_async_goto(ast, target_context, "fax", 1))
3653 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3654 } else
3655 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3656 } else if (option_debug)
3657 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3658 } else if (option_debug)
3659 ast_log(LOG_DEBUG, "Fax already handled\n");
3660 dahdi_confmute(p, 0);
3661 p->subs[index].f.frametype = AST_FRAME_NULL;
3662 p->subs[index].f.subclass = 0;
3663 *dest = &p->subs[index].f;
3664 } else if (f->subclass == 'm') {
3665 /* Confmute request */
3666 dahdi_confmute(p, 1);
3667 p->subs[index].f.frametype = AST_FRAME_NULL;
3668 p->subs[index].f.subclass = 0;
3669 *dest = &p->subs[index].f;
3670 } else if (f->subclass == 'u') {
3671 /* Unmute */
3672 dahdi_confmute(p, 0);
3673 p->subs[index].f.frametype = AST_FRAME_NULL;
3674 p->subs[index].f.subclass = 0;
3675 *dest = &p->subs[index].f;
3676 } else
3677 dahdi_confmute(p, 0);
3680 static void handle_alarms(struct dahdi_pvt *p, int alarms)
3682 const char *alarm_str = alarm2str(alarms);
3684 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3685 * doesn't know what to do with it. Don't confuse users with log messages. */
3686 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3687 p->unknown_alarm = 1;
3688 return;
3689 } else {
3690 p->unknown_alarm = 0;
3693 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3694 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3695 "Alarm: %s\r\n"
3696 "Channel: %d\r\n",
3697 alarm_str, p->channel);
3700 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
3702 int res, x;
3703 int index, mysig;
3704 char *c;
3705 struct dahdi_pvt *p = ast->tech_pvt;
3706 pthread_t threadid;
3707 pthread_attr_t attr;
3708 struct ast_channel *chan;
3709 struct ast_frame *f;
3711 index = dahdi_get_index(ast, p, 0);
3712 mysig = p->sig;
3713 if (p->outsigmod > -1)
3714 mysig = p->outsigmod;
3715 p->subs[index].f.frametype = AST_FRAME_NULL;
3716 p->subs[index].f.subclass = 0;
3717 p->subs[index].f.datalen = 0;
3718 p->subs[index].f.samples = 0;
3719 p->subs[index].f.mallocd = 0;
3720 p->subs[index].f.offset = 0;
3721 p->subs[index].f.src = "dahdi_handle_event";
3722 p->subs[index].f.data = NULL;
3723 f = &p->subs[index].f;
3725 if (index < 0)
3726 return &p->subs[index].f;
3727 if (p->fake_event) {
3728 res = p->fake_event;
3729 p->fake_event = 0;
3730 } else
3731 res = dahdi_get_event(p->subs[index].dfd);
3733 if (option_debug)
3734 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
3736 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
3737 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
3739 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
3740 #ifdef HAVE_PRI
3741 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
3742 /* absorb event */
3743 } else {
3744 #endif
3745 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
3746 p->subs[index].f.subclass = res & 0xff;
3747 #ifdef HAVE_PRI
3749 #endif
3750 dahdi_handle_dtmfup(ast, index, &f);
3751 return f;
3754 if (res & DAHDI_EVENT_DTMFDOWN) {
3755 if (option_debug)
3756 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
3757 /* Mute conference */
3758 dahdi_confmute(p, 1);
3759 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
3760 p->subs[index].f.subclass = res & 0xff;
3761 return &p->subs[index].f;
3764 switch (res) {
3765 #ifdef DAHDI_EVENT_EC_DISABLED
3766 case DAHDI_EVENT_EC_DISABLED:
3767 if (option_verbose > 2)
3768 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
3769 p->echocanon = 0;
3770 break;
3771 #endif
3772 case DAHDI_EVENT_BITSCHANGED:
3773 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
3774 case DAHDI_EVENT_PULSE_START:
3775 /* Stop tone if there's a pulse start and the PBX isn't started */
3776 if (!ast->pbx)
3777 tone_zone_play_tone(p->subs[index].dfd, -1);
3778 break;
3779 case DAHDI_EVENT_DIALCOMPLETE:
3780 if (p->inalarm) break;
3781 if ((p->radio || (p->oprmode < 0))) break;
3782 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
3783 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
3784 return NULL;
3786 if (!x) { /* if not still dialing in driver */
3787 dahdi_enable_ec(p);
3788 if (p->echobreak) {
3789 dahdi_train_ec(p);
3790 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
3791 p->dop.op = DAHDI_DIAL_OP_REPLACE;
3792 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
3793 p->echobreak = 0;
3794 } else {
3795 p->dialing = 0;
3796 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
3797 /* if thru with dialing after offhook */
3798 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
3799 ast_setstate(ast, AST_STATE_UP);
3800 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3801 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3802 break;
3803 } else { /* if to state wait for offhook to dial rest */
3804 /* we now wait for off hook */
3805 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
3808 if (ast->_state == AST_STATE_DIALING) {
3809 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3810 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
3811 } 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)))) {
3812 ast_setstate(ast, AST_STATE_RINGING);
3813 } else if (!p->answeronpolarityswitch) {
3814 ast_setstate(ast, AST_STATE_UP);
3815 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3816 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3817 /* If aops=0 and hops=1, this is necessary */
3818 p->polarity = POLARITY_REV;
3819 } else {
3820 /* Start clean, so we can catch the change to REV polarity when party answers */
3821 p->polarity = POLARITY_IDLE;
3826 break;
3827 case DAHDI_EVENT_ALARM:
3828 #ifdef HAVE_PRI
3829 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
3830 /* T309 is not enabled : hangup calls when alarm occurs */
3831 if (p->call) {
3832 if (p->pri && p->pri->pri) {
3833 if (!pri_grab(p, p->pri)) {
3834 pri_hangup(p->pri->pri, p->call, -1);
3835 pri_destroycall(p->pri->pri, p->call);
3836 p->call = NULL;
3837 pri_rel(p->pri);
3838 } else
3839 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3840 } else
3841 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
3843 if (p->owner)
3844 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3846 if (p->bearer)
3847 p->bearer->inalarm = 1;
3848 else
3849 #endif
3850 p->inalarm = 1;
3851 res = get_alarms(p);
3852 handle_alarms(p, res);
3853 #ifdef HAVE_LIBPRI
3854 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3855 /* fall through intentionally */
3856 } else {
3857 break;
3859 #endif
3860 case DAHDI_EVENT_ONHOOK:
3861 if (p->radio) {
3862 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3863 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
3864 break;
3866 if (p->oprmode < 0)
3868 if (p->oprmode != -1) break;
3869 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3871 /* Make sure it starts ringing */
3872 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3873 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
3874 save_conference(p->oprpeer);
3875 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3877 break;
3879 switch (p->sig) {
3880 case SIG_FXOLS:
3881 case SIG_FXOGS:
3882 case SIG_FXOKS:
3883 p->onhooktime = time(NULL);
3884 p->msgstate = -1;
3885 /* Check for some special conditions regarding call waiting */
3886 if (index == SUB_REAL) {
3887 /* The normal line was hung up */
3888 if (p->subs[SUB_CALLWAIT].owner) {
3889 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3890 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3891 if (option_verbose > 2)
3892 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
3893 unalloc_sub(p, SUB_CALLWAIT);
3894 #if 0
3895 p->subs[index].needanswer = 0;
3896 p->subs[index].needringing = 0;
3897 #endif
3898 p->callwaitingrepeat = 0;
3899 p->cidcwexpire = 0;
3900 p->owner = NULL;
3901 /* Don't start streaming audio yet if the incoming call isn't up yet */
3902 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
3903 p->dialing = 1;
3904 dahdi_ring_phone(p);
3905 } else if (p->subs[SUB_THREEWAY].owner) {
3906 unsigned int mssinceflash;
3907 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3908 the private structure -- not especially easy or clean */
3909 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
3910 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3911 ast_mutex_unlock(&p->lock);
3912 DEADLOCK_AVOIDANCE(&ast->lock);
3913 /* We can grab ast and p in that order, without worry. We should make sure
3914 nothing seriously bad has happened though like some sort of bizarre double
3915 masquerade! */
3916 ast_mutex_lock(&p->lock);
3917 if (p->owner != ast) {
3918 ast_log(LOG_WARNING, "This isn't good...\n");
3919 return NULL;
3922 if (!p->subs[SUB_THREEWAY].owner) {
3923 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
3924 return NULL;
3926 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
3927 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
3928 if (mssinceflash < MIN_MS_SINCE_FLASH) {
3929 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3930 hanging up. Hangup both channels now */
3931 if (p->subs[SUB_THREEWAY].owner)
3932 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
3933 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3934 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
3935 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3936 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
3937 if (p->transfer) {
3938 /* In any case this isn't a threeway call anymore */
3939 p->subs[SUB_REAL].inthreeway = 0;
3940 p->subs[SUB_THREEWAY].inthreeway = 0;
3941 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
3942 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
3943 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3944 /* Swap subs and dis-own channel */
3945 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3946 p->owner = NULL;
3947 /* Ring the phone */
3948 dahdi_ring_phone(p);
3949 } else {
3950 if ((res = attempt_transfer(p)) < 0) {
3951 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3952 if (p->subs[SUB_THREEWAY].owner)
3953 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3954 } else if (res) {
3955 /* Don't actually hang up at this point */
3956 if (p->subs[SUB_THREEWAY].owner)
3957 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3958 break;
3961 } else {
3962 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3963 if (p->subs[SUB_THREEWAY].owner)
3964 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3966 } else {
3967 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3968 /* Swap subs and dis-own channel */
3969 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3970 p->owner = NULL;
3971 /* Ring the phone */
3972 dahdi_ring_phone(p);
3975 } else {
3976 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
3978 /* Fall through */
3979 default:
3980 dahdi_disable_ec(p);
3981 return NULL;
3983 break;
3984 case DAHDI_EVENT_RINGOFFHOOK:
3985 if (p->inalarm) break;
3986 if (p->oprmode < 0)
3988 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3990 /* Make sure it stops ringing */
3991 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3992 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
3993 restore_conference(p->oprpeer);
3995 break;
3997 if (p->radio)
3999 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4000 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4001 break;
4003 /* for E911, its supposed to wait for offhook then dial
4004 the second half of the dial string */
4005 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
4006 c = strchr(p->dialdest, '/');
4007 if (c)
4008 c++;
4009 else
4010 c = p->dialdest;
4011 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
4012 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
4013 if (strlen(p->dop.dialstr) > 4) {
4014 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
4015 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
4016 p->echorest[sizeof(p->echorest) - 1] = '\0';
4017 p->echobreak = 1;
4018 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
4019 } else
4020 p->echobreak = 0;
4021 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
4022 int saveerr = errno;
4024 x = DAHDI_ONHOOK;
4025 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4026 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4027 return NULL;
4029 p->dialing = 1;
4030 return &p->subs[index].f;
4032 switch (p->sig) {
4033 case SIG_FXOLS:
4034 case SIG_FXOGS:
4035 case SIG_FXOKS:
4036 switch (ast->_state) {
4037 case AST_STATE_RINGING:
4038 dahdi_enable_ec(p);
4039 dahdi_train_ec(p);
4040 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4041 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4042 /* Make sure it stops ringing */
4043 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4044 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4045 if (p->cidspill) {
4046 /* Cancel any running CallerID spill */
4047 free(p->cidspill);
4048 p->cidspill = NULL;
4050 p->dialing = 0;
4051 p->callwaitcas = 0;
4052 if (p->confirmanswer) {
4053 /* Ignore answer if "confirm answer" is enabled */
4054 p->subs[index].f.frametype = AST_FRAME_NULL;
4055 p->subs[index].f.subclass = 0;
4056 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4057 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4058 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4059 if (res < 0) {
4060 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4061 p->dop.dialstr[0] = '\0';
4062 return NULL;
4063 } else {
4064 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4065 p->subs[index].f.frametype = AST_FRAME_NULL;
4066 p->subs[index].f.subclass = 0;
4067 p->dialing = 1;
4069 p->dop.dialstr[0] = '\0';
4070 ast_setstate(ast, AST_STATE_DIALING);
4071 } else
4072 ast_setstate(ast, AST_STATE_UP);
4073 return &p->subs[index].f;
4074 case AST_STATE_DOWN:
4075 ast_setstate(ast, AST_STATE_RING);
4076 ast->rings = 1;
4077 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4078 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4079 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4080 return &p->subs[index].f;
4081 case AST_STATE_UP:
4082 /* Make sure it stops ringing */
4083 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4084 /* Okay -- probably call waiting*/
4085 if (ast_bridged_channel(p->owner))
4086 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4087 p->subs[index].needunhold = 1;
4088 break;
4089 case AST_STATE_RESERVED:
4090 /* Start up dialtone */
4091 if (has_voicemail(p))
4092 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4093 else
4094 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4095 break;
4096 default:
4097 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4099 break;
4100 case SIG_FXSLS:
4101 case SIG_FXSGS:
4102 case SIG_FXSKS:
4103 if (ast->_state == AST_STATE_RING) {
4104 p->ringt = p->ringt_base;
4107 /* Fall through */
4108 case SIG_EM:
4109 case SIG_EM_E1:
4110 case SIG_EMWINK:
4111 case SIG_FEATD:
4112 case SIG_FEATDMF:
4113 case SIG_FEATDMF_TA:
4114 case SIG_E911:
4115 case SIG_FGC_CAMA:
4116 case SIG_FGC_CAMAMF:
4117 case SIG_FEATB:
4118 case SIG_SF:
4119 case SIG_SFWINK:
4120 case SIG_SF_FEATD:
4121 case SIG_SF_FEATDMF:
4122 case SIG_SF_FEATB:
4123 if (ast->_state == AST_STATE_PRERING)
4124 ast_setstate(ast, AST_STATE_RING);
4125 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4126 if (option_debug)
4127 ast_log(LOG_DEBUG, "Ring detected\n");
4128 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4129 p->subs[index].f.subclass = AST_CONTROL_RING;
4130 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4131 if (option_debug)
4132 ast_log(LOG_DEBUG, "Line answered\n");
4133 if (p->confirmanswer) {
4134 p->subs[index].f.frametype = AST_FRAME_NULL;
4135 p->subs[index].f.subclass = 0;
4136 } else {
4137 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4138 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4139 ast_setstate(ast, AST_STATE_UP);
4141 } else if (ast->_state != AST_STATE_RING)
4142 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4143 break;
4144 default:
4145 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4147 break;
4148 #ifdef DAHDI_EVENT_RINGBEGIN
4149 case DAHDI_EVENT_RINGBEGIN:
4150 switch (p->sig) {
4151 case SIG_FXSLS:
4152 case SIG_FXSGS:
4153 case SIG_FXSKS:
4154 if (ast->_state == AST_STATE_RING) {
4155 p->ringt = p->ringt_base;
4157 break;
4159 break;
4160 #endif
4161 case DAHDI_EVENT_RINGEROFF:
4162 if (p->inalarm) break;
4163 if ((p->radio || (p->oprmode < 0))) break;
4164 ast->rings++;
4165 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4166 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4167 free(p->cidspill);
4168 p->cidspill = NULL;
4169 p->callwaitcas = 0;
4171 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4172 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4173 break;
4174 case DAHDI_EVENT_RINGERON:
4175 break;
4176 case DAHDI_EVENT_NOALARM:
4177 p->inalarm = 0;
4178 #ifdef HAVE_PRI
4179 /* Extremely unlikely but just in case */
4180 if (p->bearer)
4181 p->bearer->inalarm = 0;
4182 #endif
4183 if (!p->unknown_alarm) {
4184 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4185 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4186 "Channel: %d\r\n", p->channel);
4187 } else {
4188 p->unknown_alarm = 0;
4190 break;
4191 case DAHDI_EVENT_WINKFLASH:
4192 if (p->inalarm) break;
4193 if (p->radio) break;
4194 if (p->oprmode < 0) break;
4195 if (p->oprmode > 1)
4197 DAHDI_PARAMS par;
4199 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4201 if (!par.rxisoffhook)
4203 /* Make sure it stops ringing */
4204 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4205 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4206 save_conference(p);
4207 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4210 break;
4212 /* Remember last time we got a flash-hook */
4213 gettimeofday(&p->flashtime, NULL);
4214 switch (mysig) {
4215 case SIG_FXOLS:
4216 case SIG_FXOGS:
4217 case SIG_FXOKS:
4218 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4219 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4220 p->callwaitcas = 0;
4222 if (index != SUB_REAL) {
4223 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4224 goto winkflashdone;
4227 if (p->subs[SUB_CALLWAIT].owner) {
4228 /* Swap to call-wait */
4229 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4230 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4231 p->owner = p->subs[SUB_REAL].owner;
4232 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4233 if (p->owner->_state == AST_STATE_RINGING) {
4234 ast_setstate(p->owner, AST_STATE_UP);
4235 p->subs[SUB_REAL].needanswer = 1;
4237 p->callwaitingrepeat = 0;
4238 p->cidcwexpire = 0;
4239 /* Start music on hold if appropriate */
4240 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4241 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4242 S_OR(p->mohsuggest, NULL),
4243 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4245 p->subs[SUB_CALLWAIT].needhold = 1;
4246 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4247 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4248 S_OR(p->mohsuggest, NULL),
4249 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4251 p->subs[SUB_REAL].needunhold = 1;
4252 } else if (!p->subs[SUB_THREEWAY].owner) {
4253 char cid_num[256];
4254 char cid_name[256];
4256 if (!p->threewaycalling) {
4257 /* Just send a flash if no 3-way calling */
4258 p->subs[SUB_REAL].needflash = 1;
4259 goto winkflashdone;
4260 } else if (!check_for_conference(p)) {
4261 if (p->dahditrcallerid && p->owner) {
4262 if (p->owner->cid.cid_num)
4263 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4264 if (p->owner->cid.cid_name)
4265 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4267 /* XXX This section needs much more error checking!!! XXX */
4268 /* Start a 3-way call if feasible */
4269 if (!((ast->pbx) ||
4270 (ast->_state == AST_STATE_UP) ||
4271 (ast->_state == AST_STATE_RING))) {
4272 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4273 goto winkflashdone;
4275 if (alloc_sub(p, SUB_THREEWAY)) {
4276 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4277 goto winkflashdone;
4279 /* Make new channel */
4280 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4281 if (p->dahditrcallerid) {
4282 if (!p->origcid_num)
4283 p->origcid_num = ast_strdup(p->cid_num);
4284 if (!p->origcid_name)
4285 p->origcid_name = ast_strdup(p->cid_name);
4286 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4287 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4289 /* Swap things around between the three-way and real call */
4290 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4291 /* Disable echo canceller for better dialing */
4292 dahdi_disable_ec(p);
4293 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4294 if (res)
4295 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4296 p->owner = chan;
4297 pthread_attr_init(&attr);
4298 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4299 if (!chan) {
4300 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4301 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4302 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4303 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4304 dahdi_enable_ec(p);
4305 ast_hangup(chan);
4306 } else {
4307 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4308 int way3bridge = 0, cdr3way = 0;
4310 if (!other) {
4311 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4312 } else
4313 way3bridge = 1;
4315 if (p->subs[SUB_THREEWAY].owner->cdr)
4316 cdr3way = 1;
4318 if (option_verbose > 2)
4319 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4320 /* Start music on hold if appropriate */
4321 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4322 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4323 S_OR(p->mohsuggest, NULL),
4324 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4326 p->subs[SUB_THREEWAY].needhold = 1;
4328 pthread_attr_destroy(&attr);
4330 } else {
4331 /* Already have a 3 way call */
4332 if (p->subs[SUB_THREEWAY].inthreeway) {
4333 /* Call is already up, drop the last person */
4334 if (option_debug)
4335 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4336 /* If the primary call isn't answered yet, use it */
4337 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4338 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4339 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4340 p->owner = p->subs[SUB_REAL].owner;
4342 /* Drop the last call and stop the conference */
4343 if (option_verbose > 2)
4344 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4345 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4346 p->subs[SUB_REAL].inthreeway = 0;
4347 p->subs[SUB_THREEWAY].inthreeway = 0;
4348 } else {
4349 /* Lets see what we're up to */
4350 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4351 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4352 int otherindex = SUB_THREEWAY;
4353 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4354 int way3bridge = 0, cdr3way = 0;
4356 if (!other) {
4357 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4358 } else
4359 way3bridge = 1;
4361 if (p->subs[SUB_THREEWAY].owner->cdr)
4362 cdr3way = 1;
4364 if (option_verbose > 2)
4365 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);
4366 /* Put them in the threeway, and flip */
4367 p->subs[SUB_THREEWAY].inthreeway = 1;
4368 p->subs[SUB_REAL].inthreeway = 1;
4369 if (ast->_state == AST_STATE_UP) {
4370 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4371 otherindex = SUB_REAL;
4373 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4374 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4375 p->subs[otherindex].needunhold = 1;
4376 p->owner = p->subs[SUB_REAL].owner;
4377 if (ast->_state == AST_STATE_RINGING) {
4378 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4379 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4380 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4382 } else {
4383 if (option_verbose > 2)
4384 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4385 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4386 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4387 p->owner = p->subs[SUB_REAL].owner;
4388 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4389 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4390 p->subs[SUB_REAL].needunhold = 1;
4391 dahdi_enable_ec(p);
4396 winkflashdone:
4397 update_conf(p);
4398 break;
4399 case SIG_EM:
4400 case SIG_EM_E1:
4401 case SIG_EMWINK:
4402 case SIG_FEATD:
4403 case SIG_SF:
4404 case SIG_SFWINK:
4405 case SIG_SF_FEATD:
4406 case SIG_FXSLS:
4407 case SIG_FXSGS:
4408 if (p->dialing)
4409 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4410 else
4411 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4412 break;
4413 case SIG_FEATDMF_TA:
4414 switch (p->whichwink) {
4415 case 0:
4416 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4417 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4418 break;
4419 case 1:
4420 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4421 break;
4422 case 2:
4423 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4424 return NULL;
4426 p->whichwink++;
4427 /* Fall through */
4428 case SIG_FEATDMF:
4429 case SIG_E911:
4430 case SIG_FGC_CAMAMF:
4431 case SIG_FGC_CAMA:
4432 case SIG_FEATB:
4433 case SIG_SF_FEATDMF:
4434 case SIG_SF_FEATB:
4435 /* FGD MF *Must* wait for wink */
4436 if (!ast_strlen_zero(p->dop.dialstr)) {
4437 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4438 if (res < 0) {
4439 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4440 p->dop.dialstr[0] = '\0';
4441 return NULL;
4442 } else
4443 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4445 p->dop.dialstr[0] = '\0';
4446 break;
4447 default:
4448 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4450 break;
4451 case DAHDI_EVENT_HOOKCOMPLETE:
4452 if (p->inalarm) break;
4453 if ((p->radio || (p->oprmode < 0))) break;
4454 switch (mysig) {
4455 case SIG_FXSLS: /* only interesting for FXS */
4456 case SIG_FXSGS:
4457 case SIG_FXSKS:
4458 case SIG_EM:
4459 case SIG_EM_E1:
4460 case SIG_EMWINK:
4461 case SIG_FEATD:
4462 case SIG_SF:
4463 case SIG_SFWINK:
4464 case SIG_SF_FEATD:
4465 if (!ast_strlen_zero(p->dop.dialstr)) {
4466 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4467 if (res < 0) {
4468 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4469 p->dop.dialstr[0] = '\0';
4470 return NULL;
4471 } else
4472 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4474 p->dop.dialstr[0] = '\0';
4475 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4476 break;
4477 case SIG_FEATDMF:
4478 case SIG_FEATDMF_TA:
4479 case SIG_E911:
4480 case SIG_FGC_CAMA:
4481 case SIG_FGC_CAMAMF:
4482 case SIG_FEATB:
4483 case SIG_SF_FEATDMF:
4484 case SIG_SF_FEATB:
4485 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4486 break;
4487 default:
4488 break;
4490 break;
4491 case DAHDI_EVENT_POLARITY:
4493 * If we get a Polarity Switch event, check to see
4494 * if we should change the polarity state and
4495 * mark the channel as UP or if this is an indication
4496 * of remote end disconnect.
4498 if (p->polarity == POLARITY_IDLE) {
4499 p->polarity = POLARITY_REV;
4500 if (p->answeronpolarityswitch &&
4501 ((ast->_state == AST_STATE_DIALING) ||
4502 (ast->_state == AST_STATE_RINGING))) {
4503 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4504 ast_setstate(p->owner, AST_STATE_UP);
4505 if (p->hanguponpolarityswitch) {
4506 gettimeofday(&p->polaritydelaytv, NULL);
4508 } else
4509 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4511 /* Removed else statement from here as it was preventing hangups from ever happening*/
4512 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4513 if (p->hanguponpolarityswitch &&
4514 (p->polarityonanswerdelay > 0) &&
4515 (p->polarity == POLARITY_REV) &&
4516 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4517 /* Added log_debug information below to provide a better indication of what is going on */
4518 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) );
4520 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4521 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4522 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4523 p->polarity = POLARITY_IDLE;
4524 } else {
4525 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);
4527 } else {
4528 p->polarity = POLARITY_IDLE;
4529 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4531 /* Added more log_debug information below to provide a better indication of what is going on */
4532 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) );
4533 break;
4534 default:
4535 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4537 return &p->subs[index].f;
4540 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4542 struct dahdi_pvt *p = ast->tech_pvt;
4543 int res;
4544 int usedindex=-1;
4545 int index;
4546 struct ast_frame *f;
4549 index = dahdi_get_index(ast, p, 1);
4551 p->subs[index].f.frametype = AST_FRAME_NULL;
4552 p->subs[index].f.datalen = 0;
4553 p->subs[index].f.samples = 0;
4554 p->subs[index].f.mallocd = 0;
4555 p->subs[index].f.offset = 0;
4556 p->subs[index].f.subclass = 0;
4557 p->subs[index].f.delivery = ast_tv(0,0);
4558 p->subs[index].f.src = "dahdi_exception";
4559 p->subs[index].f.data = NULL;
4562 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4563 /* If nobody owns us, absorb the event appropriately, otherwise
4564 we loop indefinitely. This occurs when, during call waiting, the
4565 other end hangs up our channel so that it no longer exists, but we
4566 have neither FLASH'd nor ONHOOK'd to signify our desire to
4567 change to the other channel. */
4568 if (p->fake_event) {
4569 res = p->fake_event;
4570 p->fake_event = 0;
4571 } else
4572 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4573 /* Switch to real if there is one and this isn't something really silly... */
4574 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4575 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4576 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4577 p->owner = p->subs[SUB_REAL].owner;
4578 if (p->owner && ast_bridged_channel(p->owner))
4579 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4580 p->subs[SUB_REAL].needunhold = 1;
4582 switch (res) {
4583 case DAHDI_EVENT_ONHOOK:
4584 dahdi_disable_ec(p);
4585 if (p->owner) {
4586 if (option_verbose > 2)
4587 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4588 dahdi_ring_phone(p);
4589 p->callwaitingrepeat = 0;
4590 p->cidcwexpire = 0;
4591 } else
4592 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4593 update_conf(p);
4594 break;
4595 case DAHDI_EVENT_RINGOFFHOOK:
4596 dahdi_enable_ec(p);
4597 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4598 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4599 p->subs[SUB_REAL].needanswer = 1;
4600 p->dialing = 0;
4602 break;
4603 case DAHDI_EVENT_HOOKCOMPLETE:
4604 case DAHDI_EVENT_RINGERON:
4605 case DAHDI_EVENT_RINGEROFF:
4606 /* Do nothing */
4607 break;
4608 case DAHDI_EVENT_WINKFLASH:
4609 gettimeofday(&p->flashtime, NULL);
4610 if (p->owner) {
4611 if (option_verbose > 2)
4612 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4613 if (p->owner->_state != AST_STATE_UP) {
4614 /* Answer if necessary */
4615 usedindex = dahdi_get_index(p->owner, p, 0);
4616 if (usedindex > -1) {
4617 p->subs[usedindex].needanswer = 1;
4619 ast_setstate(p->owner, AST_STATE_UP);
4621 p->callwaitingrepeat = 0;
4622 p->cidcwexpire = 0;
4623 if (ast_bridged_channel(p->owner))
4624 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4625 p->subs[SUB_REAL].needunhold = 1;
4626 } else
4627 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4628 update_conf(p);
4629 break;
4630 default:
4631 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4633 f = &p->subs[index].f;
4634 return f;
4636 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4637 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4638 /* If it's not us, return NULL immediately */
4639 if (ast != p->owner) {
4640 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4641 f = &p->subs[index].f;
4642 return f;
4644 f = dahdi_handle_event(ast);
4645 return f;
4648 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4650 struct dahdi_pvt *p = ast->tech_pvt;
4651 struct ast_frame *f;
4652 ast_mutex_lock(&p->lock);
4653 f = __dahdi_exception(ast);
4654 ast_mutex_unlock(&p->lock);
4655 return f;
4658 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4660 struct dahdi_pvt *p = ast->tech_pvt;
4661 int res;
4662 int index;
4663 void *readbuf;
4664 struct ast_frame *f;
4666 while (ast_mutex_trylock(&p->lock)) {
4667 DEADLOCK_AVOIDANCE(&ast->lock);
4670 index = dahdi_get_index(ast, p, 0);
4672 /* Hang up if we don't really exist */
4673 if (index < 0) {
4674 ast_log(LOG_WARNING, "We dont exist?\n");
4675 ast_mutex_unlock(&p->lock);
4676 return NULL;
4679 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4681 p->subs[index].f.frametype = AST_FRAME_NULL;
4682 p->subs[index].f.datalen = 0;
4683 p->subs[index].f.samples = 0;
4684 p->subs[index].f.mallocd = 0;
4685 p->subs[index].f.offset = 0;
4686 p->subs[index].f.subclass = 0;
4687 p->subs[index].f.delivery = ast_tv(0,0);
4688 p->subs[index].f.src = "dahdi_read";
4689 p->subs[index].f.data = NULL;
4691 /* make sure it sends initial key state as first frame */
4692 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4694 DAHDI_PARAMS ps;
4696 ps.channo = p->channel;
4697 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4698 ast_mutex_unlock(&p->lock);
4699 return NULL;
4701 p->firstradio = 1;
4702 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4703 if (ps.rxisoffhook)
4705 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4707 else
4709 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4711 ast_mutex_unlock(&p->lock);
4712 return &p->subs[index].f;
4714 if (p->ringt == 1) {
4715 ast_mutex_unlock(&p->lock);
4716 return NULL;
4718 else if (p->ringt > 0)
4719 p->ringt--;
4721 if (p->subs[index].needringing) {
4722 /* Send ringing frame if requested */
4723 p->subs[index].needringing = 0;
4724 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4725 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4726 ast_setstate(ast, AST_STATE_RINGING);
4727 ast_mutex_unlock(&p->lock);
4728 return &p->subs[index].f;
4731 if (p->subs[index].needbusy) {
4732 /* Send busy frame if requested */
4733 p->subs[index].needbusy = 0;
4734 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4735 p->subs[index].f.subclass = AST_CONTROL_BUSY;
4736 ast_mutex_unlock(&p->lock);
4737 return &p->subs[index].f;
4740 if (p->subs[index].needcongestion) {
4741 /* Send congestion frame if requested */
4742 p->subs[index].needcongestion = 0;
4743 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4744 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
4745 ast_mutex_unlock(&p->lock);
4746 return &p->subs[index].f;
4749 if (p->subs[index].needcallerid) {
4750 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
4751 S_OR(p->lastcid_name, NULL),
4752 S_OR(p->lastcid_num, NULL)
4754 p->subs[index].needcallerid = 0;
4757 if (p->subs[index].needanswer) {
4758 /* Send answer frame if requested */
4759 p->subs[index].needanswer = 0;
4760 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4761 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4762 ast_mutex_unlock(&p->lock);
4763 return &p->subs[index].f;
4766 if (p->subs[index].needflash) {
4767 /* Send answer frame if requested */
4768 p->subs[index].needflash = 0;
4769 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4770 p->subs[index].f.subclass = AST_CONTROL_FLASH;
4771 ast_mutex_unlock(&p->lock);
4772 return &p->subs[index].f;
4775 if (p->subs[index].needhold) {
4776 /* Send answer frame if requested */
4777 p->subs[index].needhold = 0;
4778 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4779 p->subs[index].f.subclass = AST_CONTROL_HOLD;
4780 ast_mutex_unlock(&p->lock);
4781 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
4782 return &p->subs[index].f;
4785 if (p->subs[index].needunhold) {
4786 /* Send answer frame if requested */
4787 p->subs[index].needunhold = 0;
4788 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4789 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
4790 ast_mutex_unlock(&p->lock);
4791 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
4792 return &p->subs[index].f;
4795 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
4796 if (!p->subs[index].linear) {
4797 p->subs[index].linear = 1;
4798 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4799 if (res)
4800 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
4802 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
4803 (ast->rawreadformat == AST_FORMAT_ALAW)) {
4804 if (p->subs[index].linear) {
4805 p->subs[index].linear = 0;
4806 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4807 if (res)
4808 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
4810 } else {
4811 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
4812 ast_mutex_unlock(&p->lock);
4813 return NULL;
4815 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
4816 CHECK_BLOCKING(ast);
4817 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4818 ast_clear_flag(ast, AST_FLAG_BLOCKING);
4819 /* Check for hangup */
4820 if (res < 0) {
4821 f = NULL;
4822 if (res == -1) {
4823 if (errno == EAGAIN) {
4824 /* Return "NULL" frame if there is nobody there */
4825 ast_mutex_unlock(&p->lock);
4826 return &p->subs[index].f;
4827 } else if (errno == ELAST) {
4828 f = __dahdi_exception(ast);
4829 } else
4830 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
4832 ast_mutex_unlock(&p->lock);
4833 return f;
4835 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
4836 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4837 f = __dahdi_exception(ast);
4838 ast_mutex_unlock(&p->lock);
4839 return f;
4841 if (p->tdd) { /* if in TDD mode, see if we receive that */
4842 int c;
4844 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
4845 if (c < 0) {
4846 ast_log(LOG_DEBUG,"tdd_feed failed\n");
4847 ast_mutex_unlock(&p->lock);
4848 return NULL;
4850 if (c) { /* if a char to return */
4851 p->subs[index].f.subclass = 0;
4852 p->subs[index].f.frametype = AST_FRAME_TEXT;
4853 p->subs[index].f.mallocd = 0;
4854 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4855 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
4856 p->subs[index].f.datalen = 1;
4857 *((char *) p->subs[index].f.data) = c;
4858 ast_mutex_unlock(&p->lock);
4859 return &p->subs[index].f;
4862 /* Ensure the CW timer decrements only on a single subchannel */
4863 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
4864 p->callwaitingrepeat--;
4866 if (p->cidcwexpire)
4867 p->cidcwexpire--;
4868 /* Repeat callwaiting */
4869 if (p->callwaitingrepeat == 1) {
4870 p->callwaitrings++;
4871 dahdi_callwait(ast);
4873 /* Expire CID/CW */
4874 if (p->cidcwexpire == 1) {
4875 if (option_verbose > 2)
4876 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
4877 restore_conference(p);
4879 if (p->subs[index].linear) {
4880 p->subs[index].f.datalen = READ_SIZE * 2;
4881 } else
4882 p->subs[index].f.datalen = READ_SIZE;
4884 /* Handle CallerID Transmission */
4885 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
4886 send_callerid(p);
4889 p->subs[index].f.frametype = AST_FRAME_VOICE;
4890 p->subs[index].f.subclass = ast->rawreadformat;
4891 p->subs[index].f.samples = READ_SIZE;
4892 p->subs[index].f.mallocd = 0;
4893 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4894 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
4895 #if 0
4896 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
4897 #endif
4898 if (p->dialing || /* Transmitting something */
4899 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
4900 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
4902 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4903 don't send anything */
4904 p->subs[index].f.frametype = AST_FRAME_NULL;
4905 p->subs[index].f.subclass = 0;
4906 p->subs[index].f.samples = 0;
4907 p->subs[index].f.mallocd = 0;
4908 p->subs[index].f.offset = 0;
4909 p->subs[index].f.data = NULL;
4910 p->subs[index].f.datalen= 0;
4912 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
4913 /* Perform busy detection. etc on the dahdi line */
4914 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
4915 if (f) {
4916 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
4917 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
4918 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4919 a busy */
4920 f = NULL;
4922 } else if (f->frametype == AST_FRAME_DTMF) {
4923 #ifdef HAVE_PRI
4924 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
4925 /* Don't accept in-band DTMF when in overlap dial mode */
4926 f->frametype = AST_FRAME_NULL;
4927 f->subclass = 0;
4929 #endif
4930 /* DSP clears us of being pulse */
4931 p->pulsedial = 0;
4934 } else
4935 f = &p->subs[index].f;
4937 if (f && (f->frametype == AST_FRAME_DTMF))
4938 dahdi_handle_dtmfup(ast, index, &f);
4940 /* If we have a fake_event, trigger exception to handle it */
4941 if (p->fake_event)
4942 ast_set_flag(ast, AST_FLAG_EXCEPTION);
4944 ast_mutex_unlock(&p->lock);
4945 return f;
4948 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
4950 int sent=0;
4951 int size;
4952 int res;
4953 int fd;
4954 fd = p->subs[index].dfd;
4955 while (len) {
4956 size = len;
4957 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
4958 size = (linear ? READ_SIZE * 2 : READ_SIZE);
4959 res = write(fd, buf, size);
4960 if (res != size) {
4961 if (option_debug)
4962 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
4963 return sent;
4965 len -= size;
4966 buf += size;
4968 return sent;
4971 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
4973 struct dahdi_pvt *p = ast->tech_pvt;
4974 int res;
4975 int index;
4976 index = dahdi_get_index(ast, p, 0);
4977 if (index < 0) {
4978 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
4979 return -1;
4982 #if 0
4983 #ifdef HAVE_PRI
4984 ast_mutex_lock(&p->lock);
4985 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
4986 if (p->pri->pri) {
4987 if (!pri_grab(p, p->pri)) {
4988 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
4989 pri_rel(p->pri);
4990 } else
4991 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
4993 p->proceeding=1;
4995 ast_mutex_unlock(&p->lock);
4996 #endif
4997 #endif
4998 /* Write a frame of (presumably voice) data */
4999 if (frame->frametype != AST_FRAME_VOICE) {
5000 if (frame->frametype != AST_FRAME_IMAGE)
5001 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
5002 return 0;
5004 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
5005 (frame->subclass != AST_FORMAT_ULAW) &&
5006 (frame->subclass != AST_FORMAT_ALAW)) {
5007 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
5008 return -1;
5010 if (p->dialing) {
5011 if (option_debug)
5012 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
5013 return 0;
5015 if (!p->owner) {
5016 if (option_debug)
5017 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
5018 return 0;
5020 if (p->cidspill) {
5021 if (option_debug)
5022 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5023 return 0;
5025 /* Return if it's not valid data */
5026 if (!frame->data || !frame->datalen)
5027 return 0;
5029 if (frame->subclass == AST_FORMAT_SLINEAR) {
5030 if (!p->subs[index].linear) {
5031 p->subs[index].linear = 1;
5032 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5033 if (res)
5034 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5036 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5037 } else {
5038 /* x-law already */
5039 if (p->subs[index].linear) {
5040 p->subs[index].linear = 0;
5041 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5042 if (res)
5043 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5045 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5047 if (res < 0) {
5048 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5049 return -1;
5051 return 0;
5054 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5056 struct dahdi_pvt *p = chan->tech_pvt;
5057 int res=-1;
5058 int index;
5059 int func = DAHDI_FLASH;
5060 ast_mutex_lock(&p->lock);
5061 index = dahdi_get_index(chan, p, 0);
5062 if (option_debug)
5063 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5064 if (index == SUB_REAL) {
5065 switch (condition) {
5066 case AST_CONTROL_BUSY:
5067 #ifdef HAVE_PRI
5068 if (p->priindication_oob && p->sig == SIG_PRI) {
5069 chan->hangupcause = AST_CAUSE_USER_BUSY;
5070 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5071 res = 0;
5072 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5073 if (p->pri->pri) {
5074 if (!pri_grab(p, p->pri)) {
5075 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5076 pri_rel(p->pri);
5078 else
5079 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5081 p->progress = 1;
5082 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5083 } else
5084 #endif
5085 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5086 break;
5087 case AST_CONTROL_RINGING:
5088 #ifdef HAVE_PRI
5089 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5090 if (p->pri->pri) {
5091 if (!pri_grab(p, p->pri)) {
5092 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5093 pri_rel(p->pri);
5095 else
5096 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5098 p->alerting = 1;
5100 #endif
5101 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5102 if (chan->_state != AST_STATE_UP) {
5103 if ((chan->_state != AST_STATE_RING) ||
5104 ((p->sig != SIG_FXSKS) &&
5105 (p->sig != SIG_FXSLS) &&
5106 (p->sig != SIG_FXSGS)))
5107 ast_setstate(chan, AST_STATE_RINGING);
5109 break;
5110 case AST_CONTROL_PROCEEDING:
5111 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5112 #ifdef HAVE_PRI
5113 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5114 if (p->pri->pri) {
5115 if (!pri_grab(p, p->pri)) {
5116 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5117 pri_rel(p->pri);
5119 else
5120 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5122 p->proceeding = 1;
5124 #endif
5125 /* don't continue in ast_indicate */
5126 res = 0;
5127 break;
5128 case AST_CONTROL_PROGRESS:
5129 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5130 #ifdef HAVE_PRI
5131 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5132 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5133 if (p->pri->pri) {
5134 if (!pri_grab(p, p->pri)) {
5135 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5136 pri_rel(p->pri);
5138 else
5139 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5141 p->progress = 1;
5143 #endif
5144 /* don't continue in ast_indicate */
5145 res = 0;
5146 break;
5147 case AST_CONTROL_CONGESTION:
5148 chan->hangupcause = AST_CAUSE_CONGESTION;
5149 #ifdef HAVE_PRI
5150 if (p->priindication_oob && p->sig == SIG_PRI) {
5151 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5152 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5153 res = 0;
5154 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5155 if (p->pri) {
5156 if (!pri_grab(p, p->pri)) {
5157 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5158 pri_rel(p->pri);
5159 } else
5160 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5162 p->progress = 1;
5163 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5164 } else
5165 #endif
5166 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5167 break;
5168 case AST_CONTROL_HOLD:
5169 #ifdef HAVE_PRI
5170 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5171 if (!pri_grab(p, p->pri)) {
5172 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5173 pri_rel(p->pri);
5174 } else
5175 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5176 } else
5177 #endif
5178 ast_moh_start(chan, data, p->mohinterpret);
5179 break;
5180 case AST_CONTROL_UNHOLD:
5181 #ifdef HAVE_PRI
5182 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5183 if (!pri_grab(p, p->pri)) {
5184 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5185 pri_rel(p->pri);
5186 } else
5187 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5188 } else
5189 #endif
5190 ast_moh_stop(chan);
5191 break;
5192 case AST_CONTROL_RADIO_KEY:
5193 if (p->radio)
5194 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5195 res = 0;
5196 break;
5197 case AST_CONTROL_RADIO_UNKEY:
5198 if (p->radio)
5199 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5200 res = 0;
5201 break;
5202 case AST_CONTROL_FLASH:
5203 /* flash hookswitch */
5204 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5205 /* Clear out the dial buffer */
5206 p->dop.dialstr[0] = '\0';
5207 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5208 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5209 chan->name, strerror(errno));
5210 } else
5211 res = 0;
5212 } else
5213 res = 0;
5214 break;
5215 case AST_CONTROL_SRCUPDATE:
5216 res = 0;
5217 break;
5218 case -1:
5219 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5220 break;
5222 } else
5223 res = 0;
5224 ast_mutex_unlock(&p->lock);
5225 return res;
5228 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5230 struct ast_channel *tmp;
5231 int deflaw;
5232 int res;
5233 int x,y;
5234 int features;
5235 char *b2 = NULL;
5236 DAHDI_PARAMS ps;
5237 char chanprefix[*dahdi_chan_name_len + 4];
5239 if (i->subs[index].owner) {
5240 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5241 return NULL;
5243 y = 1;
5244 do {
5245 if (b2)
5246 free(b2);
5247 #ifdef HAVE_PRI
5248 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5249 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5250 else
5251 #endif
5252 if (i->channel == CHAN_PSEUDO)
5253 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5254 else
5255 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5256 for (x = 0; x < 3; x++) {
5257 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
5258 break;
5260 y++;
5261 } while (x < 3);
5262 strcpy(chanprefix, dahdi_chan_name);
5263 strcat(chanprefix, "/%s");
5264 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
5265 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5266 free(b2);
5267 if (!tmp)
5268 return NULL;
5269 tmp->tech = chan_tech;
5270 ps.channo = i->channel;
5271 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5272 if (res) {
5273 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5274 ps.curlaw = DAHDI_LAW_MULAW;
5276 if (ps.curlaw == DAHDI_LAW_ALAW)
5277 deflaw = AST_FORMAT_ALAW;
5278 else
5279 deflaw = AST_FORMAT_ULAW;
5280 if (law) {
5281 if (law == DAHDI_LAW_ALAW)
5282 deflaw = AST_FORMAT_ALAW;
5283 else
5284 deflaw = AST_FORMAT_ULAW;
5286 tmp->fds[0] = i->subs[index].dfd;
5287 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5288 /* Start out assuming ulaw since it's smaller :) */
5289 tmp->rawreadformat = deflaw;
5290 tmp->readformat = deflaw;
5291 tmp->rawwriteformat = deflaw;
5292 tmp->writeformat = deflaw;
5293 i->subs[index].linear = 0;
5294 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5295 features = 0;
5296 if (index == SUB_REAL) {
5297 if (i->busydetect && CANBUSYDETECT(i))
5298 features |= DSP_FEATURE_BUSY_DETECT;
5299 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5300 features |= DSP_FEATURE_CALL_PROGRESS;
5301 if ((!i->outgoing && (i->callprogress & 4)) ||
5302 (i->outgoing && (i->callprogress & 2))) {
5303 features |= DSP_FEATURE_FAX_DETECT;
5305 #ifdef DAHDI_TONEDETECT
5306 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5307 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5308 #endif
5309 i->hardwaredtmf = 0;
5310 features |= DSP_FEATURE_DTMF_DETECT;
5311 #ifdef DAHDI_TONEDETECT
5312 } else if (NEED_MFDETECT(i)) {
5313 i->hardwaredtmf = 1;
5314 features |= DSP_FEATURE_DTMF_DETECT;
5316 #endif
5318 if (features) {
5319 if (i->dsp) {
5320 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5321 } else {
5322 if (i->channel != CHAN_PSEUDO)
5323 i->dsp = ast_dsp_new();
5324 else
5325 i->dsp = NULL;
5326 if (i->dsp) {
5327 i->dsp_features = features;
5328 #ifdef HAVE_PRI
5329 /* We cannot do progress detection until receives PROGRESS message */
5330 if (i->outgoing && (i->sig == SIG_PRI)) {
5331 /* Remember requested DSP features, don't treat
5332 talking as ANSWER */
5333 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5334 features = 0;
5336 #endif
5337 ast_dsp_set_features(i->dsp, features);
5338 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5339 if (!ast_strlen_zero(progzone))
5340 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5341 if (i->busydetect && CANBUSYDETECT(i)) {
5342 ast_dsp_set_busy_count(i->dsp, i->busycount);
5343 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5349 if (state == AST_STATE_RING)
5350 tmp->rings = 1;
5351 tmp->tech_pvt = i;
5352 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5353 /* Only FXO signalled stuff can be picked up */
5354 tmp->callgroup = i->callgroup;
5355 tmp->pickupgroup = i->pickupgroup;
5357 if (!ast_strlen_zero(i->language))
5358 ast_string_field_set(tmp, language, i->language);
5359 if (!i->owner)
5360 i->owner = tmp;
5361 if (!ast_strlen_zero(i->accountcode))
5362 ast_string_field_set(tmp, accountcode, i->accountcode);
5363 if (i->amaflags)
5364 tmp->amaflags = i->amaflags;
5365 i->subs[index].owner = tmp;
5366 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5367 ast_string_field_set(tmp, call_forward, i->call_forward);
5368 /* If we've been told "no ADSI" then enforce it */
5369 if (!i->adsi)
5370 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5371 if (!ast_strlen_zero(i->exten))
5372 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5373 if (!ast_strlen_zero(i->rdnis))
5374 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5375 if (!ast_strlen_zero(i->dnid))
5376 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5378 /* Don't use ast_set_callerid() here because it will
5379 * generate a needless NewCallerID event */
5380 #ifdef PRI_ANI
5381 if (!ast_strlen_zero(i->cid_ani))
5382 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5383 else
5384 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5385 #else
5386 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5387 #endif
5388 tmp->cid.cid_pres = i->callingpres;
5389 tmp->cid.cid_ton = i->cid_ton;
5390 #ifdef HAVE_PRI
5391 tmp->transfercapability = transfercapability;
5392 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5393 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5394 i->digital = 1;
5395 /* Assume calls are not idle calls unless we're told differently */
5396 i->isidlecall = 0;
5397 i->alreadyhungup = 0;
5398 #endif
5399 /* clear the fake event in case we posted one before we had ast_channel */
5400 i->fake_event = 0;
5401 /* Assure there is no confmute on this channel */
5402 dahdi_confmute(i, 0);
5403 /* Configure the new channel jb */
5404 ast_jb_configure(tmp, &global_jbconf);
5405 if (startpbx) {
5406 if (ast_pbx_start(tmp)) {
5407 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5408 ast_hangup(tmp);
5409 i->owner = NULL;
5410 return NULL;
5414 ast_module_ref(ast_module_info->self);
5416 return tmp;
5420 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5422 char c;
5424 *str = 0; /* start with empty output buffer */
5425 for (;;)
5427 /* Wait for the first digit (up to specified ms). */
5428 c = ast_waitfordigit(chan, ms);
5429 /* if timeout, hangup or error, return as such */
5430 if (c < 1)
5431 return c;
5432 *str++ = c;
5433 *str = 0;
5434 if (strchr(term, c))
5435 return 1;
5439 static int dahdi_wink(struct dahdi_pvt *p, int index)
5441 int j;
5442 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5443 for (;;)
5445 /* set bits of interest */
5446 j = DAHDI_IOMUX_SIGEVENT;
5447 /* wait for some happening */
5448 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5449 /* exit loop if we have it */
5450 if (j & DAHDI_IOMUX_SIGEVENT) break;
5452 /* get the event info */
5453 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5454 return 0;
5457 static void *ss_thread(void *data)
5459 struct ast_channel *chan = data;
5460 struct dahdi_pvt *p = chan->tech_pvt;
5461 char exten[AST_MAX_EXTENSION] = "";
5462 char exten2[AST_MAX_EXTENSION] = "";
5463 unsigned char buf[256];
5464 char dtmfcid[300];
5465 char dtmfbuf[300];
5466 struct callerid_state *cs = NULL;
5467 char *name = NULL, *number = NULL;
5468 int distMatches;
5469 int curRingData[3];
5470 int receivedRingT;
5471 int counter1;
5472 int counter;
5473 int samples = 0;
5474 struct ast_smdi_md_message *smdi_msg = NULL;
5475 int flags;
5476 int i;
5477 int timeout;
5478 int getforward = 0;
5479 char *s1, *s2;
5480 int len = 0;
5481 int res;
5482 int index;
5484 /* in the bizarre case where the channel has become a zombie before we
5485 even get started here, abort safely
5487 if (!p) {
5488 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5489 ast_hangup(chan);
5490 return NULL;
5493 if (option_verbose > 2)
5494 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5495 index = dahdi_get_index(chan, p, 1);
5496 if (index < 0) {
5497 ast_log(LOG_WARNING, "Huh?\n");
5498 ast_hangup(chan);
5499 return NULL;
5501 if (p->dsp)
5502 ast_dsp_digitreset(p->dsp);
5503 switch (p->sig) {
5504 #ifdef HAVE_PRI
5505 case SIG_PRI:
5506 /* Now loop looking for an extension */
5507 ast_copy_string(exten, p->exten, sizeof(exten));
5508 len = strlen(exten);
5509 res = 0;
5510 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5511 if (len && !ast_ignore_pattern(chan->context, exten))
5512 tone_zone_play_tone(p->subs[index].dfd, -1);
5513 else
5514 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5515 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5516 timeout = matchdigittimeout;
5517 else
5518 timeout = gendigittimeout;
5519 res = ast_waitfordigit(chan, timeout);
5520 if (res < 0) {
5521 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5522 ast_hangup(chan);
5523 return NULL;
5524 } else if (res) {
5525 exten[len++] = res;
5526 exten[len] = '\0';
5527 } else
5528 break;
5530 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5531 if (ast_strlen_zero(exten)) {
5532 if (option_verbose > 2)
5533 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5534 exten[0] = 's';
5535 exten[1] = '\0';
5537 tone_zone_play_tone(p->subs[index].dfd, -1);
5538 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5539 /* Start the real PBX */
5540 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5541 if (p->dsp) ast_dsp_digitreset(p->dsp);
5542 dahdi_enable_ec(p);
5543 ast_setstate(chan, AST_STATE_RING);
5544 res = ast_pbx_run(chan);
5545 if (res) {
5546 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5548 } else {
5549 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5550 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5551 ast_hangup(chan);
5552 p->exten[0] = '\0';
5553 /* Since we send release complete here, we won't get one */
5554 p->call = NULL;
5556 return NULL;
5557 break;
5558 #endif
5559 case SIG_FEATD:
5560 case SIG_FEATDMF:
5561 case SIG_FEATDMF_TA:
5562 case SIG_E911:
5563 case SIG_FGC_CAMAMF:
5564 case SIG_FEATB:
5565 case SIG_EMWINK:
5566 case SIG_SF_FEATD:
5567 case SIG_SF_FEATDMF:
5568 case SIG_SF_FEATB:
5569 case SIG_SFWINK:
5570 if (dahdi_wink(p, index))
5571 return NULL;
5572 /* Fall through */
5573 case SIG_EM:
5574 case SIG_EM_E1:
5575 case SIG_SF:
5576 case SIG_FGC_CAMA:
5577 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5578 if (p->dsp)
5579 ast_dsp_digitreset(p->dsp);
5580 /* set digit mode appropriately */
5581 if (p->dsp) {
5582 if (NEED_MFDETECT(p))
5583 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5584 else
5585 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5587 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5588 /* Wait for the first digit only if immediate=no */
5589 if (!p->immediate)
5590 /* Wait for the first digit (up to 5 seconds). */
5591 res = ast_waitfordigit(chan, 5000);
5592 else
5593 res = 0;
5594 if (res > 0) {
5595 /* save first char */
5596 dtmfbuf[0] = res;
5597 switch (p->sig) {
5598 case SIG_FEATD:
5599 case SIG_SF_FEATD:
5600 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5601 if (res > 0)
5602 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5603 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5604 break;
5605 case SIG_FEATDMF_TA:
5606 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5607 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5608 if (dahdi_wink(p, index)) return NULL;
5609 dtmfbuf[0] = 0;
5610 /* Wait for the first digit (up to 5 seconds). */
5611 res = ast_waitfordigit(chan, 5000);
5612 if (res <= 0) break;
5613 dtmfbuf[0] = res;
5614 /* fall through intentionally */
5615 case SIG_FEATDMF:
5616 case SIG_E911:
5617 case SIG_FGC_CAMAMF:
5618 case SIG_SF_FEATDMF:
5619 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5620 /* if international caca, do it again to get real ANO */
5621 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5623 if (dahdi_wink(p, index)) return NULL;
5624 dtmfbuf[0] = 0;
5625 /* Wait for the first digit (up to 5 seconds). */
5626 res = ast_waitfordigit(chan, 5000);
5627 if (res <= 0) break;
5628 dtmfbuf[0] = res;
5629 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5631 if (res > 0) {
5632 /* if E911, take off hook */
5633 if (p->sig == SIG_E911)
5634 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5635 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5637 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5638 break;
5639 case SIG_FEATB:
5640 case SIG_SF_FEATB:
5641 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5642 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5643 break;
5644 case SIG_EMWINK:
5645 /* if we received a '*', we are actually receiving Feature Group D
5646 dial syntax, so use that mode; otherwise, fall through to normal
5647 mode
5649 if (res == '*') {
5650 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5651 if (res > 0)
5652 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5653 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5654 break;
5656 default:
5657 /* If we got the first digit, get the rest */
5658 len = 1;
5659 dtmfbuf[len] = '\0';
5660 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5661 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5662 timeout = matchdigittimeout;
5663 } else {
5664 timeout = gendigittimeout;
5666 res = ast_waitfordigit(chan, timeout);
5667 if (res < 0) {
5668 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5669 ast_hangup(chan);
5670 return NULL;
5671 } else if (res) {
5672 dtmfbuf[len++] = res;
5673 dtmfbuf[len] = '\0';
5674 } else {
5675 break;
5678 break;
5681 if (res == -1) {
5682 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5683 ast_hangup(chan);
5684 return NULL;
5685 } else if (res < 0) {
5686 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
5687 ast_hangup(chan);
5688 return NULL;
5691 if (p->sig == SIG_FGC_CAMA) {
5692 char anibuf[100];
5694 if (ast_safe_sleep(chan,1000) == -1) {
5695 ast_hangup(chan);
5696 return NULL;
5698 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5699 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5700 res = my_getsigstr(chan, anibuf, "#", 10000);
5701 if ((res > 0) && (strlen(anibuf) > 2)) {
5702 if (anibuf[strlen(anibuf) - 1] == '#')
5703 anibuf[strlen(anibuf) - 1] = 0;
5704 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
5706 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5709 ast_copy_string(exten, dtmfbuf, sizeof(exten));
5710 if (ast_strlen_zero(exten))
5711 ast_copy_string(exten, "s", sizeof(exten));
5712 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
5713 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5714 if (exten[0] == '*') {
5715 char *stringp=NULL;
5716 ast_copy_string(exten2, exten, sizeof(exten2));
5717 /* Parse out extension and callerid */
5718 stringp=exten2 +1;
5719 s1 = strsep(&stringp, "*");
5720 s2 = strsep(&stringp, "*");
5721 if (s2) {
5722 if (!ast_strlen_zero(p->cid_num))
5723 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5724 else
5725 ast_set_callerid(chan, s1, NULL, s1);
5726 ast_copy_string(exten, s2, sizeof(exten));
5727 } else
5728 ast_copy_string(exten, s1, sizeof(exten));
5729 } else if (p->sig == SIG_FEATD)
5730 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5732 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5733 if (exten[0] == '*') {
5734 char *stringp=NULL;
5735 ast_copy_string(exten2, exten, sizeof(exten2));
5736 /* Parse out extension and callerid */
5737 stringp=exten2 +1;
5738 s1 = strsep(&stringp, "#");
5739 s2 = strsep(&stringp, "#");
5740 if (s2) {
5741 if (!ast_strlen_zero(p->cid_num))
5742 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5743 else
5744 if (*(s1 + 2))
5745 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
5746 ast_copy_string(exten, s2 + 1, sizeof(exten));
5747 } else
5748 ast_copy_string(exten, s1 + 2, sizeof(exten));
5749 } else
5750 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5752 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
5753 if (exten[0] == '*') {
5754 char *stringp=NULL;
5755 ast_copy_string(exten2, exten, sizeof(exten2));
5756 /* Parse out extension and callerid */
5757 stringp=exten2 +1;
5758 s1 = strsep(&stringp, "#");
5759 s2 = strsep(&stringp, "#");
5760 if (s2 && (*(s2 + 1) == '0')) {
5761 if (*(s2 + 2))
5762 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
5764 if (s1) ast_copy_string(exten, s1, sizeof(exten));
5765 else ast_copy_string(exten, "911", sizeof(exten));
5766 } else
5767 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
5769 if (p->sig == SIG_FEATB) {
5770 if (exten[0] == '*') {
5771 char *stringp=NULL;
5772 ast_copy_string(exten2, exten, sizeof(exten2));
5773 /* Parse out extension and callerid */
5774 stringp=exten2 +1;
5775 s1 = strsep(&stringp, "#");
5776 ast_copy_string(exten, exten2 + 1, sizeof(exten));
5777 } else
5778 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
5780 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5781 dahdi_wink(p, index);
5782 /* some switches require a minimum guard time between
5783 the last FGD wink and something that answers
5784 immediately. This ensures it */
5785 if (ast_safe_sleep(chan,100)) return NULL;
5787 dahdi_enable_ec(p);
5788 if (NEED_MFDETECT(p)) {
5789 if (p->dsp) {
5790 if (!p->hardwaredtmf)
5791 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5792 else {
5793 ast_dsp_free(p->dsp);
5794 p->dsp = NULL;
5799 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
5800 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5801 if (p->dsp) ast_dsp_digitreset(p->dsp);
5802 res = ast_pbx_run(chan);
5803 if (res) {
5804 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5805 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5807 return NULL;
5808 } else {
5809 if (option_verbose > 2)
5810 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
5811 sleep(2);
5812 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
5813 if (res < 0)
5814 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
5815 else
5816 sleep(1);
5817 res = ast_streamfile(chan, "ss-noservice", chan->language);
5818 if (res >= 0)
5819 ast_waitstream(chan, "");
5820 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5821 ast_hangup(chan);
5822 return NULL;
5824 break;
5825 case SIG_FXOLS:
5826 case SIG_FXOGS:
5827 case SIG_FXOKS:
5828 /* Read the first digit */
5829 timeout = firstdigittimeout;
5830 /* If starting a threeway call, never timeout on the first digit so someone
5831 can use flash-hook as a "hold" feature */
5832 if (p->subs[SUB_THREEWAY].owner)
5833 timeout = 999999;
5834 while (len < AST_MAX_EXTENSION-1) {
5835 /* Read digit unless it's supposed to be immediate, in which case the
5836 only answer is 's' */
5837 if (p->immediate)
5838 res = 's';
5839 else
5840 res = ast_waitfordigit(chan, timeout);
5841 timeout = 0;
5842 if (res < 0) {
5843 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5844 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5845 ast_hangup(chan);
5846 return NULL;
5847 } else if (res) {
5848 exten[len++]=res;
5849 exten[len] = '\0';
5851 if (!ast_ignore_pattern(chan->context, exten))
5852 tone_zone_play_tone(p->subs[index].dfd, -1);
5853 else
5854 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5855 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
5856 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5857 if (getforward) {
5858 /* Record this as the forwarding extension */
5859 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
5860 if (option_verbose > 2)
5861 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
5862 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5863 if (res)
5864 break;
5865 usleep(500000);
5866 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5867 sleep(1);
5868 memset(exten, 0, sizeof(exten));
5869 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5870 len = 0;
5871 getforward = 0;
5872 } else {
5873 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5874 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5875 if (!ast_strlen_zero(p->cid_num)) {
5876 if (!p->hidecallerid)
5877 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5878 else
5879 ast_set_callerid(chan, NULL, NULL, p->cid_num);
5881 if (!ast_strlen_zero(p->cid_name)) {
5882 if (!p->hidecallerid)
5883 ast_set_callerid(chan, NULL, p->cid_name, NULL);
5885 ast_setstate(chan, AST_STATE_RING);
5886 dahdi_enable_ec(p);
5887 res = ast_pbx_run(chan);
5888 if (res) {
5889 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5890 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5892 return NULL;
5894 } else {
5895 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5896 so just set the timeout to matchdigittimeout and wait some more */
5897 timeout = matchdigittimeout;
5899 } else if (res == 0) {
5900 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
5901 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5902 dahdi_wait_event(p->subs[index].dfd);
5903 ast_hangup(chan);
5904 return NULL;
5905 } else if (p->callwaiting && !strcmp(exten, "*70")) {
5906 if (option_verbose > 2)
5907 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
5908 /* Disable call waiting if enabled */
5909 p->callwaiting = 0;
5910 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5911 if (res) {
5912 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5913 chan->name, strerror(errno));
5915 len = 0;
5916 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
5917 memset(exten, 0, sizeof(exten));
5918 timeout = firstdigittimeout;
5920 } else if (!strcmp(exten,ast_pickup_ext())) {
5921 /* Scan all channels and see if there are any
5922 * ringing channels that have call groups
5923 * that equal this channels pickup group
5925 if (index == SUB_REAL) {
5926 /* Switch us from Third call to Call Wait */
5927 if (p->subs[SUB_THREEWAY].owner) {
5928 /* If you make a threeway call and the *8# a call, it should actually
5929 look like a callwait */
5930 alloc_sub(p, SUB_CALLWAIT);
5931 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
5932 unalloc_sub(p, SUB_THREEWAY);
5934 dahdi_enable_ec(p);
5935 if (ast_pickup_call(chan)) {
5936 ast_log(LOG_DEBUG, "No call pickup possible...\n");
5937 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5938 dahdi_wait_event(p->subs[index].dfd);
5940 ast_hangup(chan);
5941 return NULL;
5942 } else {
5943 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
5944 ast_hangup(chan);
5945 return NULL;
5948 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
5949 if (option_verbose > 2)
5950 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
5951 /* Disable Caller*ID if enabled */
5952 p->hidecallerid = 1;
5953 if (chan->cid.cid_num)
5954 free(chan->cid.cid_num);
5955 chan->cid.cid_num = NULL;
5956 if (chan->cid.cid_name)
5957 free(chan->cid.cid_name);
5958 chan->cid.cid_name = NULL;
5959 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5960 if (res) {
5961 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5962 chan->name, strerror(errno));
5964 len = 0;
5965 memset(exten, 0, sizeof(exten));
5966 timeout = firstdigittimeout;
5967 } else if (p->callreturn && !strcmp(exten, "*69")) {
5968 res = 0;
5969 if (!ast_strlen_zero(p->lastcid_num)) {
5970 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
5972 if (!res)
5973 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5974 break;
5975 } else if (!strcmp(exten, "*78")) {
5976 /* Do not disturb */
5977 if (option_verbose > 2)
5978 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
5979 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5980 "Channel: %s/%d\r\n"
5981 "Status: enabled\r\n", dahdi_chan_name, p->channel);
5982 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5983 p->dnd = 1;
5984 getforward = 0;
5985 memset(exten, 0, sizeof(exten));
5986 len = 0;
5987 } else if (!strcmp(exten, "*79")) {
5988 /* Do not disturb */
5989 if (option_verbose > 2)
5990 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
5991 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
5992 "Channel: %s/%d\r\n"
5993 "Status: disabled\r\n", dahdi_chan_name, p->channel);
5994 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5995 p->dnd = 0;
5996 getforward = 0;
5997 memset(exten, 0, sizeof(exten));
5998 len = 0;
5999 } else if (p->cancallforward && !strcmp(exten, "*72")) {
6000 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6001 getforward = 1;
6002 memset(exten, 0, sizeof(exten));
6003 len = 0;
6004 } else if (p->cancallforward && !strcmp(exten, "*73")) {
6005 if (option_verbose > 2)
6006 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
6007 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6008 memset(p->call_forward, 0, sizeof(p->call_forward));
6009 getforward = 0;
6010 memset(exten, 0, sizeof(exten));
6011 len = 0;
6012 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
6013 p->subs[SUB_THREEWAY].owner &&
6014 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6015 /* This is a three way call, the main call being a real channel,
6016 and we're parking the first call. */
6017 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
6018 if (option_verbose > 2)
6019 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
6020 break;
6021 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
6022 if (option_verbose > 2)
6023 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
6024 res = ast_db_put("blacklist", p->lastcid_num, "1");
6025 if (!res) {
6026 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6027 memset(exten, 0, sizeof(exten));
6028 len = 0;
6030 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6031 if (option_verbose > 2)
6032 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6033 /* Enable Caller*ID if enabled */
6034 p->hidecallerid = 0;
6035 if (chan->cid.cid_num)
6036 free(chan->cid.cid_num);
6037 chan->cid.cid_num = NULL;
6038 if (chan->cid.cid_name)
6039 free(chan->cid.cid_name);
6040 chan->cid.cid_name = NULL;
6041 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6042 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6043 if (res) {
6044 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6045 chan->name, strerror(errno));
6047 len = 0;
6048 memset(exten, 0, sizeof(exten));
6049 timeout = firstdigittimeout;
6050 } else if (!strcmp(exten, "*0")) {
6051 struct ast_channel *nbridge =
6052 p->subs[SUB_THREEWAY].owner;
6053 struct dahdi_pvt *pbridge = NULL;
6054 /* set up the private struct of the bridged one, if any */
6055 if (nbridge && ast_bridged_channel(nbridge))
6056 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6057 if (nbridge && pbridge &&
6058 (nbridge->tech == chan_tech) &&
6059 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
6060 ISTRUNK(pbridge)) {
6061 int func = DAHDI_FLASH;
6062 /* Clear out the dial buffer */
6063 p->dop.dialstr[0] = '\0';
6064 /* flash hookswitch */
6065 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6066 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6067 nbridge->name, strerror(errno));
6069 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6070 unalloc_sub(p, SUB_THREEWAY);
6071 p->owner = p->subs[SUB_REAL].owner;
6072 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6073 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6074 ast_hangup(chan);
6075 return NULL;
6076 } else {
6077 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6078 dahdi_wait_event(p->subs[index].dfd);
6079 tone_zone_play_tone(p->subs[index].dfd, -1);
6080 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6081 unalloc_sub(p, SUB_THREEWAY);
6082 p->owner = p->subs[SUB_REAL].owner;
6083 ast_hangup(chan);
6084 return NULL;
6086 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6087 ((exten[0] != '*') || (strlen(exten) > 2))) {
6088 if (option_debug)
6089 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);
6090 break;
6092 if (!timeout)
6093 timeout = gendigittimeout;
6094 if (len && !ast_ignore_pattern(chan->context, exten))
6095 tone_zone_play_tone(p->subs[index].dfd, -1);
6097 break;
6098 case SIG_FXSLS:
6099 case SIG_FXSGS:
6100 case SIG_FXSKS:
6101 #ifdef HAVE_PRI
6102 if (p->pri) {
6103 /* This is a GR-303 trunk actually. Wait for the first ring... */
6104 struct ast_frame *f;
6105 int res;
6106 time_t start;
6108 time(&start);
6109 ast_setstate(chan, AST_STATE_RING);
6110 while (time(NULL) < start + 3) {
6111 res = ast_waitfor(chan, 1000);
6112 if (res) {
6113 f = ast_read(chan);
6114 if (!f) {
6115 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6116 ast_hangup(chan);
6117 return NULL;
6118 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6119 res = 1;
6120 } else
6121 res = 0;
6122 ast_frfree(f);
6123 if (res) {
6124 ast_log(LOG_DEBUG, "Got ring!\n");
6125 res = 0;
6126 break;
6131 #endif
6132 /* check for SMDI messages */
6133 if (p->use_smdi && p->smdi_iface) {
6134 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6136 if (smdi_msg != NULL) {
6137 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6139 if (smdi_msg->type == 'B')
6140 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6141 else if (smdi_msg->type == 'N')
6142 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6144 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6145 } else {
6146 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6150 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6151 number = smdi_msg->calling_st;
6153 /* If we want caller id, we're in a prering state due to a polarity reversal
6154 * and we're set to use a polarity reversal to trigger the start of caller id,
6155 * grab the caller id and wait for ringing to start... */
6156 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6157 /* If set to use DTMF CID signalling, listen for DTMF */
6158 if (p->cid_signalling == CID_SIG_DTMF) {
6159 int i = 0;
6160 cs = NULL;
6161 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6162 "channel %s\n", chan->name);
6163 dahdi_setlinear(p->subs[index].dfd, 0);
6164 res = 2000;
6165 for (;;) {
6166 struct ast_frame *f;
6167 res = ast_waitfor(chan, res);
6168 if (res <= 0) {
6169 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6170 "Exiting simple switch\n");
6171 ast_hangup(chan);
6172 return NULL;
6174 f = ast_read(chan);
6175 if (!f)
6176 break;
6177 if (f->frametype == AST_FRAME_DTMF) {
6178 dtmfbuf[i++] = f->subclass;
6179 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6180 res = 2000;
6182 ast_frfree(f);
6183 if (chan->_state == AST_STATE_RING ||
6184 chan->_state == AST_STATE_RINGING)
6185 break; /* Got ring */
6187 dtmfbuf[i] = '\0';
6188 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6189 /* Got cid and ring. */
6190 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6191 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6192 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6193 dtmfcid, flags);
6194 /* If first byte is NULL, we have no cid */
6195 if (!ast_strlen_zero(dtmfcid))
6196 number = dtmfcid;
6197 else
6198 number = NULL;
6199 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6200 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6201 cs = callerid_new(p->cid_signalling);
6202 if (cs) {
6203 samples = 0;
6204 #if 1
6205 bump_gains(p);
6206 #endif
6207 /* Take out of linear mode for Caller*ID processing */
6208 dahdi_setlinear(p->subs[index].dfd, 0);
6210 /* First we wait and listen for the Caller*ID */
6211 for (;;) {
6212 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6213 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6214 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6215 callerid_free(cs);
6216 ast_hangup(chan);
6217 return NULL;
6219 if (i & DAHDI_IOMUX_SIGEVENT) {
6220 res = dahdi_get_event(p->subs[index].dfd);
6221 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6223 if (p->cid_signalling == CID_SIG_V23_JP) {
6224 #ifdef DAHDI_EVENT_RINGBEGIN
6225 if (res == DAHDI_EVENT_RINGBEGIN) {
6226 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6227 usleep(1);
6229 #endif
6230 } else {
6231 res = 0;
6232 break;
6234 } else if (i & DAHDI_IOMUX_READ) {
6235 res = read(p->subs[index].dfd, buf, sizeof(buf));
6236 if (res < 0) {
6237 if (errno != ELAST) {
6238 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6239 callerid_free(cs);
6240 ast_hangup(chan);
6241 return NULL;
6243 break;
6245 samples += res;
6247 if (p->cid_signalling == CID_SIG_V23_JP) {
6248 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6249 } else {
6250 res = callerid_feed(cs, buf, res, AST_LAW(p));
6253 if (res < 0) {
6254 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6255 break;
6256 } else if (res)
6257 break;
6258 else if (samples > (8000 * 10))
6259 break;
6262 if (res == 1) {
6263 callerid_get(cs, &name, &number, &flags);
6264 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6267 if (p->cid_signalling == CID_SIG_V23_JP) {
6268 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6269 usleep(1);
6270 res = 4000;
6271 } else {
6273 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6274 res = 2000;
6277 for (;;) {
6278 struct ast_frame *f;
6279 res = ast_waitfor(chan, res);
6280 if (res <= 0) {
6281 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6282 "Exiting simple switch\n");
6283 ast_hangup(chan);
6284 return NULL;
6286 if (!(f = ast_read(chan))) {
6287 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6288 ast_hangup(chan);
6289 return NULL;
6291 ast_frfree(f);
6292 if (chan->_state == AST_STATE_RING ||
6293 chan->_state == AST_STATE_RINGING)
6294 break; /* Got ring */
6297 /* We must have a ring by now, so, if configured, lets try to listen for
6298 * distinctive ringing */
6299 if (p->usedistinctiveringdetection == 1) {
6300 len = 0;
6301 distMatches = 0;
6302 /* Clear the current ring data array so we dont have old data in it. */
6303 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6304 curRingData[receivedRingT] = 0;
6305 receivedRingT = 0;
6306 counter = 0;
6307 counter1 = 0;
6308 /* Check to see if context is what it should be, if not set to be. */
6309 if (strcmp(p->context,p->defcontext) != 0) {
6310 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6311 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6314 for (;;) {
6315 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6316 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6317 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6318 callerid_free(cs);
6319 ast_hangup(chan);
6320 return NULL;
6322 if (i & DAHDI_IOMUX_SIGEVENT) {
6323 res = dahdi_get_event(p->subs[index].dfd);
6324 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6325 res = 0;
6326 /* Let us detect distinctive ring */
6328 curRingData[receivedRingT] = p->ringt;
6330 if (p->ringt < p->ringt_base/2)
6331 break;
6332 /* Increment the ringT counter so we can match it against
6333 values in chan_dahdi.conf for distinctive ring */
6334 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6335 break;
6336 } else if (i & DAHDI_IOMUX_READ) {
6337 res = read(p->subs[index].dfd, buf, sizeof(buf));
6338 if (res < 0) {
6339 if (errno != ELAST) {
6340 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6341 callerid_free(cs);
6342 ast_hangup(chan);
6343 return NULL;
6345 break;
6347 if (p->ringt)
6348 p->ringt--;
6349 if (p->ringt == 1) {
6350 res = -1;
6351 break;
6355 if (option_verbose > 2)
6356 /* this only shows up if you have n of the dring patterns filled in */
6357 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6359 for (counter = 0; counter < 3; counter++) {
6360 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6361 channel */
6362 distMatches = 0;
6363 for (counter1 = 0; counter1 < 3; counter1++) {
6364 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6365 (p->drings.ringnum[counter].ring[counter1]-10)) {
6366 distMatches++;
6369 if (distMatches == 3) {
6370 /* The ring matches, set the context to whatever is for distinctive ring.. */
6371 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6372 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6373 if (option_verbose > 2)
6374 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6375 break;
6379 /* Restore linear mode (if appropriate) for Caller*ID processing */
6380 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6381 #if 1
6382 restore_gains(p);
6383 #endif
6384 } else
6385 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6386 } else {
6387 ast_log(LOG_WARNING, "Channel %s in prering "
6388 "state, but I have nothing to do. "
6389 "Terminating simple switch, should be "
6390 "restarted by the actual ring.\n",
6391 chan->name);
6392 ast_hangup(chan);
6393 return NULL;
6395 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6396 /* FSK Bell202 callerID */
6397 cs = callerid_new(p->cid_signalling);
6398 if (cs) {
6399 #if 1
6400 bump_gains(p);
6401 #endif
6402 samples = 0;
6403 len = 0;
6404 distMatches = 0;
6405 /* Clear the current ring data array so we dont have old data in it. */
6406 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6407 curRingData[receivedRingT] = 0;
6408 receivedRingT = 0;
6409 counter = 0;
6410 counter1 = 0;
6411 /* Check to see if context is what it should be, if not set to be. */
6412 if (strcmp(p->context,p->defcontext) != 0) {
6413 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6414 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6417 /* Take out of linear mode for Caller*ID processing */
6418 dahdi_setlinear(p->subs[index].dfd, 0);
6419 for (;;) {
6420 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6421 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6422 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6423 callerid_free(cs);
6424 ast_hangup(chan);
6425 return NULL;
6427 if (i & DAHDI_IOMUX_SIGEVENT) {
6428 res = dahdi_get_event(p->subs[index].dfd);
6429 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6430 /* If we get a PR event, they hung up while processing calerid */
6431 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6432 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6433 p->polarity = POLARITY_IDLE;
6434 callerid_free(cs);
6435 ast_hangup(chan);
6436 return NULL;
6438 res = 0;
6439 /* Let us detect callerid when the telco uses distinctive ring */
6441 curRingData[receivedRingT] = p->ringt;
6443 if (p->ringt < p->ringt_base/2)
6444 break;
6445 /* Increment the ringT counter so we can match it against
6446 values in chan_dahdi.conf for distinctive ring */
6447 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6448 break;
6449 } else if (i & DAHDI_IOMUX_READ) {
6450 res = read(p->subs[index].dfd, buf, sizeof(buf));
6451 if (res < 0) {
6452 if (errno != ELAST) {
6453 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6454 callerid_free(cs);
6455 ast_hangup(chan);
6456 return NULL;
6458 break;
6460 if (p->ringt)
6461 p->ringt--;
6462 if (p->ringt == 1) {
6463 res = -1;
6464 break;
6466 samples += res;
6467 res = callerid_feed(cs, buf, res, AST_LAW(p));
6468 if (res < 0) {
6469 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6470 break;
6471 } else if (res)
6472 break;
6473 else if (samples > (8000 * 10))
6474 break;
6477 if (res == 1) {
6478 callerid_get(cs, &name, &number, &flags);
6479 if (option_debug)
6480 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6482 if (distinctiveringaftercid == 1) {
6483 /* Clear the current ring data array so we dont have old data in it. */
6484 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6485 curRingData[receivedRingT] = 0;
6487 receivedRingT = 0;
6488 if (option_verbose > 2)
6489 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6490 for (;;) {
6491 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6492 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6493 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6494 callerid_free(cs);
6495 ast_hangup(chan);
6496 return NULL;
6498 if (i & DAHDI_IOMUX_SIGEVENT) {
6499 res = dahdi_get_event(p->subs[index].dfd);
6500 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6501 res = 0;
6502 /* Let us detect callerid when the telco uses distinctive ring */
6504 curRingData[receivedRingT] = p->ringt;
6506 if (p->ringt < p->ringt_base/2)
6507 break;
6508 /* Increment the ringT counter so we can match it against
6509 values in chan_dahdi.conf for distinctive ring */
6510 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6511 break;
6512 } else if (i & DAHDI_IOMUX_READ) {
6513 res = read(p->subs[index].dfd, buf, sizeof(buf));
6514 if (res < 0) {
6515 if (errno != ELAST) {
6516 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6517 callerid_free(cs);
6518 ast_hangup(chan);
6519 return NULL;
6521 break;
6523 if (p->ringt)
6524 p->ringt--;
6525 if (p->ringt == 1) {
6526 res = -1;
6527 break;
6532 if (p->usedistinctiveringdetection == 1) {
6533 if (option_verbose > 2)
6534 /* this only shows up if you have n of the dring patterns filled in */
6535 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6537 for (counter = 0; counter < 3; counter++) {
6538 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6539 channel */
6540 if (option_verbose > 2)
6541 /* this only shows up if you have n of the dring patterns filled in */
6542 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6543 p->drings.ringnum[counter].ring[0],
6544 p->drings.ringnum[counter].ring[1],
6545 p->drings.ringnum[counter].ring[2]);
6546 distMatches = 0;
6547 for (counter1 = 0; counter1 < 3; counter1++) {
6548 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6549 (p->drings.ringnum[counter].ring[counter1]-10)) {
6550 distMatches++;
6553 if (distMatches == 3) {
6554 /* The ring matches, set the context to whatever is for distinctive ring.. */
6555 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6556 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6557 if (option_verbose > 2)
6558 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6559 break;
6563 /* Restore linear mode (if appropriate) for Caller*ID processing */
6564 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6565 #if 1
6566 restore_gains(p);
6567 #endif
6568 if (res < 0) {
6569 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6571 } else
6572 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6574 else
6575 cs = NULL;
6577 if (number)
6578 ast_shrink_phone_number(number);
6579 ast_set_callerid(chan, number, name, number);
6581 if (smdi_msg)
6582 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6584 if (cs)
6585 callerid_free(cs);
6587 ast_setstate(chan, AST_STATE_RING);
6588 chan->rings = 1;
6589 p->ringt = p->ringt_base;
6590 res = ast_pbx_run(chan);
6591 if (res) {
6592 ast_hangup(chan);
6593 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6595 return NULL;
6596 default:
6597 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6598 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6599 if (res < 0)
6600 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6602 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6603 if (res < 0)
6604 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6605 ast_hangup(chan);
6606 return NULL;
6609 /* destroy a DAHDI channel, identified by its number */
6610 static int dahdi_destroy_channel_bynum(int channel)
6612 struct dahdi_pvt *tmp = NULL;
6613 struct dahdi_pvt *prev = NULL;
6615 tmp = iflist;
6616 while (tmp) {
6617 if (tmp->channel == channel) {
6618 destroy_channel(prev, tmp, 1);
6619 return RESULT_SUCCESS;
6621 prev = tmp;
6622 tmp = tmp->next;
6624 return RESULT_FAILURE;
6627 static int handle_init_event(struct dahdi_pvt *i, int event)
6629 int res;
6630 pthread_t threadid;
6631 pthread_attr_t attr;
6632 struct ast_channel *chan;
6633 pthread_attr_init(&attr);
6634 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6635 /* Handle an event on a given channel for the monitor thread. */
6636 switch (event) {
6637 case DAHDI_EVENT_NONE:
6638 case DAHDI_EVENT_BITSCHANGED:
6639 break;
6640 case DAHDI_EVENT_WINKFLASH:
6641 case DAHDI_EVENT_RINGOFFHOOK:
6642 if (i->inalarm) break;
6643 if (i->radio) break;
6644 /* Got a ring/answer. What kind of channel are we? */
6645 switch (i->sig) {
6646 case SIG_FXOLS:
6647 case SIG_FXOGS:
6648 case SIG_FXOKS:
6649 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6650 if (res && (errno == EBUSY))
6651 break;
6652 if (i->cidspill) {
6653 /* Cancel VMWI spill */
6654 free(i->cidspill);
6655 i->cidspill = NULL;
6657 if (i->immediate) {
6658 dahdi_enable_ec(i);
6659 /* The channel is immediately up. Start right away */
6660 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6661 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6662 if (!chan) {
6663 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6664 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6665 if (res < 0)
6666 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6668 } else {
6669 /* Check for callerid, digits, etc */
6670 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6671 if (chan) {
6672 if (has_voicemail(i))
6673 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6674 else
6675 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6676 if (res < 0)
6677 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
6678 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6679 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6680 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6681 if (res < 0)
6682 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6683 ast_hangup(chan);
6685 } else
6686 ast_log(LOG_WARNING, "Unable to create channel\n");
6688 break;
6689 case SIG_FXSLS:
6690 case SIG_FXSGS:
6691 case SIG_FXSKS:
6692 i->ringt = i->ringt_base;
6693 /* Fall through */
6694 case SIG_EMWINK:
6695 case SIG_FEATD:
6696 case SIG_FEATDMF:
6697 case SIG_FEATDMF_TA:
6698 case SIG_E911:
6699 case SIG_FGC_CAMA:
6700 case SIG_FGC_CAMAMF:
6701 case SIG_FEATB:
6702 case SIG_EM:
6703 case SIG_EM_E1:
6704 case SIG_SFWINK:
6705 case SIG_SF_FEATD:
6706 case SIG_SF_FEATDMF:
6707 case SIG_SF_FEATB:
6708 case SIG_SF:
6709 /* Check for callerid, digits, etc */
6710 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
6711 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6712 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6713 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6714 if (res < 0)
6715 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6716 ast_hangup(chan);
6717 } else if (!chan) {
6718 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
6720 break;
6721 default:
6722 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6723 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6724 if (res < 0)
6725 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6726 return -1;
6728 break;
6729 case DAHDI_EVENT_NOALARM:
6730 i->inalarm = 0;
6731 if (!i->unknown_alarm) {
6732 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
6733 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6734 "Channel: %d\r\n", i->channel);
6735 } else {
6736 i->unknown_alarm = 0;
6738 break;
6739 case DAHDI_EVENT_ALARM:
6740 i->inalarm = 1;
6741 res = get_alarms(i);
6742 handle_alarms(i, res);
6743 /* fall thru intentionally */
6744 case DAHDI_EVENT_ONHOOK:
6745 if (i->radio)
6746 break;
6747 /* Back on hook. Hang up. */
6748 switch (i->sig) {
6749 case SIG_FXOLS:
6750 case SIG_FXOGS:
6751 case SIG_FEATD:
6752 case SIG_FEATDMF:
6753 case SIG_FEATDMF_TA:
6754 case SIG_E911:
6755 case SIG_FGC_CAMA:
6756 case SIG_FGC_CAMAMF:
6757 case SIG_FEATB:
6758 case SIG_EM:
6759 case SIG_EM_E1:
6760 case SIG_EMWINK:
6761 case SIG_SF_FEATD:
6762 case SIG_SF_FEATDMF:
6763 case SIG_SF_FEATB:
6764 case SIG_SF:
6765 case SIG_SFWINK:
6766 case SIG_FXSLS:
6767 case SIG_FXSGS:
6768 case SIG_FXSKS:
6769 case SIG_GR303FXSKS:
6770 dahdi_disable_ec(i);
6771 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6772 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6773 break;
6774 case SIG_GR303FXOKS:
6775 case SIG_FXOKS:
6776 dahdi_disable_ec(i);
6777 /* Diddle the battery for the zhone */
6778 #ifdef ZHONE_HACK
6779 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6780 usleep(1);
6781 #endif
6782 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6783 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6784 break;
6785 case SIG_PRI:
6786 dahdi_disable_ec(i);
6787 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6788 break;
6789 default:
6790 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6791 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6792 return -1;
6794 break;
6795 case DAHDI_EVENT_POLARITY:
6796 switch (i->sig) {
6797 case SIG_FXSLS:
6798 case SIG_FXSKS:
6799 case SIG_FXSGS:
6800 /* We have already got a PR before the channel was
6801 created, but it wasn't handled. We need polarity
6802 to be REV for remote hangup detection to work.
6803 At least in Spain */
6804 if (i->hanguponpolarityswitch)
6805 i->polarity = POLARITY_REV;
6807 if (i->cid_start == CID_START_POLARITY) {
6808 i->polarity = POLARITY_REV;
6809 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
6810 "CID detection on channel %d\n",
6811 i->channel);
6812 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
6813 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6814 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6817 break;
6818 default:
6819 ast_log(LOG_WARNING, "handle_init_event detected "
6820 "polarity reversal on non-FXO (SIG_FXS) "
6821 "interface %d\n", i->channel);
6823 break;
6824 case DAHDI_EVENT_REMOVED: /* destroy channel */
6825 ast_log(LOG_NOTICE,
6826 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6827 i->channel);
6828 dahdi_destroy_channel_bynum(i->channel);
6829 break;
6831 pthread_attr_destroy(&attr);
6832 return 0;
6835 static void *do_monitor(void *data)
6837 int count, res, res2, spoint, pollres=0;
6838 struct dahdi_pvt *i;
6839 struct dahdi_pvt *last = NULL;
6840 time_t thispass = 0, lastpass = 0;
6841 int found;
6842 char buf[1024];
6843 struct pollfd *pfds=NULL;
6844 int lastalloc = -1;
6845 /* This thread monitors all the frame relay interfaces which are not yet in use
6846 (and thus do not have a separate thread) indefinitely */
6847 /* From here on out, we die whenever asked */
6848 #if 0
6849 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
6850 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
6851 return NULL;
6853 ast_log(LOG_DEBUG, "Monitor starting...\n");
6854 #endif
6855 for (;;) {
6856 /* Lock the interface list */
6857 ast_mutex_lock(&iflock);
6858 if (!pfds || (lastalloc != ifcount)) {
6859 if (pfds) {
6860 free(pfds);
6861 pfds = NULL;
6863 if (ifcount) {
6864 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
6865 ast_mutex_unlock(&iflock);
6866 return NULL;
6869 lastalloc = ifcount;
6871 /* Build the stuff we're going to poll on, that is the socket of every
6872 dahdi_pvt that does not have an associated owner channel */
6873 count = 0;
6874 i = iflist;
6875 while (i) {
6876 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
6877 if (!i->owner && !i->subs[SUB_REAL].owner) {
6878 /* This needs to be watched, as it lacks an owner */
6879 pfds[count].fd = i->subs[SUB_REAL].dfd;
6880 pfds[count].events = POLLPRI;
6881 pfds[count].revents = 0;
6882 /* Message waiting or r2 channels also get watched for reading */
6883 if (i->cidspill)
6884 pfds[count].events |= POLLIN;
6885 count++;
6888 i = i->next;
6890 /* Okay, now that we know what to do, release the interface lock */
6891 ast_mutex_unlock(&iflock);
6893 pthread_testcancel();
6894 /* Wait at least a second for something to happen */
6895 res = poll(pfds, count, 1000);
6896 pthread_testcancel();
6897 /* Okay, poll has finished. Let's see what happened. */
6898 if (res < 0) {
6899 if ((errno != EAGAIN) && (errno != EINTR))
6900 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
6901 continue;
6903 /* Alright, lock the interface list again, and let's look and see what has
6904 happened */
6905 ast_mutex_lock(&iflock);
6906 found = 0;
6907 spoint = 0;
6908 lastpass = thispass;
6909 thispass = time(NULL);
6910 i = iflist;
6911 while (i) {
6912 if (thispass != lastpass) {
6913 if (!found && ((i == last) || ((i == iflist) && !last))) {
6914 last = i;
6915 if (last) {
6916 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
6917 (last->sig & __DAHDI_SIG_FXO)) {
6918 res = ast_app_has_voicemail(last->mailbox, NULL);
6919 if (last->msgstate != res) {
6920 int x;
6921 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
6922 x = DAHDI_FLUSH_BOTH;
6923 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
6924 if (res2)
6925 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
6926 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
6927 /* Turn on on hook transfer for 4 seconds */
6928 x = 4000;
6929 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
6930 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
6931 last->cidpos = 0;
6932 last->msgstate = res;
6933 last->onhooktime = thispass;
6935 found ++;
6938 last = last->next;
6942 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
6943 if (i->radio && !i->owner)
6945 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
6946 if (res)
6948 if (option_debug)
6949 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
6950 /* Don't hold iflock while handling init events */
6951 ast_mutex_unlock(&iflock);
6952 handle_init_event(i, res);
6953 ast_mutex_lock(&iflock);
6955 i = i->next;
6956 continue;
6958 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
6959 if (pollres & POLLIN) {
6960 if (i->owner || i->subs[SUB_REAL].owner) {
6961 #ifdef HAVE_PRI
6962 if (!i->pri)
6963 #endif
6964 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
6965 i = i->next;
6966 continue;
6968 if (!i->cidspill) {
6969 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
6970 i = i->next;
6971 continue;
6973 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
6974 if (res > 0) {
6975 /* We read some number of bytes. Write an equal amount of data */
6976 if (res > i->cidlen - i->cidpos)
6977 res = i->cidlen - i->cidpos;
6978 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
6979 if (res2 > 0) {
6980 i->cidpos += res2;
6981 if (i->cidpos >= i->cidlen) {
6982 free(i->cidspill);
6983 i->cidspill = 0;
6984 i->cidpos = 0;
6985 i->cidlen = 0;
6987 } else {
6988 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
6989 i->msgstate = -1;
6991 } else {
6992 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
6995 if (pollres & POLLPRI) {
6996 if (i->owner || i->subs[SUB_REAL].owner) {
6997 #ifdef HAVE_PRI
6998 if (!i->pri)
6999 #endif
7000 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
7001 i = i->next;
7002 continue;
7004 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7005 if (option_debug)
7006 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
7007 /* Don't hold iflock while handling init events */
7008 ast_mutex_unlock(&iflock);
7009 handle_init_event(i, res);
7010 ast_mutex_lock(&iflock);
7013 i=i->next;
7015 ast_mutex_unlock(&iflock);
7017 /* Never reached */
7018 return NULL;
7022 static int restart_monitor(void)
7024 pthread_attr_t attr;
7025 pthread_attr_init(&attr);
7026 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7027 /* If we're supposed to be stopped -- stay stopped */
7028 if (monitor_thread == AST_PTHREADT_STOP)
7029 return 0;
7030 ast_mutex_lock(&monlock);
7031 if (monitor_thread == pthread_self()) {
7032 ast_mutex_unlock(&monlock);
7033 ast_log(LOG_WARNING, "Cannot kill myself\n");
7034 return -1;
7036 if (monitor_thread != AST_PTHREADT_NULL) {
7037 /* Wake up the thread */
7038 pthread_kill(monitor_thread, SIGURG);
7039 } else {
7040 /* Start a new monitor */
7041 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7042 ast_mutex_unlock(&monlock);
7043 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7044 pthread_attr_destroy(&attr);
7045 return -1;
7048 ast_mutex_unlock(&monlock);
7049 pthread_attr_destroy(&attr);
7050 return 0;
7053 #ifdef HAVE_PRI
7054 static int pri_resolve_span(int *span, int channel, int offset, DAHDI_SPANINFO *si)
7056 int x;
7057 int trunkgroup;
7058 /* Get appropriate trunk group if there is one */
7059 trunkgroup = pris[*span].mastertrunkgroup;
7060 if (trunkgroup) {
7061 /* Select a specific trunk group */
7062 for (x = 0; x < NUM_SPANS; x++) {
7063 if (pris[x].trunkgroup == trunkgroup) {
7064 *span = x;
7065 return 0;
7068 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7069 *span = -1;
7070 } else {
7071 if (pris[*span].trunkgroup) {
7072 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7073 *span = -1;
7074 } else if (pris[*span].mastertrunkgroup) {
7075 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7076 *span = -1;
7077 } else {
7078 if (si->totalchans == 31) {
7079 /* E1 */
7080 pris[*span].dchannels[0] = 16 + offset;
7081 } else if (si->totalchans == 24) {
7082 /* T1 or J1 */
7083 pris[*span].dchannels[0] = 24 + offset;
7084 } else if (si->totalchans == 3) {
7085 /* BRI */
7086 pris[*span].dchannels[0] = 3 + offset;
7087 } else {
7088 ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
7089 *span = -1;
7090 return 0;
7092 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7093 pris[*span].offset = offset;
7094 pris[*span].span = *span + 1;
7097 return 0;
7100 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7102 DAHDI_SPANINFO si;
7103 DAHDI_PARAMS p;
7104 int fd;
7105 int span;
7106 int ospan=0;
7107 int x,y;
7108 for (x = 0; x < NUM_SPANS; x++) {
7109 if (pris[x].trunkgroup == trunkgroup) {
7110 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7111 return -1;
7114 for (y = 0; y < NUM_DCHANS; y++) {
7115 if (!channels[y])
7116 break;
7117 memset(&si, 0, sizeof(si));
7118 memset(&p, 0, sizeof(p));
7119 #ifdef HAVE_ZAPTEL
7120 fd = open("/dev/zap/channel", O_RDWR);
7121 #else
7122 fd = open("/dev/dahdi/channel", O_RDWR);
7123 #endif
7124 if (fd < 0) {
7125 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7126 return -1;
7128 x = channels[y];
7129 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7130 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7131 dahdi_close(fd);
7132 return -1;
7134 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7135 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7136 return -1;
7138 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7139 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7140 dahdi_close(fd);
7141 return -1;
7143 span = p.spanno - 1;
7144 if (pris[span].trunkgroup) {
7145 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7146 dahdi_close(fd);
7147 return -1;
7149 if (pris[span].pvts[0]) {
7150 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7151 dahdi_close(fd);
7152 return -1;
7154 if (!y) {
7155 pris[span].trunkgroup = trunkgroup;
7156 pris[span].offset = channels[y] - p.chanpos;
7157 ospan = span;
7159 pris[ospan].dchannels[y] = channels[y];
7160 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7161 pris[span].span = span + 1;
7162 dahdi_close(fd);
7164 return 0;
7167 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7169 if (pris[span].mastertrunkgroup) {
7170 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);
7171 return -1;
7173 pris[span].mastertrunkgroup = trunkgroup;
7174 pris[span].prilogicalspan = logicalspan;
7175 return 0;
7178 #endif
7180 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7182 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7183 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7184 char fn[80];
7185 #if 1
7186 DAHDI_BUFFERINFO bi;
7187 #endif
7188 int res;
7189 int span=0;
7190 int here = 0;
7191 int x;
7192 struct dahdi_pvt **wlist;
7193 struct dahdi_pvt **wend;
7194 DAHDI_PARAMS p;
7196 wlist = &iflist;
7197 wend = &ifend;
7199 #ifdef HAVE_PRI
7200 if (pri) {
7201 wlist = &pri->crvs;
7202 wend = &pri->crvend;
7204 #endif
7206 tmp2 = *wlist;
7207 prev = NULL;
7209 while (tmp2) {
7210 if (!tmp2->destroy) {
7211 if (tmp2->channel == channel) {
7212 tmp = tmp2;
7213 here = 1;
7214 break;
7216 if (tmp2->channel > channel) {
7217 break;
7220 prev = tmp2;
7221 tmp2 = tmp2->next;
7224 if (!here && !reloading) {
7225 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7226 destroy_dahdi_pvt(&tmp);
7227 return NULL;
7229 ast_mutex_init(&tmp->lock);
7230 ifcount++;
7231 for (x = 0; x < 3; x++)
7232 tmp->subs[x].dfd = -1;
7233 tmp->channel = channel;
7236 if (tmp) {
7237 int chan_sig = conf->chan.sig;
7238 if (!here) {
7239 if ((channel != CHAN_PSEUDO) && !pri) {
7240 snprintf(fn, sizeof(fn), "%d", channel);
7241 /* Open non-blocking */
7242 if (!here)
7243 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7244 /* Allocate a DAHDI structure */
7245 if (tmp->subs[SUB_REAL].dfd < 0) {
7246 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);
7247 destroy_dahdi_pvt(&tmp);
7248 return NULL;
7250 memset(&p, 0, sizeof(p));
7251 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7252 if (res < 0) {
7253 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7254 destroy_dahdi_pvt(&tmp);
7255 return NULL;
7257 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7258 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));
7259 destroy_dahdi_pvt(&tmp);
7260 return NULL;
7262 tmp->law = p.curlaw;
7263 tmp->span = p.spanno;
7264 span = p.spanno - 1;
7265 } else {
7266 if (channel == CHAN_PSEUDO)
7267 chan_sig = 0;
7268 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7269 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7270 return NULL;
7273 #ifdef HAVE_PRI
7274 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7275 int offset;
7276 int myswitchtype;
7277 int matchesdchan;
7278 int x,y;
7279 offset = 0;
7280 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7281 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7282 destroy_dahdi_pvt(&tmp);
7283 return NULL;
7285 if (span >= NUM_SPANS) {
7286 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7287 destroy_dahdi_pvt(&tmp);
7288 return NULL;
7289 } else {
7290 DAHDI_SPANINFO si;
7291 si.spanno = 0;
7292 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7293 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7294 destroy_dahdi_pvt(&tmp);
7295 return NULL;
7297 /* Store the logical span first based upon the real span */
7298 tmp->logicalspan = pris[span].prilogicalspan;
7299 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7300 if (span < 0) {
7301 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7302 destroy_dahdi_pvt(&tmp);
7303 return NULL;
7305 if (chan_sig == SIG_PRI)
7306 myswitchtype = conf->pri.switchtype;
7307 else
7308 myswitchtype = PRI_SWITCH_GR303_TMC;
7309 /* Make sure this isn't a d-channel */
7310 matchesdchan=0;
7311 for (x = 0; x < NUM_SPANS; x++) {
7312 for (y = 0; y < NUM_DCHANS; y++) {
7313 if (pris[x].dchannels[y] == tmp->channel) {
7314 matchesdchan = 1;
7315 break;
7319 offset = p.chanpos;
7320 if (!matchesdchan) {
7321 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7322 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7323 destroy_dahdi_pvt(&tmp);
7324 return NULL;
7326 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7327 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7328 destroy_dahdi_pvt(&tmp);
7329 return NULL;
7331 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7332 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7333 destroy_dahdi_pvt(&tmp);
7334 return NULL;
7336 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7337 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7338 destroy_dahdi_pvt(&tmp);
7339 return NULL;
7341 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7342 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7343 destroy_dahdi_pvt(&tmp);
7344 return NULL;
7346 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7347 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7348 destroy_dahdi_pvt(&tmp);
7349 return NULL;
7351 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7352 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7353 destroy_dahdi_pvt(&tmp);
7354 return NULL;
7356 if (pris[span].numchans >= MAX_CHANNELS) {
7357 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7358 pris[span].trunkgroup);
7359 destroy_dahdi_pvt(&tmp);
7360 return NULL;
7362 pris[span].nodetype = conf->pri.nodetype;
7363 pris[span].switchtype = myswitchtype;
7364 pris[span].nsf = conf->pri.nsf;
7365 pris[span].dialplan = conf->pri.dialplan;
7366 pris[span].localdialplan = conf->pri.localdialplan;
7367 pris[span].pvts[pris[span].numchans++] = tmp;
7368 pris[span].minunused = conf->pri.minunused;
7369 pris[span].minidle = conf->pri.minidle;
7370 pris[span].overlapdial = conf->pri.overlapdial;
7371 #ifdef HAVE_PRI_INBANDDISCONNECT
7372 pris[span].inbanddisconnect = conf->pri.inbandrelease;
7373 #endif
7374 pris[span].facilityenable = conf->pri.facilityenable;
7375 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7376 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7377 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7378 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7379 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7380 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7381 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7382 pris[span].resetinterval = conf->pri.resetinterval;
7384 tmp->pri = &pris[span];
7385 tmp->prioffset = offset;
7386 tmp->call = NULL;
7387 } else {
7388 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7389 destroy_dahdi_pvt(&tmp);
7390 return NULL;
7393 } else {
7394 tmp->prioffset = 0;
7396 #endif
7397 } else {
7398 chan_sig = tmp->sig;
7399 memset(&p, 0, sizeof(p));
7400 if (tmp->subs[SUB_REAL].dfd > -1)
7401 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7403 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7404 switch (chan_sig) {
7405 case SIG_FXSKS:
7406 case SIG_FXSLS:
7407 case SIG_EM:
7408 case SIG_EM_E1:
7409 case SIG_EMWINK:
7410 case SIG_FEATD:
7411 case SIG_FEATDMF:
7412 case SIG_FEATDMF_TA:
7413 case SIG_FEATB:
7414 case SIG_E911:
7415 case SIG_SF:
7416 case SIG_SFWINK:
7417 case SIG_FGC_CAMA:
7418 case SIG_FGC_CAMAMF:
7419 case SIG_SF_FEATD:
7420 case SIG_SF_FEATDMF:
7421 case SIG_SF_FEATB:
7422 p.starttime = 250;
7423 break;
7426 if (tmp->radio) {
7427 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7428 p.channo = channel;
7429 p.rxwinktime = 1;
7430 p.rxflashtime = 1;
7431 p.starttime = 1;
7432 p.debouncetime = 5;
7434 if (!tmp->radio) {
7435 p.channo = channel;
7436 /* Override timing settings based on config file */
7437 if (conf->timing.prewinktime >= 0)
7438 p.prewinktime = conf->timing.prewinktime;
7439 if (conf->timing.preflashtime >= 0)
7440 p.preflashtime = conf->timing.preflashtime;
7441 if (conf->timing.winktime >= 0)
7442 p.winktime = conf->timing.winktime;
7443 if (conf->timing.flashtime >= 0)
7444 p.flashtime = conf->timing.flashtime;
7445 if (conf->timing.starttime >= 0)
7446 p.starttime = conf->timing.starttime;
7447 if (conf->timing.rxwinktime >= 0)
7448 p.rxwinktime = conf->timing.rxwinktime;
7449 if (conf->timing.rxflashtime >= 0)
7450 p.rxflashtime = conf->timing.rxflashtime;
7451 if (conf->timing.debouncetime >= 0)
7452 p.debouncetime = conf->timing.debouncetime;
7455 /* dont set parms on a pseudo-channel (or CRV) */
7456 if (tmp->subs[SUB_REAL].dfd >= 0)
7458 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7459 if (res < 0) {
7460 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7461 destroy_dahdi_pvt(&tmp);
7462 return NULL;
7465 #if 1
7466 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7467 memset(&bi, 0, sizeof(bi));
7468 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7469 if (!res) {
7470 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7471 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7472 bi.numbufs = numbufs;
7473 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7474 if (res < 0) {
7475 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7477 } else
7478 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7480 #endif
7481 tmp->immediate = conf->chan.immediate;
7482 tmp->transfertobusy = conf->chan.transfertobusy;
7483 tmp->sig = chan_sig;
7484 tmp->outsigmod = conf->chan.outsigmod;
7485 tmp->ringt_base = ringt_base;
7486 tmp->firstradio = 0;
7487 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7488 tmp->permcallwaiting = conf->chan.callwaiting;
7489 else
7490 tmp->permcallwaiting = 0;
7491 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7492 tmp->destroy = 0;
7493 tmp->drings = drings;
7494 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7495 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7496 tmp->threewaycalling = conf->chan.threewaycalling;
7497 tmp->adsi = conf->chan.adsi;
7498 tmp->use_smdi = conf->chan.use_smdi;
7499 tmp->permhidecallerid = conf->chan.hidecallerid;
7500 tmp->callreturn = conf->chan.callreturn;
7501 tmp->echocancel = conf->chan.echocancel;
7502 tmp->echotraining = conf->chan.echotraining;
7503 tmp->pulse = conf->chan.pulse;
7504 if (tmp->echocancel)
7505 tmp->echocanbridged = conf->chan.echocanbridged;
7506 else {
7507 if (conf->chan.echocanbridged)
7508 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7509 tmp->echocanbridged = 0;
7511 tmp->busydetect = conf->chan.busydetect;
7512 tmp->busycount = conf->chan.busycount;
7513 tmp->busy_tonelength = conf->chan.busy_tonelength;
7514 tmp->busy_quietlength = conf->chan.busy_quietlength;
7515 tmp->callprogress = conf->chan.callprogress;
7516 tmp->cancallforward = conf->chan.cancallforward;
7517 tmp->dtmfrelax = conf->chan.dtmfrelax;
7518 tmp->callwaiting = tmp->permcallwaiting;
7519 tmp->hidecallerid = tmp->permhidecallerid;
7520 tmp->channel = channel;
7521 tmp->stripmsd = conf->chan.stripmsd;
7522 tmp->use_callerid = conf->chan.use_callerid;
7523 tmp->cid_signalling = conf->chan.cid_signalling;
7524 tmp->cid_start = conf->chan.cid_start;
7525 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7526 tmp->restrictcid = conf->chan.restrictcid;
7527 tmp->use_callingpres = conf->chan.use_callingpres;
7528 tmp->priindication_oob = conf->chan.priindication_oob;
7529 tmp->priexclusive = conf->chan.priexclusive;
7530 if (tmp->usedistinctiveringdetection) {
7531 if (!tmp->use_callerid) {
7532 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7533 tmp->use_callerid = 1;
7537 if (tmp->cid_signalling == CID_SIG_SMDI) {
7538 if (!tmp->use_smdi) {
7539 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7540 tmp->use_smdi = 1;
7543 if (tmp->use_smdi) {
7544 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7545 if (!(tmp->smdi_iface)) {
7546 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7547 tmp->use_smdi = 0;
7551 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7552 tmp->amaflags = conf->chan.amaflags;
7553 if (!here) {
7554 tmp->confno = -1;
7555 tmp->propconfno = -1;
7557 tmp->canpark = conf->chan.canpark;
7558 tmp->transfer = conf->chan.transfer;
7559 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7560 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7561 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7562 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7563 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7564 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7565 tmp->cid_ton = 0;
7566 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7567 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7568 tmp->msgstate = -1;
7569 tmp->group = conf->chan.group;
7570 tmp->callgroup = conf->chan.callgroup;
7571 tmp->pickupgroup= conf->chan.pickupgroup;
7572 tmp->rxgain = conf->chan.rxgain;
7573 tmp->txgain = conf->chan.txgain;
7574 tmp->tonezone = conf->chan.tonezone;
7575 tmp->onhooktime = time(NULL);
7576 if (tmp->subs[SUB_REAL].dfd > -1) {
7577 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7578 if (tmp->dsp)
7579 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7580 update_conf(tmp);
7581 if (!here) {
7582 if (chan_sig != SIG_PRI)
7583 /* Hang it up to be sure it's good */
7584 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7586 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7587 #ifdef HAVE_PRI
7588 /* the dchannel is down so put the channel in alarm */
7589 if (tmp->pri && !pri_is_up(tmp->pri)) {
7590 tmp->inalarm = 1;
7592 #endif
7593 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
7594 tmp->inalarm = 1;
7595 handle_alarms(tmp, res);
7596 } else {
7597 /* yes, this looks strange... the unknown_alarm flag is only used to
7598 control whether an 'alarm cleared' message gets generated when we
7599 get an indication that the channel is no longer in alarm status.
7600 however, the channel *could* be in an alarm status that we aren't
7601 aware of (since get_alarms() only reports span alarms, not channel
7602 alarms). setting this flag will cause any potential 'alarm cleared'
7603 message to be suppressed, but if a real alarm occurs before that
7604 happens, this flag will get cleared by it and the situation will
7605 be normal.
7607 tmp->unknown_alarm = 1;
7611 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
7612 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
7613 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
7614 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
7617 if (tmp && !here) {
7618 /* nothing on the iflist */
7619 if (!*wlist) {
7620 *wlist = tmp;
7621 tmp->prev = NULL;
7622 tmp->next = NULL;
7623 *wend = tmp;
7624 } else {
7625 /* at least one member on the iflist */
7626 struct dahdi_pvt *working = *wlist;
7628 /* check if we maybe have to put it on the begining */
7629 if (working->channel > tmp->channel) {
7630 tmp->next = *wlist;
7631 tmp->prev = NULL;
7632 (*wlist)->prev = tmp;
7633 *wlist = tmp;
7634 } else {
7635 /* go through all the members and put the member in the right place */
7636 while (working) {
7637 /* in the middle */
7638 if (working->next) {
7639 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
7640 tmp->next = working->next;
7641 tmp->prev = working;
7642 working->next->prev = tmp;
7643 working->next = tmp;
7644 break;
7646 } else {
7647 /* the last */
7648 if (working->channel < tmp->channel) {
7649 working->next = tmp;
7650 tmp->next = NULL;
7651 tmp->prev = working;
7652 *wend = tmp;
7653 break;
7656 working = working->next;
7661 return tmp;
7664 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
7666 int res;
7667 DAHDI_PARAMS par;
7669 /* First, check group matching */
7670 if (groupmatch) {
7671 if ((p->group & groupmatch) != groupmatch)
7672 return 0;
7673 *groupmatched = 1;
7675 /* Check to see if we have a channel match */
7676 if (channelmatch != -1) {
7677 if (p->channel != channelmatch)
7678 return 0;
7679 *channelmatched = 1;
7681 /* We're at least busy at this point */
7682 if (busy) {
7683 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
7684 *busy = 1;
7686 /* If do not disturb, definitely not */
7687 if (p->dnd)
7688 return 0;
7689 /* If guard time, definitely not */
7690 if (p->guardtime && (time(NULL) < p->guardtime))
7691 return 0;
7693 /* If no owner definitely available */
7694 if (!p->owner) {
7695 #ifdef HAVE_PRI
7696 /* Trust PRI */
7697 if (p->pri) {
7698 if (p->resetting || p->call)
7699 return 0;
7700 else
7701 return 1;
7703 #endif
7704 if (!(p->radio || (p->oprmode < 0)))
7706 if (!p->sig || (p->sig == SIG_FXSLS))
7707 return 1;
7708 /* Check hook state */
7709 if (p->subs[SUB_REAL].dfd > -1)
7710 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
7711 else {
7712 /* Assume not off hook on CVRS */
7713 res = 0;
7714 par.rxisoffhook = 0;
7716 if (res) {
7717 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
7718 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
7719 /* When "onhook" that means no battery on the line, and thus
7720 it is out of service..., if it's on a TDM card... If it's a channel
7721 bank, there is no telling... */
7722 if (par.rxbits > -1)
7723 return 1;
7724 if (par.rxisoffhook)
7725 return 1;
7726 else
7727 #ifdef DAHDI_CHECK_HOOKSTATE
7728 return 0;
7729 #else
7730 return 1;
7731 #endif
7732 } else if (par.rxisoffhook) {
7733 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
7734 /* Not available when the other end is off hook */
7735 return 0;
7738 return 1;
7741 /* If it's not an FXO, forget about call wait */
7742 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
7743 return 0;
7745 if (!p->callwaiting) {
7746 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7747 return 0;
7750 if (p->subs[SUB_CALLWAIT].dfd > -1) {
7751 /* If there is already a call waiting call, then we can't take a second one */
7752 return 0;
7755 if ((p->owner->_state != AST_STATE_UP) &&
7756 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
7757 /* If the current call is not up, then don't allow the call */
7758 return 0;
7760 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
7761 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7762 return 0;
7764 /* We're cool */
7765 return 1;
7768 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
7770 struct dahdi_pvt *p;
7771 DAHDI_BUFFERINFO bi;
7772 int res;
7774 if ((p = ast_malloc(sizeof(*p)))) {
7775 memcpy(p, src, sizeof(struct dahdi_pvt));
7776 ast_mutex_init(&p->lock);
7777 #ifdef HAVE_ZAPTEL
7778 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
7779 #else
7780 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
7781 #endif
7782 /* Allocate a DAHDI structure */
7783 if (p->subs[SUB_REAL].dfd < 0) {
7784 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
7785 destroy_dahdi_pvt(&p);
7786 return NULL;
7788 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7789 if (!res) {
7790 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7791 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7792 bi.numbufs = numbufs;
7793 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7794 if (res < 0) {
7795 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
7797 } else
7798 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
7800 p->destroy = 1;
7801 p->next = iflist;
7802 p->prev = NULL;
7803 iflist = p;
7804 if (iflist->next)
7805 iflist->next->prev = p;
7806 return p;
7810 #ifdef HAVE_PRI
7811 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
7813 int x;
7814 if (backwards)
7815 x = pri->numchans;
7816 else
7817 x = 0;
7818 for (;;) {
7819 if (backwards && (x < 0))
7820 break;
7821 if (!backwards && (x >= pri->numchans))
7822 break;
7823 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7824 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7825 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7826 return x;
7828 if (backwards)
7829 x--;
7830 else
7831 x++;
7833 return -1;
7835 #endif
7837 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
7839 ast_group_t groupmatch = 0;
7840 int channelmatch = -1;
7841 int roundrobin = 0;
7842 int callwait = 0;
7843 int busy = 0;
7844 struct dahdi_pvt *p;
7845 struct ast_channel *tmp = NULL;
7846 char *dest=NULL;
7847 int x;
7848 char *s;
7849 char opt=0;
7850 int res=0, y=0;
7851 int backwards = 0;
7852 #ifdef HAVE_PRI
7853 int crv;
7854 int bearer = -1;
7855 int trunkgroup;
7856 struct dahdi_pri *pri=NULL;
7857 #endif
7858 struct dahdi_pvt *exit, *start, *end;
7859 ast_mutex_t *lock;
7860 int channelmatched = 0;
7861 int groupmatched = 0;
7863 /* Assume we're locking the iflock */
7864 lock = &iflock;
7865 start = iflist;
7866 end = ifend;
7867 if (data) {
7868 dest = ast_strdupa((char *)data);
7869 } else {
7870 ast_log(LOG_WARNING, "Channel requested with no data\n");
7871 return NULL;
7873 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
7874 /* Retrieve the group number */
7875 char *stringp=NULL;
7876 stringp=dest + 1;
7877 s = strsep(&stringp, "/");
7878 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7879 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
7880 return NULL;
7882 groupmatch = ((ast_group_t) 1 << x);
7883 if (toupper(dest[0]) == 'G') {
7884 if (dest[0] == 'G') {
7885 backwards = 1;
7886 p = ifend;
7887 } else
7888 p = iflist;
7889 } else {
7890 if (dest[0] == 'R') {
7891 backwards = 1;
7892 p = round_robin[x]?round_robin[x]->prev:ifend;
7893 if (!p)
7894 p = ifend;
7895 } else {
7896 p = round_robin[x]?round_robin[x]->next:iflist;
7897 if (!p)
7898 p = iflist;
7900 roundrobin = 1;
7902 } else {
7903 char *stringp=NULL;
7904 stringp=dest;
7905 s = strsep(&stringp, "/");
7906 p = iflist;
7907 if (!strcasecmp(s, "pseudo")) {
7908 /* Special case for pseudo */
7909 x = CHAN_PSEUDO;
7910 channelmatch = x;
7912 #ifdef HAVE_PRI
7913 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
7914 if ((trunkgroup < 1) || (crv < 1)) {
7915 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
7916 return NULL;
7918 res--;
7919 for (x = 0; x < NUM_SPANS; x++) {
7920 if (pris[x].trunkgroup == trunkgroup) {
7921 pri = pris + x;
7922 lock = &pri->lock;
7923 start = pri->crvs;
7924 end = pri->crvend;
7925 break;
7928 if (!pri) {
7929 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
7930 return NULL;
7932 channelmatch = crv;
7933 p = pris[x].crvs;
7935 #endif
7936 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7937 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
7938 return NULL;
7939 } else {
7940 channelmatch = x;
7943 /* Search for an unowned channel */
7944 ast_mutex_lock(lock);
7945 exit = p;
7946 while (p && !tmp) {
7947 if (roundrobin)
7948 round_robin[x] = p;
7949 #if 0
7950 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
7951 #endif
7953 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
7954 if (option_debug)
7955 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
7956 if (p->inalarm)
7957 goto next;
7959 callwait = (p->owner != NULL);
7960 #ifdef HAVE_PRI
7961 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
7962 if (p->sig != SIG_FXSKS) {
7963 /* Gotta find an actual channel to use for this
7964 CRV if this isn't a callwait */
7965 bearer = pri_find_empty_chan(pri, 0);
7966 if (bearer < 0) {
7967 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
7968 p = NULL;
7969 break;
7971 pri_assign_bearer(p, pri, pri->pvts[bearer]);
7972 } else {
7973 if (alloc_sub(p, 0)) {
7974 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
7975 p = NULL;
7976 break;
7977 } else
7978 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
7979 p->pri = pri;
7982 #endif
7983 if (p->channel == CHAN_PSEUDO) {
7984 p = chandup(p);
7985 if (!p) {
7986 break;
7989 if (p->owner) {
7990 if (alloc_sub(p, SUB_CALLWAIT)) {
7991 p = NULL;
7992 break;
7995 p->outgoing = 1;
7996 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
7997 #ifdef HAVE_PRI
7998 if (p->bearer) {
7999 /* Log owner to bearer channel, too */
8000 p->bearer->owner = tmp;
8002 #endif
8003 /* Make special notes */
8004 if (res > 1) {
8005 if (opt == 'c') {
8006 /* Confirm answer */
8007 p->confirmanswer = 1;
8008 } else if (opt == 'r') {
8009 /* Distinctive ring */
8010 if (res < 3)
8011 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
8012 else
8013 p->distinctivering = y;
8014 } else if (opt == 'd') {
8015 /* If this is an ISDN call, make it digital */
8016 p->digital = 1;
8017 if (tmp)
8018 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
8019 } else {
8020 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
8023 /* Note if the call is a call waiting call */
8024 if (tmp && callwait)
8025 tmp->cdrflags |= AST_CDR_CALLWAIT;
8026 break;
8028 next:
8029 if (backwards) {
8030 p = p->prev;
8031 if (!p)
8032 p = end;
8033 } else {
8034 p = p->next;
8035 if (!p)
8036 p = start;
8038 /* stop when you roll to the one that we started from */
8039 if (p == exit)
8040 break;
8042 ast_mutex_unlock(lock);
8043 restart_monitor();
8044 if (callwait)
8045 *cause = AST_CAUSE_BUSY;
8046 else if (!tmp) {
8047 if (channelmatched) {
8048 if (busy)
8049 *cause = AST_CAUSE_BUSY;
8050 } else if (groupmatched) {
8051 *cause = AST_CAUSE_CONGESTION;
8055 return tmp;
8059 #ifdef HAVE_PRI
8060 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8062 struct dahdi_pvt *p;
8063 p = pri->crvs;
8064 while (p) {
8065 if (p->channel == crv)
8066 return p;
8067 p = p->next;
8069 return NULL;
8073 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8075 int x;
8076 int span = PRI_SPAN(channel);
8077 int spanfd;
8078 DAHDI_PARAMS param;
8079 int principle = -1;
8080 int explicit = PRI_EXPLICIT(channel);
8081 channel = PRI_CHANNEL(channel);
8083 if (!explicit) {
8084 spanfd = pri_active_dchan_fd(pri);
8085 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8086 return -1;
8087 span = pris[param.spanno - 1].prilogicalspan;
8090 for (x = 0; x < pri->numchans; x++) {
8091 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8092 principle = x;
8093 break;
8097 return principle;
8100 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8102 int x;
8103 struct dahdi_pvt *crv;
8104 if (!c) {
8105 if (principle < 0)
8106 return -1;
8107 return principle;
8109 if ((principle > -1) &&
8110 (principle < pri->numchans) &&
8111 (pri->pvts[principle]) &&
8112 (pri->pvts[principle]->call == c))
8113 return principle;
8114 /* First, check for other bearers */
8115 for (x = 0; x < pri->numchans; x++) {
8116 if (!pri->pvts[x])
8117 continue;
8118 if (pri->pvts[x]->call == c) {
8119 /* Found our call */
8120 if (principle != x) {
8121 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8123 if (option_verbose > 2)
8124 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8125 old->channel, new->channel);
8126 if (new->owner) {
8127 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8128 old->channel, new->channel, new->channel);
8129 return -1;
8131 /* Fix it all up now */
8132 new->owner = old->owner;
8133 old->owner = NULL;
8134 if (new->owner) {
8135 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
8136 new->owner->tech_pvt = new;
8137 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8138 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8139 old->subs[SUB_REAL].owner = NULL;
8140 } else
8141 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);
8142 new->call = old->call;
8143 old->call = NULL;
8145 /* Copy any DSP that may be present */
8146 new->dsp = old->dsp;
8147 new->dsp_features = old->dsp_features;
8148 old->dsp = NULL;
8149 old->dsp_features = 0;
8151 return principle;
8154 /* Now check for a CRV with no bearer */
8155 crv = pri->crvs;
8156 while (crv) {
8157 if (crv->call == c) {
8158 /* This is our match... Perform some basic checks */
8159 if (crv->bearer)
8160 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8161 else if (pri->pvts[principle]->owner)
8162 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8163 else {
8164 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8165 wakeup the potential sleeper */
8166 dahdi_close(crv->subs[SUB_REAL].dfd);
8167 pri->pvts[principle]->call = crv->call;
8168 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8169 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8170 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8171 pri->trunkgroup, crv->channel);
8172 wakeup_sub(crv, SUB_REAL, pri);
8174 return principle;
8176 crv = crv->next;
8178 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8179 return -1;
8182 static void *do_idle_thread(void *vchan)
8184 struct ast_channel *chan = vchan;
8185 struct dahdi_pvt *pvt = chan->tech_pvt;
8186 struct ast_frame *f;
8187 char ex[80];
8188 /* Wait up to 30 seconds for an answer */
8189 int newms, ms = 30000;
8190 if (option_verbose > 2)
8191 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8192 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8193 if (ast_call(chan, ex, 0)) {
8194 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8195 ast_hangup(chan);
8196 return NULL;
8198 while ((newms = ast_waitfor(chan, ms)) > 0) {
8199 f = ast_read(chan);
8200 if (!f) {
8201 /* Got hangup */
8202 break;
8204 if (f->frametype == AST_FRAME_CONTROL) {
8205 switch (f->subclass) {
8206 case AST_CONTROL_ANSWER:
8207 /* Launch the PBX */
8208 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8209 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8210 chan->priority = 1;
8211 if (option_verbose > 3)
8212 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8213 ast_pbx_run(chan);
8214 /* It's already hungup, return immediately */
8215 return NULL;
8216 case AST_CONTROL_BUSY:
8217 if (option_verbose > 3)
8218 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8219 break;
8220 case AST_CONTROL_CONGESTION:
8221 if (option_verbose > 3)
8222 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8223 break;
8226 ast_frfree(f);
8227 ms = newms;
8229 /* Hangup the channel since nothing happend */
8230 ast_hangup(chan);
8231 return NULL;
8234 #ifndef PRI_RESTART
8235 #error "Upgrade your libpri"
8236 #endif
8237 static void dahdi_pri_message(struct pri *pri, char *s)
8239 int x, y;
8240 int dchan = -1, span = -1;
8241 int dchancount = 0;
8243 if (pri) {
8244 for (x = 0; x < NUM_SPANS; x++) {
8245 for (y = 0; y < NUM_DCHANS; y++) {
8246 if (pris[x].dchans[y])
8247 dchancount++;
8249 if (pris[x].dchans[y] == pri)
8250 dchan = y;
8252 if (dchan >= 0) {
8253 span = x;
8254 break;
8256 dchancount = 0;
8258 if ((dchan >= 0) && (span >= 0)) {
8259 if (dchancount > 1)
8260 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
8261 else
8262 ast_verbose("%s", s);
8263 } else
8264 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8265 } else
8266 ast_verbose("%s", s);
8268 ast_mutex_lock(&pridebugfdlock);
8270 if (pridebugfd >= 0)
8271 write(pridebugfd, s, strlen(s));
8273 ast_mutex_unlock(&pridebugfdlock);
8276 static void dahdi_pri_error(struct pri *pri, char *s)
8278 int x, y;
8279 int dchan = -1, span = -1;
8280 int dchancount = 0;
8282 if (pri) {
8283 for (x = 0; x < NUM_SPANS; x++) {
8284 for (y = 0; y < NUM_DCHANS; y++) {
8285 if (pris[x].dchans[y])
8286 dchancount++;
8288 if (pris[x].dchans[y] == pri)
8289 dchan = y;
8291 if (dchan >= 0) {
8292 span = x;
8293 break;
8295 dchancount = 0;
8297 if ((dchan >= 0) && (span >= 0)) {
8298 if (dchancount > 1)
8299 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8300 else
8301 ast_log(LOG_ERROR, "%s", s);
8302 } else
8303 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8304 } else
8305 ast_log(LOG_ERROR, "%s", s);
8307 ast_mutex_lock(&pridebugfdlock);
8309 if (pridebugfd >= 0)
8310 write(pridebugfd, s, strlen(s));
8312 ast_mutex_unlock(&pridebugfdlock);
8315 static int pri_check_restart(struct dahdi_pri *pri)
8317 do {
8318 pri->resetpos++;
8319 } while ((pri->resetpos < pri->numchans) &&
8320 (!pri->pvts[pri->resetpos] ||
8321 pri->pvts[pri->resetpos]->call ||
8322 pri->pvts[pri->resetpos]->resetting));
8323 if (pri->resetpos < pri->numchans) {
8324 /* Mark the channel as resetting and restart it */
8325 pri->pvts[pri->resetpos]->resetting = 1;
8326 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8327 } else {
8328 pri->resetting = 0;
8329 time(&pri->lastreset);
8331 return 0;
8334 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
8336 int x;
8337 int redo;
8338 ast_mutex_unlock(&pri->lock);
8339 ast_mutex_lock(&p->lock);
8340 do {
8341 redo = 0;
8342 for (x = 0; x < 3; x++) {
8343 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
8344 redo++;
8345 DEADLOCK_AVOIDANCE(&p->lock);
8347 if (p->subs[x].owner) {
8348 ast_queue_hangup(p->subs[x].owner);
8349 ast_mutex_unlock(&p->subs[x].owner->lock);
8352 } while (redo);
8353 ast_mutex_unlock(&p->lock);
8354 ast_mutex_lock(&pri->lock);
8355 return 0;
8358 static char * redirectingreason2str(int redirectingreason)
8360 switch (redirectingreason) {
8361 case 0:
8362 return "UNKNOWN";
8363 case 1:
8364 return "BUSY";
8365 case 2:
8366 return "NO_REPLY";
8367 case 0xF:
8368 return "UNCONDITIONAL";
8369 default:
8370 return "NOREDIRECT";
8374 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
8376 switch (plan) {
8377 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8378 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
8379 break;
8380 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8381 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
8382 break;
8383 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8384 snprintf(buf, size, "%s%s", pri->localprefix, number);
8385 break;
8386 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8387 snprintf(buf, size, "%s%s", pri->privateprefix, number);
8388 break;
8389 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8390 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
8391 break;
8392 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8393 snprintf(buf, size, "%s", number);
8394 break;
8398 static int dahdi_setlaw(int dfd, int law)
8400 int res;
8401 res = ioctl(dfd, DAHDI_SETLAW, &law);
8402 if (res)
8403 return res;
8404 return 0;
8407 static void *pri_dchannel(void *vpri)
8409 struct dahdi_pri *pri = vpri;
8410 pri_event *e;
8411 struct pollfd fds[NUM_DCHANS];
8412 int res;
8413 int chanpos = 0;
8414 int x;
8415 int haveidles;
8416 int activeidles;
8417 int nextidle = -1;
8418 struct ast_channel *c;
8419 struct timeval tv, lowest, *next;
8420 struct timeval lastidle = { 0, 0 };
8421 int doidling=0;
8422 char *cc;
8423 char idlen[80];
8424 struct ast_channel *idle;
8425 pthread_t p;
8426 time_t t;
8427 int i, which=-1;
8428 int numdchans;
8429 int cause=0;
8430 struct dahdi_pvt *crv;
8431 pthread_t threadid;
8432 pthread_attr_t attr;
8433 char ani2str[6];
8434 char plancallingnum[256];
8435 char plancallingani[256];
8436 char calledtonstr[10];
8438 gettimeofday(&lastidle, NULL);
8439 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
8440 /* Need to do idle dialing, check to be sure though */
8441 cc = strchr(pri->idleext, '@');
8442 if (cc) {
8443 *cc = '\0';
8444 cc++;
8445 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
8446 #if 0
8447 /* Extensions may not be loaded yet */
8448 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
8449 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
8450 else
8451 #endif
8452 doidling = 1;
8453 } else
8454 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
8456 for (;;) {
8457 for (i = 0; i < NUM_DCHANS; i++) {
8458 if (!pri->dchannels[i])
8459 break;
8460 fds[i].fd = pri->fds[i];
8461 fds[i].events = POLLIN | POLLPRI;
8462 fds[i].revents = 0;
8464 numdchans = i;
8465 time(&t);
8466 ast_mutex_lock(&pri->lock);
8467 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
8468 if (pri->resetting && pri_is_up(pri)) {
8469 if (pri->resetpos < 0)
8470 pri_check_restart(pri);
8471 } else {
8472 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
8473 pri->resetting = 1;
8474 pri->resetpos = -1;
8478 /* Look for any idle channels if appropriate */
8479 if (doidling && pri_is_up(pri)) {
8480 nextidle = -1;
8481 haveidles = 0;
8482 activeidles = 0;
8483 for (x = pri->numchans; x >= 0; x--) {
8484 if (pri->pvts[x] && !pri->pvts[x]->owner &&
8485 !pri->pvts[x]->call) {
8486 if (haveidles < pri->minunused) {
8487 haveidles++;
8488 } else if (!pri->pvts[x]->resetting) {
8489 nextidle = x;
8490 break;
8492 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
8493 activeidles++;
8495 if (nextidle > -1) {
8496 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
8497 /* Don't create a new idle call more than once per second */
8498 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
8499 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
8500 if (idle) {
8501 pri->pvts[nextidle]->isidlecall = 1;
8502 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
8503 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
8504 dahdi_hangup(idle);
8506 } else
8507 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
8508 gettimeofday(&lastidle, NULL);
8510 } else if ((haveidles < pri->minunused) &&
8511 (activeidles > pri->minidle)) {
8512 /* Mark something for hangup if there is something
8513 that can be hungup */
8514 for (x = pri->numchans; x >= 0; x--) {
8515 /* find a candidate channel */
8516 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
8517 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8518 haveidles++;
8519 /* Stop if we have enough idle channels or
8520 can't spare any more active idle ones */
8521 if ((haveidles >= pri->minunused) ||
8522 (activeidles <= pri->minidle))
8523 break;
8528 /* Start with reasonable max */
8529 lowest = ast_tv(60, 0);
8530 for (i = 0; i < NUM_DCHANS; i++) {
8531 /* Find lowest available d-channel */
8532 if (!pri->dchannels[i])
8533 break;
8534 if ((next = pri_schedule_next(pri->dchans[i]))) {
8535 /* We need relative time here */
8536 tv = ast_tvsub(*next, ast_tvnow());
8537 if (tv.tv_sec < 0) {
8538 tv = ast_tv(0,0);
8540 if (doidling || pri->resetting) {
8541 if (tv.tv_sec > 1) {
8542 tv = ast_tv(1, 0);
8544 } else {
8545 if (tv.tv_sec > 60) {
8546 tv = ast_tv(60, 0);
8549 } else if (doidling || pri->resetting) {
8550 /* Make sure we stop at least once per second if we're
8551 monitoring idle channels */
8552 tv = ast_tv(1,0);
8553 } else {
8554 /* Don't poll for more than 60 seconds */
8555 tv = ast_tv(60, 0);
8557 if (!i || ast_tvcmp(tv, lowest) < 0) {
8558 lowest = tv;
8561 ast_mutex_unlock(&pri->lock);
8563 e = NULL;
8564 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
8566 ast_mutex_lock(&pri->lock);
8567 if (!res) {
8568 for (which = 0; which < NUM_DCHANS; which++) {
8569 if (!pri->dchans[which])
8570 break;
8571 /* Just a timeout, run the scheduler */
8572 e = pri_schedule_run(pri->dchans[which]);
8573 if (e)
8574 break;
8576 } else if (res > -1) {
8577 for (which = 0; which < NUM_DCHANS; which++) {
8578 if (!pri->dchans[which])
8579 break;
8580 if (fds[which].revents & POLLPRI) {
8581 /* Check for an event */
8582 x = 0;
8583 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
8584 if (x)
8585 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);
8586 /* Keep track of alarm state */
8587 if (x == DAHDI_EVENT_ALARM) {
8588 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8589 pri_find_dchan(pri);
8590 } else if (x == DAHDI_EVENT_NOALARM) {
8591 pri->dchanavail[which] |= DCHAN_NOTINALARM;
8592 pri_restart(pri->dchans[which]);
8595 if (option_debug)
8596 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
8597 } else if (fds[which].revents & POLLIN) {
8598 e = pri_check_event(pri->dchans[which]);
8600 if (e)
8601 break;
8603 } else if (errno != EINTR)
8604 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8606 if (e) {
8607 if (pri->debug)
8608 pri_dump_event(pri->dchans[which], e);
8610 if (e->e != PRI_EVENT_DCHAN_DOWN) {
8611 if (!(pri->dchanavail[which] & DCHAN_UP)) {
8612 if (option_verbose > 1)
8613 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8615 pri->dchanavail[which] |= DCHAN_UP;
8616 } else {
8617 if (pri->dchanavail[which] & DCHAN_UP) {
8618 if (option_verbose > 1)
8619 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8621 pri->dchanavail[which] &= ~DCHAN_UP;
8624 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
8625 /* Must be an NFAS group that has the secondary dchan active */
8626 pri->pri = pri->dchans[which];
8628 switch (e->e) {
8629 case PRI_EVENT_DCHAN_UP:
8630 if (!pri->pri) pri_find_dchan(pri);
8632 /* Note presense of D-channel */
8633 time(&pri->lastreset);
8635 /* Restart in 5 seconds */
8636 if (pri->resetinterval > -1) {
8637 pri->lastreset -= pri->resetinterval;
8638 pri->lastreset += 5;
8640 pri->resetting = 0;
8641 /* Take the channels from inalarm condition */
8642 for (i = 0; i < pri->numchans; i++)
8643 if (pri->pvts[i]) {
8644 pri->pvts[i]->inalarm = 0;
8646 break;
8647 case PRI_EVENT_DCHAN_DOWN:
8648 pri_find_dchan(pri);
8649 if (!pri_is_up(pri)) {
8650 pri->resetting = 0;
8651 /* Hangup active channels and put them in alarm mode */
8652 for (i = 0; i < pri->numchans; i++) {
8653 struct dahdi_pvt *p = pri->pvts[i];
8654 if (p) {
8655 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8656 /* T309 is not enabled : hangup calls when alarm occurs */
8657 if (p->call) {
8658 if (p->pri && p->pri->pri) {
8659 pri_hangup(p->pri->pri, p->call, -1);
8660 pri_destroycall(p->pri->pri, p->call);
8661 p->call = NULL;
8662 } else
8663 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8665 if (p->realcall) {
8666 pri_hangup_all(p->realcall, pri);
8667 } else if (p->owner)
8668 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8670 p->inalarm = 1;
8674 break;
8675 case PRI_EVENT_RESTART:
8676 if (e->restart.channel > -1) {
8677 chanpos = pri_find_principle(pri, e->restart.channel);
8678 if (chanpos < 0)
8679 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8680 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8681 else {
8682 if (option_verbose > 2)
8683 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
8684 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8685 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8686 if (pri->pvts[chanpos]->call) {
8687 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
8688 pri->pvts[chanpos]->call = NULL;
8690 /* Force soft hangup if appropriate */
8691 if (pri->pvts[chanpos]->realcall)
8692 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8693 else if (pri->pvts[chanpos]->owner)
8694 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8695 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8697 } else {
8698 if (option_verbose > 2)
8699 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
8700 for (x = 0; x < pri->numchans; x++)
8701 if (pri->pvts[x]) {
8702 ast_mutex_lock(&pri->pvts[x]->lock);
8703 if (pri->pvts[x]->call) {
8704 pri_destroycall(pri->pri, pri->pvts[x]->call);
8705 pri->pvts[x]->call = NULL;
8707 if (pri->pvts[chanpos]->realcall)
8708 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8709 else if (pri->pvts[x]->owner)
8710 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8711 ast_mutex_unlock(&pri->pvts[x]->lock);
8714 break;
8715 case PRI_EVENT_KEYPAD_DIGIT:
8716 chanpos = pri_find_principle(pri, e->digit.channel);
8717 if (chanpos < 0) {
8718 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8719 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
8720 } else {
8721 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
8722 if (chanpos > -1) {
8723 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8724 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8725 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
8726 /* how to do that */
8727 int digitlen = strlen(e->digit.digits);
8728 char digit;
8729 int i;
8730 for (i = 0; i < digitlen; i++) {
8731 digit = e->digit.digits[i];
8733 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8734 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8738 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8741 break;
8743 case PRI_EVENT_INFO_RECEIVED:
8744 chanpos = pri_find_principle(pri, e->ring.channel);
8745 if (chanpos < 0) {
8746 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
8747 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8748 } else {
8749 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8750 if (chanpos > -1) {
8751 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8752 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8753 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8754 /* how to do that */
8755 int digitlen = strlen(e->ring.callednum);
8756 char digit;
8757 int i;
8758 for (i = 0; i < digitlen; i++) {
8759 digit = e->ring.callednum[i];
8761 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8762 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8766 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8769 break;
8770 case PRI_EVENT_RING:
8771 crv = NULL;
8772 if (e->ring.channel == -1)
8773 chanpos = pri_find_empty_chan(pri, 1);
8774 else
8775 chanpos = pri_find_principle(pri, e->ring.channel);
8776 /* if no channel specified find one empty */
8777 if (chanpos < 0) {
8778 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8779 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8780 } else {
8781 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8782 if (pri->pvts[chanpos]->owner) {
8783 if (pri->pvts[chanpos]->call == e->ring.call) {
8784 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8785 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8786 break;
8787 } else {
8788 /* This is where we handle initial glare */
8789 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8790 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8791 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8792 chanpos = -1;
8795 if (chanpos > -1)
8796 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8798 if ((chanpos < 0) && (e->ring.flexible))
8799 chanpos = pri_find_empty_chan(pri, 1);
8800 if (chanpos > -1) {
8801 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8802 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8803 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8804 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8805 if (crv)
8806 ast_mutex_lock(&crv->lock);
8807 if (!crv || crv->owner) {
8808 pri->pvts[chanpos]->call = NULL;
8809 if (crv) {
8810 if (crv->owner)
8811 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8812 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);
8813 } else
8814 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);
8815 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8816 if (crv)
8817 ast_mutex_unlock(&crv->lock);
8818 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8819 break;
8822 pri->pvts[chanpos]->call = e->ring.call;
8823 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8824 if (pri->pvts[chanpos]->use_callerid) {
8825 ast_shrink_phone_number(plancallingnum);
8826 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
8827 #ifdef PRI_ANI
8828 if (!ast_strlen_zero(e->ring.callingani)) {
8829 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
8830 ast_shrink_phone_number(plancallingani);
8831 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
8832 } else {
8833 pri->pvts[chanpos]->cid_ani[0] = '\0';
8835 #endif
8836 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
8837 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8838 } else {
8839 pri->pvts[chanpos]->cid_num[0] = '\0';
8840 pri->pvts[chanpos]->cid_ani[0] = '\0';
8841 pri->pvts[chanpos]->cid_name[0] = '\0';
8842 pri->pvts[chanpos]->cid_ton = 0;
8844 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8845 e->ring.redirectingnum, e->ring.callingplanrdnis);
8846 /* If immediate=yes go to s|1 */
8847 if (pri->pvts[chanpos]->immediate) {
8848 if (option_verbose > 2)
8849 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8850 pri->pvts[chanpos]->exten[0] = 's';
8851 pri->pvts[chanpos]->exten[1] = '\0';
8853 /* Get called number */
8854 else if (!ast_strlen_zero(e->ring.callednum)) {
8855 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8856 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8857 } else if (pri->overlapdial)
8858 pri->pvts[chanpos]->exten[0] = '\0';
8859 else {
8860 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8861 pri->pvts[chanpos]->exten[0] = 's';
8862 pri->pvts[chanpos]->exten[1] = '\0';
8864 /* Set DNID on all incoming calls -- even immediate */
8865 if (!ast_strlen_zero(e->ring.callednum))
8866 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8867 /* No number yet, but received "sending complete"? */
8868 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8869 if (option_verbose > 2)
8870 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8871 pri->pvts[chanpos]->exten[0] = 's';
8872 pri->pvts[chanpos]->exten[1] = '\0';
8874 /* Make sure extension exists (or in overlap dial mode, can exist) */
8875 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8876 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8877 /* Setup law */
8878 int law;
8879 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
8880 /* Set to audio mode at this point */
8881 law = 1;
8882 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
8883 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
8885 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
8886 law = DAHDI_LAW_ALAW;
8887 else
8888 law = DAHDI_LAW_MULAW;
8889 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
8890 if (res < 0)
8891 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
8892 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8893 if (res < 0)
8894 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
8895 if (e->ring.complete || !pri->overlapdial) {
8896 /* Just announce proceeding */
8897 pri->pvts[chanpos]->proceeding = 1;
8898 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8899 } else {
8900 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
8901 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8902 else
8903 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8905 /* Get the use_callingpres state */
8906 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
8908 /* Start PBX */
8909 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8910 /* Release the PRI lock while we create the channel */
8911 ast_mutex_unlock(&pri->lock);
8912 if (crv) {
8913 /* Set bearer and such */
8914 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
8915 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8916 pri->pvts[chanpos]->owner = &inuse;
8917 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
8918 } else {
8919 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
8922 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8924 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
8925 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
8927 if (e->ring.ani2 >= 0) {
8928 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
8929 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8932 #ifdef SUPPORT_USERUSER
8933 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8934 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8936 #endif
8938 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8939 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8940 if (e->ring.redirectingreason >= 0)
8941 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8943 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8944 ast_mutex_lock(&pri->lock);
8946 pthread_attr_init(&attr);
8947 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
8948 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
8949 if (option_verbose > 2)
8950 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
8951 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
8952 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8953 } else {
8954 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
8955 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8956 if (c)
8957 ast_hangup(c);
8958 else {
8959 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
8960 pri->pvts[chanpos]->call = NULL;
8963 pthread_attr_destroy(&attr);
8964 } else {
8965 ast_mutex_unlock(&pri->lock);
8966 /* Release PRI lock while we create the channel */
8967 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
8968 if (c) {
8969 char calledtonstr[10];
8971 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8973 if (e->ring.ani2 >= 0) {
8974 snprintf(ani2str, 5, "%d", e->ring.ani2);
8975 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
8978 #ifdef SUPPORT_USERUSER
8979 if (!ast_strlen_zero(e->ring.useruserinfo)) {
8980 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
8982 #endif
8984 if (e->ring.redirectingreason >= 0)
8985 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
8987 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
8988 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
8990 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8991 ast_mutex_lock(&pri->lock);
8993 if (option_verbose > 2)
8994 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
8995 plancallingnum, pri->pvts[chanpos]->exten,
8996 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
8997 dahdi_enable_ec(pri->pvts[chanpos]);
8998 } else {
9000 ast_mutex_lock(&pri->lock);
9002 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9003 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9004 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9005 pri->pvts[chanpos]->call = NULL;
9008 } else {
9009 if (option_verbose > 2)
9010 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9011 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
9012 pri->pvts[chanpos]->prioffset, pri->span);
9013 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
9014 pri->pvts[chanpos]->call = NULL;
9015 pri->pvts[chanpos]->exten[0] = '\0';
9017 if (crv)
9018 ast_mutex_unlock(&crv->lock);
9019 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9020 } else {
9021 if (e->ring.flexible)
9022 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
9023 else
9024 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
9026 break;
9027 case PRI_EVENT_RINGING:
9028 chanpos = pri_find_principle(pri, e->ringing.channel);
9029 if (chanpos < 0) {
9030 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9031 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9032 } else {
9033 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9034 if (chanpos < 0) {
9035 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9036 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9037 } else {
9038 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9039 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9040 dahdi_enable_ec(pri->pvts[chanpos]);
9041 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9042 pri->pvts[chanpos]->alerting = 1;
9043 } else
9044 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9045 #ifdef PRI_PROGRESS_MASK
9046 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9047 #else
9048 if (e->ringing.progress == 8) {
9049 #endif
9050 /* Now we can do call progress detection */
9051 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9052 /* RINGING detection isn't required because we got ALERTING signal */
9053 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9054 pri->pvts[chanpos]->dsp_features = 0;
9058 #ifdef SUPPORT_USERUSER
9059 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9060 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9061 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9062 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9063 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9065 #endif
9067 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9070 break;
9071 case PRI_EVENT_PROGRESS:
9072 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9073 chanpos = pri_find_principle(pri, e->proceeding.channel);
9074 if (chanpos > -1) {
9075 #ifdef PRI_PROGRESS_MASK
9076 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9077 #else
9078 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9079 #endif
9080 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9082 if (e->proceeding.cause > -1) {
9083 if (option_verbose > 2)
9084 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9086 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9087 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9088 if (pri->pvts[chanpos]->owner) {
9089 if (option_verbose > 2)
9090 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9092 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9093 f.subclass = AST_CONTROL_BUSY;
9098 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9099 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9100 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9101 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9102 #ifdef PRI_PROGRESS_MASK
9103 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9104 #else
9105 if (e->proceeding.progress == 8) {
9106 #endif
9107 /* Now we can do call progress detection */
9108 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9109 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9110 pri->pvts[chanpos]->dsp_features = 0;
9113 pri->pvts[chanpos]->progress = 1;
9114 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9117 break;
9118 case PRI_EVENT_PROCEEDING:
9119 chanpos = pri_find_principle(pri, e->proceeding.channel);
9120 if (chanpos > -1) {
9121 if (!pri->pvts[chanpos]->proceeding) {
9122 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9124 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9125 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9126 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9127 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9128 #ifdef PRI_PROGRESS_MASK
9129 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9130 #else
9131 if (e->proceeding.progress == 8) {
9132 #endif
9133 /* Now we can do call progress detection */
9134 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9135 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9136 pri->pvts[chanpos]->dsp_features = 0;
9138 /* Bring voice path up */
9139 f.subclass = AST_CONTROL_PROGRESS;
9140 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9142 pri->pvts[chanpos]->proceeding = 1;
9143 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9146 break;
9147 case PRI_EVENT_FACNAME:
9148 chanpos = pri_find_principle(pri, e->facname.channel);
9149 if (chanpos < 0) {
9150 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9151 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9152 } else {
9153 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
9154 if (chanpos < 0) {
9155 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
9156 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9157 } else {
9158 /* Re-use *69 field for PRI */
9159 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9160 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
9161 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
9162 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
9163 dahdi_enable_ec(pri->pvts[chanpos]);
9164 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9167 break;
9168 case PRI_EVENT_ANSWER:
9169 chanpos = pri_find_principle(pri, e->answer.channel);
9170 if (chanpos < 0) {
9171 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
9172 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9173 } else {
9174 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
9175 if (chanpos < 0) {
9176 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
9177 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9178 } else {
9179 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9180 /* Now we can do call progress detection */
9182 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9183 * By this time, we need DTMF detection and other features that were previously disabled
9184 * -- Matt F */
9185 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9186 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9187 pri->pvts[chanpos]->dsp_features = 0;
9189 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
9190 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
9191 x = DAHDI_START;
9192 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
9193 if (res < 0) {
9194 if (errno != EINPROGRESS) {
9195 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
9198 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9199 pri->pvts[chanpos]->dialing = 1;
9200 /* Send any "w" waited stuff */
9201 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
9202 if (res < 0) {
9203 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
9204 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9205 } else
9206 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9207 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9208 } else if (pri->pvts[chanpos]->confirmanswer) {
9209 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9210 } else {
9211 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9212 /* Enable echo cancellation if it's not on already */
9213 dahdi_enable_ec(pri->pvts[chanpos]);
9216 #ifdef SUPPORT_USERUSER
9217 if (!ast_strlen_zero(e->answer.useruserinfo)) {
9218 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9219 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9220 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
9221 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9223 #endif
9225 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9228 break;
9229 case PRI_EVENT_HANGUP:
9230 chanpos = pri_find_principle(pri, e->hangup.channel);
9231 if (chanpos < 0) {
9232 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
9233 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9234 } else {
9235 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9236 if (chanpos > -1) {
9237 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9238 if (!pri->pvts[chanpos]->alreadyhungup) {
9239 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9240 pri->pvts[chanpos]->alreadyhungup = 1;
9241 if (pri->pvts[chanpos]->realcall)
9242 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9243 else if (pri->pvts[chanpos]->owner) {
9244 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9245 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9246 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9247 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9248 else {
9249 switch (e->hangup.cause) {
9250 case PRI_CAUSE_USER_BUSY:
9251 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9252 break;
9253 case PRI_CAUSE_CALL_REJECTED:
9254 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9255 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9256 case PRI_CAUSE_SWITCH_CONGESTION:
9257 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9258 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9259 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9260 break;
9261 default:
9262 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9266 if (option_verbose > 2)
9267 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9268 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9269 } else {
9270 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9271 pri->pvts[chanpos]->call = NULL;
9273 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9274 if (option_verbose > 2)
9275 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9276 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9277 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9278 pri->pvts[chanpos]->resetting = 1;
9280 if (e->hangup.aoc_units > -1)
9281 if (option_verbose > 2)
9282 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9283 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9285 #ifdef SUPPORT_USERUSER
9286 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
9287 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9288 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9289 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9290 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9292 #endif
9294 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9295 } else {
9296 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9297 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9300 break;
9301 #ifndef PRI_EVENT_HANGUP_REQ
9302 #error please update libpri
9303 #endif
9304 case PRI_EVENT_HANGUP_REQ:
9305 chanpos = pri_find_principle(pri, e->hangup.channel);
9306 if (chanpos < 0) {
9307 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9308 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9309 } else {
9310 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9311 if (chanpos > -1) {
9312 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9313 if (pri->pvts[chanpos]->realcall)
9314 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9315 else if (pri->pvts[chanpos]->owner) {
9316 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9317 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9318 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9319 else {
9320 switch (e->hangup.cause) {
9321 case PRI_CAUSE_USER_BUSY:
9322 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9323 break;
9324 case PRI_CAUSE_CALL_REJECTED:
9325 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9326 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9327 case PRI_CAUSE_SWITCH_CONGESTION:
9328 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9329 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9330 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9331 break;
9332 default:
9333 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9336 if (option_verbose > 2)
9337 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);
9338 if (e->hangup.aoc_units > -1)
9339 if (option_verbose > 2)
9340 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9341 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9342 } else {
9343 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9344 pri->pvts[chanpos]->call = NULL;
9346 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9347 if (option_verbose > 2)
9348 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9349 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9350 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9351 pri->pvts[chanpos]->resetting = 1;
9354 #ifdef SUPPORT_USERUSER
9355 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9356 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9357 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9358 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9359 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9361 #endif
9363 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9364 } else {
9365 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);
9368 break;
9369 case PRI_EVENT_HANGUP_ACK:
9370 chanpos = pri_find_principle(pri, e->hangup.channel);
9371 if (chanpos < 0) {
9372 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9373 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9374 } else {
9375 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9376 if (chanpos > -1) {
9377 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9378 pri->pvts[chanpos]->call = NULL;
9379 pri->pvts[chanpos]->resetting = 0;
9380 if (pri->pvts[chanpos]->owner) {
9381 if (option_verbose > 2)
9382 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);
9385 #ifdef SUPPORT_USERUSER
9386 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9387 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9388 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9389 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9390 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9392 #endif
9394 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9397 break;
9398 case PRI_EVENT_CONFIG_ERR:
9399 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
9400 break;
9401 case PRI_EVENT_RESTART_ACK:
9402 chanpos = pri_find_principle(pri, e->restartack.channel);
9403 if (chanpos < 0) {
9404 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9405 channel number, so we have to figure it out... This must be why
9406 everybody resets exactly a channel at a time. */
9407 for (x = 0; x < pri->numchans; x++) {
9408 if (pri->pvts[x] && pri->pvts[x]->resetting) {
9409 chanpos = x;
9410 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9411 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
9412 pri->pvts[chanpos]->prioffset, pri->span);
9413 if (pri->pvts[chanpos]->realcall)
9414 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9415 else if (pri->pvts[chanpos]->owner) {
9416 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
9417 pri->pvts[chanpos]->prioffset, pri->span);
9418 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9420 pri->pvts[chanpos]->resetting = 0;
9421 if (option_verbose > 2)
9422 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9423 pri->pvts[chanpos]->prioffset, pri->span);
9424 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9425 if (pri->resetting)
9426 pri_check_restart(pri);
9427 break;
9430 if (chanpos < 0) {
9431 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
9432 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9434 } else {
9435 if (pri->pvts[chanpos]) {
9436 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9437 if (pri->pvts[chanpos]->realcall)
9438 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9439 else if (pri->pvts[chanpos]->owner) {
9440 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
9441 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9442 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9444 pri->pvts[chanpos]->resetting = 0;
9445 if (option_verbose > 2)
9446 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9447 pri->pvts[chanpos]->prioffset, pri->span);
9448 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9449 if (pri->resetting)
9450 pri_check_restart(pri);
9453 break;
9454 case PRI_EVENT_SETUP_ACK:
9455 chanpos = pri_find_principle(pri, e->setup_ack.channel);
9456 if (chanpos < 0) {
9457 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9458 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
9459 } else {
9460 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
9461 if (chanpos > -1) {
9462 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9463 pri->pvts[chanpos]->setup_ack = 1;
9464 /* Send any queued digits */
9465 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
9466 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
9467 pri_information(pri->pri, pri->pvts[chanpos]->call,
9468 pri->pvts[chanpos]->dialdest[x]);
9470 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9471 } else
9472 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
9474 break;
9475 case PRI_EVENT_NOTIFY:
9476 chanpos = pri_find_principle(pri, e->notify.channel);
9477 if (chanpos < 0) {
9478 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9479 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
9480 } else {
9481 struct ast_frame f = { AST_FRAME_CONTROL, };
9482 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9483 switch (e->notify.info) {
9484 case PRI_NOTIFY_REMOTE_HOLD:
9485 f.subclass = AST_CONTROL_HOLD;
9486 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9487 break;
9488 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9489 f.subclass = AST_CONTROL_UNHOLD;
9490 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9491 break;
9493 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9495 break;
9496 default:
9497 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9500 ast_mutex_unlock(&pri->lock);
9502 /* Never reached */
9503 return NULL;
9506 static int start_pri(struct dahdi_pri *pri)
9508 int res, x;
9509 DAHDI_PARAMS p;
9510 DAHDI_BUFFERINFO bi;
9511 DAHDI_SPANINFO si;
9512 int i;
9514 for (i = 0; i < NUM_DCHANS; i++) {
9515 if (!pri->dchannels[i])
9516 break;
9517 #ifdef HAVE_ZAPTEL
9518 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
9519 #else
9520 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
9521 #endif
9522 x = pri->dchannels[i];
9523 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
9524 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
9525 return -1;
9527 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
9528 if (res) {
9529 dahdi_close(pri->fds[i]);
9530 pri->fds[i] = -1;
9531 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
9532 return -1;
9534 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
9535 dahdi_close(pri->fds[i]);
9536 pri->fds[i] = -1;
9537 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x);
9538 return -1;
9540 memset(&si, 0, sizeof(si));
9541 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
9542 if (res) {
9543 dahdi_close(pri->fds[i]);
9544 pri->fds[i] = -1;
9545 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
9547 if (!si.alarms)
9548 pri->dchanavail[i] |= DCHAN_NOTINALARM;
9549 else
9550 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
9551 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
9552 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
9553 bi.numbufs = 32;
9554 bi.bufsize = 1024;
9555 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
9556 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
9557 dahdi_close(pri->fds[i]);
9558 pri->fds[i] = -1;
9559 return -1;
9561 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9562 /* Force overlap dial if we're doing GR-303! */
9563 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9564 pri->overlapdial = 1;
9565 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
9566 #ifdef HAVE_PRI_INBANDDISCONNECT
9567 pri_set_inbanddisconnect(pri->dchans[i], pri->inbandrelease);
9568 #endif
9569 /* Enslave to master if appropriate */
9570 if (i)
9571 pri_enslave(pri->dchans[0], pri->dchans[i]);
9572 if (!pri->dchans[i]) {
9573 dahdi_close(pri->fds[i]);
9574 pri->fds[i] = -1;
9575 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
9576 return -1;
9578 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
9579 pri_set_nsf(pri->dchans[i], pri->nsf);
9580 #ifdef PRI_GETSET_TIMERS
9581 for (x = 0; x < PRI_MAX_TIMERS; x++) {
9582 if (pritimers[x] != 0)
9583 pri_set_timer(pri->dchans[i], x, pritimers[x]);
9585 #endif
9587 /* Assume primary is the one we use */
9588 pri->pri = pri->dchans[0];
9589 pri->resetpos = -1;
9590 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
9591 for (i = 0; i < NUM_DCHANS; i++) {
9592 if (!pri->dchannels[i])
9593 break;
9594 dahdi_close(pri->fds[i]);
9595 pri->fds[i] = -1;
9597 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
9598 return -1;
9600 return 0;
9603 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
9605 int which, span;
9606 char *ret = NULL;
9608 if (pos != rpos)
9609 return ret;
9611 for (which = span = 0; span < NUM_SPANS; span++) {
9612 if (pris[span].pri && ++which > state) {
9613 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
9614 break;
9617 return ret;
9620 static char *complete_span_4(const char *line, const char *word, int pos, int state)
9622 return complete_span_helper(line,word,pos,state,3);
9625 static char *complete_span_5(const char *line, const char *word, int pos, int state)
9627 return complete_span_helper(line,word,pos,state,4);
9630 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9632 int myfd;
9634 if (!strncasecmp(argv[1], "set", 3)) {
9635 if (argc < 5)
9636 return RESULT_SHOWUSAGE;
9638 if (ast_strlen_zero(argv[4]))
9639 return RESULT_SHOWUSAGE;
9641 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
9642 if (myfd < 0) {
9643 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9644 return RESULT_SUCCESS;
9647 ast_mutex_lock(&pridebugfdlock);
9649 if (pridebugfd >= 0)
9650 close(pridebugfd);
9652 pridebugfd = myfd;
9653 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9655 ast_mutex_unlock(&pridebugfdlock);
9657 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9658 } else {
9659 /* Assume it is unset */
9660 ast_mutex_lock(&pridebugfdlock);
9661 close(pridebugfd);
9662 pridebugfd = -1;
9663 ast_cli(fd, "PRI debug output to file disabled\n");
9664 ast_mutex_unlock(&pridebugfdlock);
9667 return RESULT_SUCCESS;
9670 #ifdef HAVE_PRI_VERSION
9671 static int handle_pri_version(int fd, int agc, char *argv[]) {
9672 ast_cli(fd, "libpri version: %s\n", pri_get_version());
9673 return RESULT_SUCCESS;
9675 #endif
9677 static int handle_pri_debug(int fd, int argc, char *argv[])
9679 int span;
9680 int x;
9681 if (argc < 4) {
9682 return RESULT_SHOWUSAGE;
9684 span = atoi(argv[3]);
9685 if ((span < 1) || (span > NUM_SPANS)) {
9686 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
9687 return RESULT_SUCCESS;
9689 if (!pris[span-1].pri) {
9690 ast_cli(fd, "No PRI running on span %d\n", span);
9691 return RESULT_SUCCESS;
9693 for (x = 0; x < NUM_DCHANS; x++) {
9694 if (pris[span-1].dchans[x])
9695 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9696 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9697 PRI_DEBUG_Q921_STATE);
9699 ast_cli(fd, "Enabled debugging on span %d\n", span);
9700 return RESULT_SUCCESS;
9705 static int handle_pri_no_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], 0);
9724 ast_cli(fd, "Disabled debugging on span %d\n", span);
9725 return RESULT_SUCCESS;
9728 static int handle_pri_really_debug(int fd, int argc, char *argv[])
9730 int span;
9731 int x;
9732 if (argc < 5)
9733 return RESULT_SHOWUSAGE;
9734 span = atoi(argv[4]);
9735 if ((span < 1) || (span > NUM_SPANS)) {
9736 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9737 return RESULT_SUCCESS;
9739 if (!pris[span-1].pri) {
9740 ast_cli(fd, "No PRI running on span %d\n", span);
9741 return RESULT_SUCCESS;
9743 for (x = 0; x < NUM_DCHANS; x++) {
9744 if (pris[span-1].dchans[x])
9745 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9746 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9747 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
9749 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
9750 return RESULT_SUCCESS;
9753 static void build_status(char *s, size_t len, int status, int active)
9755 if (!s || len < 1) {
9756 return;
9758 s[0] = '\0';
9759 if (status & DCHAN_PROVISIONED)
9760 strncat(s, "Provisioned, ", len - strlen(s) - 1);
9761 if (!(status & DCHAN_NOTINALARM))
9762 strncat(s, "In Alarm, ", len - strlen(s) - 1);
9763 if (status & DCHAN_UP)
9764 strncat(s, "Up", len - strlen(s) - 1);
9765 else
9766 strncat(s, "Down", len - strlen(s) - 1);
9767 if (active)
9768 strncat(s, ", Active", len - strlen(s) - 1);
9769 else
9770 strncat(s, ", Standby", len - strlen(s) - 1);
9771 s[len - 1] = '\0';
9774 static int handle_pri_show_spans(int fd, int argc, char *argv[])
9776 int span;
9777 int x;
9778 char status[256];
9779 if (argc != 3)
9780 return RESULT_SHOWUSAGE;
9782 for (span = 0; span < NUM_SPANS; span++) {
9783 if (pris[span].pri) {
9784 for (x = 0; x < NUM_DCHANS; x++) {
9785 if (pris[span].dchannels[x]) {
9786 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
9787 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
9792 return RESULT_SUCCESS;
9795 static int handle_pri_show_span(int fd, int argc, char *argv[])
9797 int span;
9798 int x;
9799 char status[256];
9800 if (argc < 4)
9801 return RESULT_SHOWUSAGE;
9802 span = atoi(argv[3]);
9803 if ((span < 1) || (span > NUM_SPANS)) {
9804 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
9805 return RESULT_SUCCESS;
9807 if (!pris[span-1].pri) {
9808 ast_cli(fd, "No PRI running on span %d\n", span);
9809 return RESULT_SUCCESS;
9811 for (x = 0; x < NUM_DCHANS; x++) {
9812 if (pris[span-1].dchannels[x]) {
9813 #ifdef PRI_DUMP_INFO_STR
9814 char *info_str = NULL;
9815 #endif
9816 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
9817 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
9818 ast_cli(fd, "Status: %s\n", status);
9819 #ifdef PRI_DUMP_INFO_STR
9820 info_str = pri_dump_info_str(pris[span-1].pri);
9821 if (info_str) {
9822 ast_cli(fd, "%s", info_str);
9823 free(info_str);
9825 #else
9826 pri_dump_info(pris[span-1].pri);
9827 #endif
9828 ast_cli(fd, "\n");
9831 return RESULT_SUCCESS;
9834 static int handle_pri_show_debug(int fd, int argc, char *argv[])
9836 int x;
9837 int span;
9838 int count=0;
9839 int debug=0;
9841 for (span = 0; span < NUM_SPANS; span++) {
9842 if (pris[span].pri) {
9843 for (x = 0; x < NUM_DCHANS; x++) {
9844 debug = 0;
9845 if (pris[span].dchans[x]) {
9846 debug = pri_get_debug(pris[span].dchans[x]);
9847 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" );
9848 count++;
9854 ast_mutex_lock(&pridebugfdlock);
9855 if (pridebugfd >= 0)
9856 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9857 ast_mutex_unlock(&pridebugfdlock);
9859 if (!count)
9860 ast_cli(fd, "No debug set or no PRI running\n");
9861 return RESULT_SUCCESS;
9864 static const char pri_debug_help[] =
9865 "Usage: pri debug span <span>\n"
9866 " Enables debugging on a given PRI span\n";
9868 static const char pri_no_debug_help[] =
9869 "Usage: pri no debug span <span>\n"
9870 " Disables debugging on a given PRI span\n";
9872 static const char pri_really_debug_help[] =
9873 "Usage: pri intensive debug span <span>\n"
9874 " Enables debugging down to the Q.921 level\n";
9876 static const char pri_show_span_help[] =
9877 "Usage: pri show span <span>\n"
9878 " Displays PRI Information on a given PRI span\n";
9880 static const char pri_show_spans_help[] =
9881 "Usage: pri show spans\n"
9882 " Displays PRI Information\n";
9884 static struct ast_cli_entry dahdi_pri_cli[] = {
9885 { { "pri", "debug", "span", NULL },
9886 handle_pri_debug, "Enables PRI debugging on a span",
9887 pri_debug_help, complete_span_4 },
9889 { { "pri", "no", "debug", "span", NULL },
9890 handle_pri_no_debug, "Disables PRI debugging on a span",
9891 pri_no_debug_help, complete_span_5 },
9893 { { "pri", "intense", "debug", "span", NULL },
9894 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
9895 pri_really_debug_help, complete_span_5 },
9897 { { "pri", "show", "spans", NULL },
9898 handle_pri_show_spans, "Displays PRI Information",
9899 pri_show_spans_help },
9901 { { "pri", "show", "span", NULL },
9902 handle_pri_show_span, "Displays PRI Information",
9903 pri_show_span_help, complete_span_4 },
9905 { { "pri", "show", "debug", NULL },
9906 handle_pri_show_debug, "Displays current PRI debug settings" },
9908 { { "pri", "set", "debug", "file", NULL },
9909 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
9911 { { "pri", "unset", "debug", "file", NULL },
9912 handle_pri_set_debug_file, "Ends PRI debug output to file" },
9914 #ifdef HAVE_PRI_VERSION
9915 { { "pri", "show", "version", NULL },
9916 handle_pri_version, "Displays version of libpri" },
9917 #endif
9920 #endif /* HAVE_PRI */
9922 static int dahdi_destroy_channel(int fd, int argc, char **argv)
9924 int channel;
9926 if (argc != 4)
9927 return RESULT_SHOWUSAGE;
9929 channel = atoi(argv[3]);
9931 return dahdi_destroy_channel_bynum(channel);
9934 static int setup_dahdi(int reload);
9935 static int dahdi_restart(void)
9937 if (option_verbose > 0)
9938 ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading %s configuration.\n", dahdi_chan_name);
9939 while (iflist) {
9940 if (option_debug)
9941 ast_log(LOG_DEBUG, "Destroying %s channel no. %d\n", dahdi_chan_name, iflist->channel);
9942 /* Also updates iflist: */
9943 destroy_channel(NULL, iflist, 1);
9945 if (option_debug)
9946 ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
9947 if (setup_dahdi(0) != 0) {
9948 ast_log(LOG_WARNING, "Reload channels from %s config failed!\n", dahdi_chan_name);
9949 return 1;
9951 return 0;
9954 static int dahdi_restart_cmd(int fd, int argc, char **argv)
9956 if (argc != 2) {
9957 return RESULT_SHOWUSAGE;
9960 if (dahdi_restart() != 0)
9961 return RESULT_FAILURE;
9962 return RESULT_SUCCESS;
9965 static int dahdi_show_channels(int fd, int argc, char **argv)
9967 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9968 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
9969 struct dahdi_pvt *tmp = NULL;
9970 char tmps[20] = "";
9971 ast_mutex_t *lock;
9972 struct dahdi_pvt *start;
9973 #ifdef HAVE_PRI
9974 int trunkgroup;
9975 struct dahdi_pri *pri = NULL;
9976 int x;
9977 #endif
9979 lock = &iflock;
9980 start = iflist;
9982 #ifdef HAVE_PRI
9983 if (argc == 4) {
9984 if ((trunkgroup = atoi(argv[3])) < 1)
9985 return RESULT_SHOWUSAGE;
9986 for (x = 0; x < NUM_SPANS; x++) {
9987 if (pris[x].trunkgroup == trunkgroup) {
9988 pri = pris + x;
9989 break;
9992 if (pri) {
9993 start = pri->crvs;
9994 lock = &pri->lock;
9995 } else {
9996 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
9997 return RESULT_FAILURE;
9999 } else
10000 #endif
10001 if (argc != 3)
10002 return RESULT_SHOWUSAGE;
10004 ast_mutex_lock(lock);
10005 #ifdef HAVE_PRI
10006 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10007 #else
10008 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10009 #endif
10011 tmp = start;
10012 while (tmp) {
10013 if (tmp->channel > 0) {
10014 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10015 } else
10016 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10017 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10018 tmp = tmp->next;
10020 ast_mutex_unlock(lock);
10021 return RESULT_SUCCESS;
10022 #undef FORMAT
10023 #undef FORMAT2
10026 static int dahdi_show_channel(int fd, int argc, char **argv)
10028 int channel;
10029 struct dahdi_pvt *tmp = NULL;
10030 DAHDI_CONFINFO ci;
10031 DAHDI_PARAMS ps;
10032 int x;
10033 ast_mutex_t *lock;
10034 struct dahdi_pvt *start;
10035 #ifdef HAVE_PRI
10036 char *c;
10037 int trunkgroup;
10038 struct dahdi_pri *pri=NULL;
10039 #endif
10041 lock = &iflock;
10042 start = iflist;
10044 if (argc != 4)
10045 return RESULT_SHOWUSAGE;
10046 #ifdef HAVE_PRI
10047 if ((c = strchr(argv[3], ':'))) {
10048 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10049 return RESULT_SHOWUSAGE;
10050 if ((trunkgroup < 1) || (channel < 1))
10051 return RESULT_SHOWUSAGE;
10052 for (x = 0; x < NUM_SPANS; x++) {
10053 if (pris[x].trunkgroup == trunkgroup) {
10054 pri = pris + x;
10055 break;
10058 if (pri) {
10059 start = pri->crvs;
10060 lock = &pri->lock;
10061 } else {
10062 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10063 return RESULT_FAILURE;
10065 } else
10066 #endif
10067 channel = atoi(argv[3]);
10069 ast_mutex_lock(lock);
10070 tmp = start;
10071 while (tmp) {
10072 if (tmp->channel == channel) {
10073 #ifdef HAVE_PRI
10074 if (pri)
10075 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10076 else
10077 #endif
10078 ast_cli(fd, "Channel: %d\n", tmp->channel);
10079 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10080 ast_cli(fd, "Span: %d\n", tmp->span);
10081 ast_cli(fd, "Extension: %s\n", tmp->exten);
10082 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10083 ast_cli(fd, "Context: %s\n", tmp->context);
10084 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10085 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10086 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10087 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10088 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10089 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10090 ast_cli(fd, "Radio: %d\n", tmp->radio);
10091 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10092 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)" : "");
10093 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)" : "");
10094 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)" : "");
10095 ast_cli(fd, "Confno: %d\n", tmp->confno);
10096 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10097 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10098 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10099 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10100 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10101 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10102 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10103 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10104 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10105 if (tmp->master)
10106 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10107 for (x = 0; x < MAX_SLAVES; x++) {
10108 if (tmp->slaves[x])
10109 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10111 #ifdef HAVE_PRI
10112 if (tmp->pri) {
10113 ast_cli(fd, "PRI Flags: ");
10114 if (tmp->resetting)
10115 ast_cli(fd, "Resetting ");
10116 if (tmp->call)
10117 ast_cli(fd, "Call ");
10118 if (tmp->bearer)
10119 ast_cli(fd, "Bearer ");
10120 ast_cli(fd, "\n");
10121 if (tmp->logicalspan)
10122 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10123 else
10124 ast_cli(fd, "PRI Logical Span: Implicit\n");
10127 #endif
10128 memset(&ci, 0, sizeof(ci));
10129 ps.channo = tmp->channel;
10130 if (tmp->subs[SUB_REAL].dfd > -1) {
10131 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10132 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10134 #ifdef DAHDI_GETCONFMUTE
10135 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10136 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10138 #endif
10139 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10140 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10141 } else {
10142 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10145 ast_mutex_unlock(lock);
10146 return RESULT_SUCCESS;
10148 tmp = tmp->next;
10151 ast_cli(fd, "Unable to find given channel %d\n", channel);
10152 ast_mutex_unlock(lock);
10153 return RESULT_FAILURE;
10156 static char dahdi_show_cadences_usage[] =
10157 "Usage: dahdi show cadences\n"
10158 " Shows all cadences currently defined\n";
10160 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10162 int i, j;
10163 for (i = 0; i < num_cadence; i++) {
10164 char output[1024];
10165 char tmp[16], tmp2[64];
10166 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10167 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10169 for (j = 0; j < 16; j++) {
10170 if (cadences[i].ringcadence[j] == 0)
10171 break;
10172 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10173 if (cidrings[i] * 2 - 1 == j)
10174 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10175 else
10176 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10177 if (j != 0)
10178 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10179 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10181 ast_cli(fd,"%s\n",output);
10183 return 0;
10186 /* Based on irqmiss.c */
10187 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10188 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10189 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10191 int span;
10192 int res;
10193 char alarms[50];
10195 int ctl;
10196 DAHDI_SPANINFO s;
10198 #ifdef HAVE_ZAPTEL
10199 if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
10200 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10201 ast_cli(fd, "No Zaptel interface found.\n");
10202 return RESULT_FAILURE;
10204 #else
10205 if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
10206 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10207 ast_cli(fd, "No DAHDI interface found.\n");
10208 return RESULT_FAILURE;
10210 #endif
10211 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10213 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10214 s.spanno = span;
10215 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10216 if (res) {
10217 continue;
10219 alarms[0] = '\0';
10220 if (s.alarms > 0) {
10221 if (s.alarms & DAHDI_ALARM_BLUE)
10222 strcat(alarms, "BLU/");
10223 if (s.alarms & DAHDI_ALARM_YELLOW)
10224 strcat(alarms, "YEL/");
10225 if (s.alarms & DAHDI_ALARM_RED)
10226 strcat(alarms, "RED/");
10227 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10228 strcat(alarms, "LB/");
10229 if (s.alarms & DAHDI_ALARM_RECOVER)
10230 strcat(alarms, "REC/");
10231 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10232 strcat(alarms, "NOP/");
10233 if (!strlen(alarms))
10234 strcat(alarms, "UUU/");
10235 if (strlen(alarms)) {
10236 /* Strip trailing / */
10237 alarms[strlen(alarms) - 1] = '\0';
10239 } else {
10240 if (s.numchans)
10241 strcpy(alarms, "OK");
10242 else
10243 strcpy(alarms, "UNCONFIGURED");
10246 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10248 close(ctl);
10250 return RESULT_SUCCESS;
10251 #undef FORMAT
10252 #undef FORMAT2
10255 static char show_channels_usage[] =
10256 "Usage: dahdi show channels\n"
10257 " Shows a list of available channels\n";
10259 static char show_channel_usage[] =
10260 "Usage: dahdi show channel <chan num>\n"
10261 " Detailed information about a given channel\n";
10263 static char dahdi_show_status_usage[] =
10264 "Usage: dahdi show status\n"
10265 " Shows a list of DAHDI cards with status\n";
10267 static char destroy_channel_usage[] =
10268 "Usage: dahdi destroy channel <chan num>\n"
10269 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10271 static char dahdi_restart_usage[] =
10272 "Usage: dahdi restart\n"
10273 " Restarts the DAHDI channels: destroys them all and then\n"
10274 " re-reads them from chan_dahdi.conf.\n"
10275 " Note that this will STOP any running CALL on DAHDI channels.\n"
10278 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10279 { "zap", "show", "cadences", NULL },
10280 handle_dahdi_show_cadences, NULL,
10281 NULL };
10283 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10284 { "zap", "show", "channels", NULL },
10285 dahdi_show_channels, NULL,
10286 NULL };
10288 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10289 { "zap", "show", "channel", NULL },
10290 dahdi_show_channel, NULL,
10291 NULL };
10293 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10294 { "zap", "destroy", "channel", NULL },
10295 dahdi_destroy_channel, NULL,
10296 NULL };
10298 static struct ast_cli_entry cli_zap_restart_deprecated = {
10299 { "zap", "restart", NULL },
10300 dahdi_restart_cmd, NULL,
10301 NULL };
10303 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10304 { "zap", "show", "status", NULL },
10305 dahdi_show_status, NULL,
10306 NULL };
10308 static struct ast_cli_entry dahdi_cli[] = {
10309 { { "dahdi", "show", "cadences", NULL },
10310 handle_dahdi_show_cadences, "List cadences",
10311 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10313 { { "dahdi", "show", "channels", NULL},
10314 dahdi_show_channels, "Show active DAHDI channels",
10315 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10317 { { "dahdi", "show", "channel", NULL},
10318 dahdi_show_channel, "Show information on a channel",
10319 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10321 { { "dahdi", "destroy", "channel", NULL},
10322 dahdi_destroy_channel, "Destroy a channel",
10323 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10325 { { "dahdi", "restart", NULL},
10326 dahdi_restart_cmd, "Fully restart DAHDI channels",
10327 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10329 { { "dahdi", "show", "status", NULL},
10330 dahdi_show_status, "Show all DAHDI cards status",
10331 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10334 #define TRANSFER 0
10335 #define HANGUP 1
10337 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10339 if (p) {
10340 switch (mode) {
10341 case TRANSFER:
10342 p->fake_event = DAHDI_EVENT_WINKFLASH;
10343 break;
10344 case HANGUP:
10345 p->fake_event = DAHDI_EVENT_ONHOOK;
10346 break;
10347 default:
10348 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10351 return 0;
10353 static struct dahdi_pvt *find_channel(int channel)
10355 struct dahdi_pvt *p = iflist;
10356 while (p) {
10357 if (p->channel == channel) {
10358 break;
10360 p = p->next;
10362 return p;
10365 #define local_astman_ack(s, m, msg, zap) do { if (!zap) astman_send_ack(s, m, "DAHDI" msg); else astman_send_ack(s, m, "Zap" msg); } while (0)
10366 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10368 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10370 struct dahdi_pvt *p = NULL;
10371 const char *channel = local_astman_header(m, "Channel", zap_mode);
10373 if (ast_strlen_zero(channel)) {
10374 astman_send_error(s, m, "No channel specified");
10375 return 0;
10377 if (!(p = find_channel(atoi(channel)))) {
10378 astman_send_error(s, m, "No such channel");
10379 return 0;
10381 p->dnd = dnd;
10382 local_astman_ack(s, m, "DND", zap_mode);
10384 return 0;
10387 static int zap_action_dndon(struct mansession *s, const struct message *m)
10389 return __action_dnd(s, m, 1, 1);
10392 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10394 return __action_dnd(s, m, 0, 1);
10397 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10399 return __action_dnd(s, m, 1, 0);
10402 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10404 return __action_dnd(s, m, 0, 0);
10407 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10409 struct dahdi_pvt *p = NULL;
10410 const char *channel = local_astman_header(m, "Channel", zap_mode);
10412 if (ast_strlen_zero(channel)) {
10413 astman_send_error(s, m, "No channel specified");
10414 return 0;
10416 if (!(p = find_channel(atoi(channel)))) {
10417 astman_send_error(s, m, "No such channel");
10418 return 0;
10420 dahdi_fake_event(p,TRANSFER);
10421 local_astman_ack(s, m, "Transfer", zap_mode);
10423 return 0;
10426 static int zap_action_transfer(struct mansession *s, const struct message *m)
10428 return __action_transfer(s, m, 1);
10431 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10433 return __action_transfer(s, m, 0);
10436 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
10438 struct dahdi_pvt *p = NULL;
10439 const char *channel = local_astman_header(m, "Channel", zap_mode);
10441 if (ast_strlen_zero(channel)) {
10442 astman_send_error(s, m, "No channel specified");
10443 return 0;
10445 if (!(p = find_channel(atoi(channel)))) {
10446 astman_send_error(s, m, "No such channel");
10447 return 0;
10449 dahdi_fake_event(p, HANGUP);
10450 local_astman_ack(s, m, "Hangup", zap_mode);
10451 return 0;
10454 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10456 return __action_transferhangup(s, m, 1);
10459 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10461 return __action_transferhangup(s, m, 0);
10464 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10466 struct dahdi_pvt *p = NULL;
10467 const char *channel = local_astman_header(m, "Channel", zap_mode);
10468 const char *number = astman_get_header(m, "Number");
10469 int i;
10471 if (ast_strlen_zero(channel)) {
10472 astman_send_error(s, m, "No channel specified");
10473 return 0;
10475 if (ast_strlen_zero(number)) {
10476 astman_send_error(s, m, "No number specified");
10477 return 0;
10479 if (!(p = find_channel(atoi(channel)))) {
10480 astman_send_error(s, m, "No such channel");
10481 return 0;
10483 if (!p->owner) {
10484 astman_send_error(s, m, "Channel does not have an owner");
10485 return 0;
10487 for (i = 0; i < strlen(number); i++) {
10488 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10490 dahdi_queue_frame(p, &f, NULL);
10492 local_astman_ack(s, m, "DialOffHook", zap_mode);
10494 return 0;
10497 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10499 return __action_dialoffhook(s, m, 1);
10502 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10504 return __action_dialoffhook(s, m, 0);
10507 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10509 struct dahdi_pvt *tmp = NULL;
10510 const char *id = astman_get_header(m, "ActionID");
10511 char idText[256] = "";
10513 local_astman_ack(s, m, " channel status will follow", zap_mode);
10514 if (!ast_strlen_zero(id))
10515 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10517 ast_mutex_lock(&iflock);
10519 tmp = iflist;
10520 while (tmp) {
10521 if (tmp->channel > 0) {
10522 int alarm = get_alarms(tmp);
10523 astman_append(s,
10524 "Event: %sShowChannels\r\n"
10525 "Channel: %d\r\n"
10526 "Signalling: %s\r\n"
10527 "Context: %s\r\n"
10528 "DND: %s\r\n"
10529 "Alarm: %s\r\n"
10530 "%s"
10531 "\r\n",
10532 dahdi_chan_name,
10533 tmp->channel, sig2str(tmp->sig), tmp->context,
10534 tmp->dnd ? "Enabled" : "Disabled",
10535 alarm2str(alarm), idText);
10538 tmp = tmp->next;
10541 ast_mutex_unlock(&iflock);
10543 astman_append(s,
10544 "Event: %sShowChannelsComplete\r\n"
10545 "%s"
10546 "\r\n",
10547 dahdi_chan_name,
10548 idText);
10549 return 0;
10552 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10554 return __action_showchannels(s, m, 1);
10557 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10559 return __action_showchannels(s, m, 0);
10562 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10564 if (dahdi_restart() != 0) {
10565 if (zap_mode) {
10566 astman_send_error(s, m, "Failed to restart Zap");
10567 } else {
10568 astman_send_error(s, m, "Failed to restart DAHDI");
10570 return 1;
10572 local_astman_ack(s, m, "Restart: Success", zap_mode);
10573 return 0;
10576 static int zap_action_restart(struct mansession *s, const struct message *m)
10578 return __action_restart(s, m, 1);
10581 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10583 return __action_restart(s, m, 0);
10586 #define local_astman_unregister(a) do { \
10587 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10588 ast_manager_unregister("DAHDI" a); \
10590 ast_manager_unregister("Zap" a); \
10591 } while (0)
10593 static int __unload_module(void)
10595 int x;
10596 struct dahdi_pvt *p, *pl;
10598 #ifdef HAVE_PRI
10599 int i;
10600 for (i = 0; i < NUM_SPANS; i++) {
10601 if (pris[i].master != AST_PTHREADT_NULL)
10602 pthread_cancel(pris[i].master);
10604 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10605 ast_unregister_application(dahdi_send_keypad_facility_app);
10606 #endif
10607 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10608 local_astman_unregister("DialOffHook");
10609 local_astman_unregister("Hangup");
10610 local_astman_unregister("Transfer");
10611 local_astman_unregister("DNDoff");
10612 local_astman_unregister("DNDon");
10613 local_astman_unregister("ShowChannels");
10614 local_astman_unregister("Restart");
10615 ast_channel_unregister(chan_tech);
10616 ast_mutex_lock(&iflock);
10617 /* Hangup all interfaces if they have an owner */
10618 p = iflist;
10619 while (p) {
10620 if (p->owner)
10621 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10622 p = p->next;
10624 ast_mutex_unlock(&iflock);
10625 ast_mutex_lock(&monlock);
10626 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10627 pthread_cancel(monitor_thread);
10628 pthread_kill(monitor_thread, SIGURG);
10629 pthread_join(monitor_thread, NULL);
10631 monitor_thread = AST_PTHREADT_STOP;
10632 ast_mutex_unlock(&monlock);
10634 ast_mutex_lock(&iflock);
10635 /* Destroy all the interfaces and free their memory */
10636 p = iflist;
10637 while (p) {
10638 /* Free any callerid */
10639 if (p->cidspill)
10640 free(p->cidspill);
10641 /* Close the DAHDI thingy */
10642 if (p->subs[SUB_REAL].dfd > -1)
10643 dahdi_close(p->subs[SUB_REAL].dfd);
10644 pl = p;
10645 p = p->next;
10646 x = pl->channel;
10647 /* Free associated memory */
10648 if (pl)
10649 destroy_dahdi_pvt(&pl);
10650 ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10652 iflist = NULL;
10653 ifcount = 0;
10654 ast_mutex_unlock(&iflock);
10655 #ifdef HAVE_PRI
10656 for (i = 0; i < NUM_SPANS; i++) {
10657 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10658 pthread_join(pris[i].master, NULL);
10659 dahdi_close(pris[i].fds[i]);
10661 #endif
10662 return 0;
10665 static int unload_module(void)
10667 #ifdef HAVE_PRI
10668 int y;
10669 for (y = 0; y < NUM_SPANS; y++)
10670 ast_mutex_destroy(&pris[y].lock);
10671 #endif
10672 return __unload_module();
10675 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10677 char *c, *chan;
10678 int x, start, finish;
10679 struct dahdi_pvt *tmp;
10680 #ifdef HAVE_PRI
10681 struct dahdi_pri *pri;
10682 int trunkgroup, y;
10683 #endif
10685 if ((reload == 0) && (conf->chan.sig < 0)) {
10686 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10687 return -1;
10690 c = ast_strdupa(value);
10692 #ifdef HAVE_PRI
10693 pri = NULL;
10694 if (iscrv) {
10695 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10696 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10697 return -1;
10699 if (trunkgroup < 1) {
10700 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10701 return -1;
10703 c += y;
10704 for (y = 0; y < NUM_SPANS; y++) {
10705 if (pris[y].trunkgroup == trunkgroup) {
10706 pri = pris + y;
10707 break;
10710 if (!pri) {
10711 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10712 return -1;
10715 #endif
10717 while ((chan = strsep(&c, ","))) {
10718 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10719 /* Range */
10720 } else if (sscanf(chan, "%d", &start)) {
10721 /* Just one */
10722 finish = start;
10723 } else if (!strcasecmp(chan, "pseudo")) {
10724 finish = start = CHAN_PSEUDO;
10725 if (found_pseudo)
10726 *found_pseudo = 1;
10727 } else {
10728 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10729 return -1;
10731 if (finish < start) {
10732 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10733 x = finish;
10734 finish = start;
10735 start = x;
10738 for (x = start; x <= finish; x++) {
10739 #ifdef HAVE_PRI
10740 tmp = mkintf(x, conf, pri, reload);
10741 #else
10742 tmp = mkintf(x, conf, NULL, reload);
10743 #endif
10745 if (tmp) {
10746 if (option_verbose > 2) {
10747 #ifdef HAVE_PRI
10748 if (pri)
10749 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10750 else
10751 #endif
10752 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10754 } else {
10755 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10756 (reload == 1) ? "reconfigure" : "register", value);
10757 return -1;
10762 return 0;
10765 /** The length of the parameters list of 'dahdichan'.
10766 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10767 #define MAX_CHANLIST_LEN 80
10768 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10770 struct dahdi_pvt *tmp;
10771 char *ringc; /* temporary string for parsing the dring number. */
10772 int y;
10773 int found_pseudo = 0;
10774 char dahdichan[MAX_CHANLIST_LEN] = {};
10776 for (; v; v = v->next) {
10777 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10778 continue;
10780 /* Create the interface list */
10781 if (!strcasecmp(v->name, "channel")
10782 #ifdef HAVE_PRI
10783 || !strcasecmp(v->name, "crv")
10784 #endif
10786 int iscrv;
10787 if (skipchannels)
10788 continue;
10789 iscrv = !strcasecmp(v->name, "crv");
10790 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
10791 return -1;
10792 } else if (!strcasecmp(v->name, "dahdichan")) {
10793 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
10794 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
10795 if (ast_true(v->value))
10796 confp->chan.usedistinctiveringdetection = 1;
10797 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
10798 if (ast_true(v->value))
10799 distinctiveringaftercid = 1;
10800 } else if (!strcasecmp(v->name, "dring1context")) {
10801 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
10802 } else if (!strcasecmp(v->name, "dring2context")) {
10803 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
10804 } else if (!strcasecmp(v->name, "dring3context")) {
10805 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
10806 } else if (!strcasecmp(v->name, "dring1")) {
10807 ringc = v->value;
10808 sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
10809 } else if (!strcasecmp(v->name, "dring2")) {
10810 ringc = v->value;
10811 sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
10812 } else if (!strcasecmp(v->name, "dring3")) {
10813 ringc = v->value;
10814 sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
10815 } else if (!strcasecmp(v->name, "usecallerid")) {
10816 confp->chan.use_callerid = ast_true(v->value);
10817 } else if (!strcasecmp(v->name, "cidsignalling")) {
10818 if (!strcasecmp(v->value, "bell"))
10819 confp->chan.cid_signalling = CID_SIG_BELL;
10820 else if (!strcasecmp(v->value, "v23"))
10821 confp->chan.cid_signalling = CID_SIG_V23;
10822 else if (!strcasecmp(v->value, "dtmf"))
10823 confp->chan.cid_signalling = CID_SIG_DTMF;
10824 else if (!strcasecmp(v->value, "smdi"))
10825 confp->chan.cid_signalling = CID_SIG_SMDI;
10826 else if (!strcasecmp(v->value, "v23_jp"))
10827 confp->chan.cid_signalling = CID_SIG_V23_JP;
10828 else if (ast_true(v->value))
10829 confp->chan.cid_signalling = CID_SIG_BELL;
10830 } else if (!strcasecmp(v->name, "cidstart")) {
10831 if (!strcasecmp(v->value, "ring"))
10832 confp->chan.cid_start = CID_START_RING;
10833 else if (!strcasecmp(v->value, "polarity"))
10834 confp->chan.cid_start = CID_START_POLARITY;
10835 else if (ast_true(v->value))
10836 confp->chan.cid_start = CID_START_RING;
10837 } else if (!strcasecmp(v->name, "threewaycalling")) {
10838 confp->chan.threewaycalling = ast_true(v->value);
10839 } else if (!strcasecmp(v->name, "cancallforward")) {
10840 confp->chan.cancallforward = ast_true(v->value);
10841 } else if (!strcasecmp(v->name, "relaxdtmf")) {
10842 if (ast_true(v->value))
10843 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
10844 else
10845 confp->chan.dtmfrelax = 0;
10846 } else if (!strcasecmp(v->name, "mailbox")) {
10847 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
10848 } else if (!strcasecmp(v->name, "hasvoicemail")) {
10849 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
10850 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
10852 } else if (!strcasecmp(v->name, "adsi")) {
10853 confp->chan.adsi = ast_true(v->value);
10854 } else if (!strcasecmp(v->name, "usesmdi")) {
10855 confp->chan.use_smdi = ast_true(v->value);
10856 } else if (!strcasecmp(v->name, "smdiport")) {
10857 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
10858 } else if (!strcasecmp(v->name, "transfer")) {
10859 confp->chan.transfer = ast_true(v->value);
10860 } else if (!strcasecmp(v->name, "canpark")) {
10861 confp->chan.canpark = ast_true(v->value);
10862 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
10863 confp->chan.echocanbridged = ast_true(v->value);
10864 } else if (!strcasecmp(v->name, "busydetect")) {
10865 confp->chan.busydetect = ast_true(v->value);
10866 } else if (!strcasecmp(v->name, "busycount")) {
10867 confp->chan.busycount = atoi(v->value);
10868 } else if (!strcasecmp(v->name, "busypattern")) {
10869 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
10870 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
10872 } else if (!strcasecmp(v->name, "callprogress")) {
10873 if (ast_true(v->value))
10874 confp->chan.callprogress |= 1;
10875 else
10876 confp->chan.callprogress &= ~1;
10877 } else if (!strcasecmp(v->name, "faxdetect")) {
10878 if (!strcasecmp(v->value, "incoming")) {
10879 confp->chan.callprogress |= 4;
10880 confp->chan.callprogress &= ~2;
10881 } else if (!strcasecmp(v->value, "outgoing")) {
10882 confp->chan.callprogress &= ~4;
10883 confp->chan.callprogress |= 2;
10884 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
10885 confp->chan.callprogress |= 6;
10886 else
10887 confp->chan.callprogress &= ~6;
10888 } else if (!strcasecmp(v->name, "echocancel")) {
10889 if (!ast_strlen_zero(v->value)) {
10890 y = atoi(v->value);
10891 } else
10892 y = 0;
10893 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
10894 confp->chan.echocancel = y;
10895 else {
10896 confp->chan.echocancel = ast_true(v->value);
10897 if (confp->chan.echocancel)
10898 confp->chan.echocancel=128;
10900 } else if (!strcasecmp(v->name, "echotraining")) {
10901 if (sscanf(v->value, "%d", &y) == 1) {
10902 if ((y < 10) || (y > 4000)) {
10903 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
10904 } else {
10905 confp->chan.echotraining = y;
10907 } else if (ast_true(v->value)) {
10908 confp->chan.echotraining = 400;
10909 } else
10910 confp->chan.echotraining = 0;
10911 } else if (!strcasecmp(v->name, "hidecallerid")) {
10912 confp->chan.hidecallerid = ast_true(v->value);
10913 } else if (!strcasecmp(v->name, "hidecalleridname")) {
10914 confp->chan.hidecalleridname = ast_true(v->value);
10915 } else if (!strcasecmp(v->name, "pulsedial")) {
10916 confp->chan.pulse = ast_true(v->value);
10917 } else if (!strcasecmp(v->name, "callreturn")) {
10918 confp->chan.callreturn = ast_true(v->value);
10919 } else if (!strcasecmp(v->name, "callwaiting")) {
10920 confp->chan.callwaiting = ast_true(v->value);
10921 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
10922 confp->chan.callwaitingcallerid = ast_true(v->value);
10923 } else if (!strcasecmp(v->name, "context")) {
10924 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
10925 } else if (!strcasecmp(v->name, "language")) {
10926 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
10927 } else if (!strcasecmp(v->name, "progzone")) {
10928 ast_copy_string(progzone, v->value, sizeof(progzone));
10929 } else if (!strcasecmp(v->name, "mohinterpret")
10930 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
10931 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
10932 } else if (!strcasecmp(v->name, "mohsuggest")) {
10933 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
10934 } else if (!strcasecmp(v->name, "stripmsd")) {
10935 confp->chan.stripmsd = atoi(v->value);
10936 } else if (!strcasecmp(v->name, "jitterbuffers")) {
10937 numbufs = atoi(v->value);
10938 } else if (!strcasecmp(v->name, "group")) {
10939 confp->chan.group = ast_get_group(v->value);
10940 } else if (!strcasecmp(v->name, "callgroup")) {
10941 confp->chan.callgroup = ast_get_group(v->value);
10942 } else if (!strcasecmp(v->name, "pickupgroup")) {
10943 confp->chan.pickupgroup = ast_get_group(v->value);
10944 } else if (!strcasecmp(v->name, "immediate")) {
10945 confp->chan.immediate = ast_true(v->value);
10946 } else if (!strcasecmp(v->name, "transfertobusy")) {
10947 confp->chan.transfertobusy = ast_true(v->value);
10948 } else if (!strcasecmp(v->name, "rxgain")) {
10949 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
10950 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
10952 } else if (!strcasecmp(v->name, "txgain")) {
10953 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
10954 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
10956 } else if (!strcasecmp(v->name, "tonezone")) {
10957 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
10958 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
10960 } else if (!strcasecmp(v->name, "callerid")) {
10961 if (!strcasecmp(v->value, "asreceived")) {
10962 confp->chan.cid_num[0] = '\0';
10963 confp->chan.cid_name[0] = '\0';
10964 } else {
10965 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
10967 } else if (!strcasecmp(v->name, "fullname")) {
10968 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
10969 } else if (!strcasecmp(v->name, "cid_number")) {
10970 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
10971 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
10972 confp->chan.dahditrcallerid = ast_true(v->value);
10973 } else if (!strcasecmp(v->name, "restrictcid")) {
10974 confp->chan.restrictcid = ast_true(v->value);
10975 } else if (!strcasecmp(v->name, "usecallingpres")) {
10976 confp->chan.use_callingpres = ast_true(v->value);
10977 } else if (!strcasecmp(v->name, "accountcode")) {
10978 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
10979 } else if (!strcasecmp(v->name, "amaflags")) {
10980 y = ast_cdr_amaflags2int(v->value);
10981 if (y < 0)
10982 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
10983 else
10984 confp->chan.amaflags = y;
10985 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
10986 confp->chan.polarityonanswerdelay = atoi(v->value);
10987 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
10988 confp->chan.answeronpolarityswitch = ast_true(v->value);
10989 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
10990 confp->chan.hanguponpolarityswitch = ast_true(v->value);
10991 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
10992 confp->chan.sendcalleridafter = atoi(v->value);
10993 } else if (!reload){
10994 if (!strcasecmp(v->name, "signalling")) {
10995 confp->chan.outsigmod = -1;
10996 if (!strcasecmp(v->value, "em")) {
10997 confp->chan.sig = SIG_EM;
10998 } else if (!strcasecmp(v->value, "em_e1")) {
10999 confp->chan.sig = SIG_EM_E1;
11000 } else if (!strcasecmp(v->value, "em_w")) {
11001 confp->chan.sig = SIG_EMWINK;
11002 confp->chan.radio = 0;
11003 } else if (!strcasecmp(v->value, "fxs_ls")) {
11004 confp->chan.sig = SIG_FXSLS;
11005 confp->chan.radio = 0;
11006 } else if (!strcasecmp(v->value, "fxs_gs")) {
11007 confp->chan.sig = SIG_FXSGS;
11008 confp->chan.radio = 0;
11009 } else if (!strcasecmp(v->value, "fxs_ks")) {
11010 confp->chan.sig = SIG_FXSKS;
11011 confp->chan.radio = 0;
11012 } else if (!strcasecmp(v->value, "fxo_ls")) {
11013 confp->chan.sig = SIG_FXOLS;
11014 confp->chan.radio = 0;
11015 } else if (!strcasecmp(v->value, "fxo_gs")) {
11016 confp->chan.sig = SIG_FXOGS;
11017 confp->chan.radio = 0;
11018 } else if (!strcasecmp(v->value, "fxo_ks")) {
11019 confp->chan.sig = SIG_FXOKS;
11020 confp->chan.radio = 0;
11021 } else if (!strcasecmp(v->value, "fxs_rx")) {
11022 confp->chan.sig = SIG_FXSKS;
11023 confp->chan.radio = 1;
11024 } else if (!strcasecmp(v->value, "fxo_rx")) {
11025 confp->chan.sig = SIG_FXOLS;
11026 confp->chan.radio = 1;
11027 } else if (!strcasecmp(v->value, "fxs_tx")) {
11028 confp->chan.sig = SIG_FXSLS;
11029 confp->chan.radio = 1;
11030 } else if (!strcasecmp(v->value, "fxo_tx")) {
11031 confp->chan.sig = SIG_FXOGS;
11032 confp->chan.radio = 1;
11033 } else if (!strcasecmp(v->value, "em_rx")) {
11034 confp->chan.sig = SIG_EM;
11035 confp->chan.radio = 1;
11036 } else if (!strcasecmp(v->value, "em_tx")) {
11037 confp->chan.sig = SIG_EM;
11038 confp->chan.radio = 1;
11039 } else if (!strcasecmp(v->value, "em_rxtx")) {
11040 confp->chan.sig = SIG_EM;
11041 confp->chan.radio = 2;
11042 } else if (!strcasecmp(v->value, "em_txrx")) {
11043 confp->chan.sig = SIG_EM;
11044 confp->chan.radio = 2;
11045 } else if (!strcasecmp(v->value, "sf")) {
11046 confp->chan.sig = SIG_SF;
11047 confp->chan.radio = 0;
11048 } else if (!strcasecmp(v->value, "sf_w")) {
11049 confp->chan.sig = SIG_SFWINK;
11050 confp->chan.radio = 0;
11051 } else if (!strcasecmp(v->value, "sf_featd")) {
11052 confp->chan.sig = SIG_FEATD;
11053 confp->chan.radio = 0;
11054 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11055 confp->chan.sig = SIG_FEATDMF;
11056 confp->chan.radio = 0;
11057 } else if (!strcasecmp(v->value, "sf_featb")) {
11058 confp->chan.sig = SIG_SF_FEATB;
11059 confp->chan.radio = 0;
11060 } else if (!strcasecmp(v->value, "sf")) {
11061 confp->chan.sig = SIG_SF;
11062 confp->chan.radio = 0;
11063 } else if (!strcasecmp(v->value, "sf_rx")) {
11064 confp->chan.sig = SIG_SF;
11065 confp->chan.radio = 1;
11066 } else if (!strcasecmp(v->value, "sf_tx")) {
11067 confp->chan.sig = SIG_SF;
11068 confp->chan.radio = 1;
11069 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11070 confp->chan.sig = SIG_SF;
11071 confp->chan.radio = 2;
11072 } else if (!strcasecmp(v->value, "sf_txrx")) {
11073 confp->chan.sig = SIG_SF;
11074 confp->chan.radio = 2;
11075 } else if (!strcasecmp(v->value, "featd")) {
11076 confp->chan.sig = SIG_FEATD;
11077 confp->chan.radio = 0;
11078 } else if (!strcasecmp(v->value, "featdmf")) {
11079 confp->chan.sig = SIG_FEATDMF;
11080 confp->chan.radio = 0;
11081 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11082 confp->chan.sig = SIG_FEATDMF_TA;
11083 confp->chan.radio = 0;
11084 } else if (!strcasecmp(v->value, "e911")) {
11085 confp->chan.sig = SIG_E911;
11086 confp->chan.radio = 0;
11087 } else if (!strcasecmp(v->value, "fgccama")) {
11088 confp->chan.sig = SIG_FGC_CAMA;
11089 confp->chan.radio = 0;
11090 } else if (!strcasecmp(v->value, "fgccamamf")) {
11091 confp->chan.sig = SIG_FGC_CAMAMF;
11092 confp->chan.radio = 0;
11093 } else if (!strcasecmp(v->value, "featb")) {
11094 confp->chan.sig = SIG_FEATB;
11095 confp->chan.radio = 0;
11096 #ifdef HAVE_PRI
11097 } else if (!strcasecmp(v->value, "pri_net")) {
11098 confp->chan.radio = 0;
11099 confp->chan.sig = SIG_PRI;
11100 confp->pri.nodetype = PRI_NETWORK;
11101 } else if (!strcasecmp(v->value, "pri_cpe")) {
11102 confp->chan.sig = SIG_PRI;
11103 confp->chan.radio = 0;
11104 confp->pri.nodetype = PRI_CPE;
11105 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11106 confp->chan.sig = SIG_GR303FXOKS;
11107 confp->chan.radio = 0;
11108 confp->pri.nodetype = PRI_NETWORK;
11109 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11110 confp->chan.sig = SIG_GR303FXSKS;
11111 confp->chan.radio = 0;
11112 confp->pri.nodetype = PRI_CPE;
11113 #endif
11114 } else {
11115 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11117 } else if (!strcasecmp(v->name, "outsignalling")) {
11118 if (!strcasecmp(v->value, "em")) {
11119 confp->chan.outsigmod = SIG_EM;
11120 } else if (!strcasecmp(v->value, "em_e1")) {
11121 confp->chan.outsigmod = SIG_EM_E1;
11122 } else if (!strcasecmp(v->value, "em_w")) {
11123 confp->chan.outsigmod = SIG_EMWINK;
11124 } else if (!strcasecmp(v->value, "sf")) {
11125 confp->chan.outsigmod = SIG_SF;
11126 } else if (!strcasecmp(v->value, "sf_w")) {
11127 confp->chan.outsigmod = SIG_SFWINK;
11128 } else if (!strcasecmp(v->value, "sf_featd")) {
11129 confp->chan.outsigmod = SIG_FEATD;
11130 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11131 confp->chan.outsigmod = SIG_FEATDMF;
11132 } else if (!strcasecmp(v->value, "sf_featb")) {
11133 confp->chan.outsigmod = SIG_SF_FEATB;
11134 } else if (!strcasecmp(v->value, "sf")) {
11135 confp->chan.outsigmod = SIG_SF;
11136 } else if (!strcasecmp(v->value, "featd")) {
11137 confp->chan.outsigmod = SIG_FEATD;
11138 } else if (!strcasecmp(v->value, "featdmf")) {
11139 confp->chan.outsigmod = SIG_FEATDMF;
11140 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11141 confp->chan.outsigmod = SIG_FEATDMF_TA;
11142 } else if (!strcasecmp(v->value, "e911")) {
11143 confp->chan.outsigmod = SIG_E911;
11144 } else if (!strcasecmp(v->value, "fgccama")) {
11145 confp->chan.outsigmod = SIG_FGC_CAMA;
11146 } else if (!strcasecmp(v->value, "fgccamamf")) {
11147 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11148 } else if (!strcasecmp(v->value, "featb")) {
11149 confp->chan.outsigmod = SIG_FEATB;
11150 } else {
11151 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11153 #ifdef HAVE_PRI
11154 } else if (!strcasecmp(v->name, "pridialplan")) {
11155 if (!strcasecmp(v->value, "national")) {
11156 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11157 } else if (!strcasecmp(v->value, "unknown")) {
11158 confp->pri.dialplan = PRI_UNKNOWN + 1;
11159 } else if (!strcasecmp(v->value, "private")) {
11160 confp->pri.dialplan = PRI_PRIVATE + 1;
11161 } else if (!strcasecmp(v->value, "international")) {
11162 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11163 } else if (!strcasecmp(v->value, "local")) {
11164 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11165 } else if (!strcasecmp(v->value, "dynamic")) {
11166 confp->pri.dialplan = -1;
11167 } else {
11168 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11170 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11171 if (!strcasecmp(v->value, "national")) {
11172 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11173 } else if (!strcasecmp(v->value, "unknown")) {
11174 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11175 } else if (!strcasecmp(v->value, "private")) {
11176 confp->pri.localdialplan = PRI_PRIVATE + 1;
11177 } else if (!strcasecmp(v->value, "international")) {
11178 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11179 } else if (!strcasecmp(v->value, "local")) {
11180 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11181 } else if (!strcasecmp(v->value, "dynamic")) {
11182 confp->pri.localdialplan = -1;
11183 } else {
11184 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11186 } else if (!strcasecmp(v->name, "switchtype")) {
11187 if (!strcasecmp(v->value, "national"))
11188 confp->pri.switchtype = PRI_SWITCH_NI2;
11189 else if (!strcasecmp(v->value, "ni1"))
11190 confp->pri.switchtype = PRI_SWITCH_NI1;
11191 else if (!strcasecmp(v->value, "dms100"))
11192 confp->pri.switchtype = PRI_SWITCH_DMS100;
11193 else if (!strcasecmp(v->value, "4ess"))
11194 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11195 else if (!strcasecmp(v->value, "5ess"))
11196 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11197 else if (!strcasecmp(v->value, "euroisdn"))
11198 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11199 else if (!strcasecmp(v->value, "qsig"))
11200 confp->pri.switchtype = PRI_SWITCH_QSIG;
11201 else {
11202 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11203 return -1;
11205 } else if (!strcasecmp(v->name, "nsf")) {
11206 if (!strcasecmp(v->value, "sdn"))
11207 confp->pri.nsf = PRI_NSF_SDN;
11208 else if (!strcasecmp(v->value, "megacom"))
11209 confp->pri.nsf = PRI_NSF_MEGACOM;
11210 else if (!strcasecmp(v->value, "tollfreemegacom"))
11211 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11212 else if (!strcasecmp(v->value, "accunet"))
11213 confp->pri.nsf = PRI_NSF_ACCUNET;
11214 else if (!strcasecmp(v->value, "none"))
11215 confp->pri.nsf = PRI_NSF_NONE;
11216 else {
11217 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11218 confp->pri.nsf = PRI_NSF_NONE;
11220 } else if (!strcasecmp(v->name, "priindication")) {
11221 if (!strcasecmp(v->value, "outofband"))
11222 confp->chan.priindication_oob = 1;
11223 else if (!strcasecmp(v->value, "inband"))
11224 confp->chan.priindication_oob = 0;
11225 else
11226 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11227 v->value, v->lineno);
11228 } else if (!strcasecmp(v->name, "priexclusive")) {
11229 confp->chan.priexclusive = ast_true(v->value);
11230 } else if (!strcasecmp(v->name, "internationalprefix")) {
11231 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11232 } else if (!strcasecmp(v->name, "nationalprefix")) {
11233 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11234 } else if (!strcasecmp(v->name, "localprefix")) {
11235 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11236 } else if (!strcasecmp(v->name, "privateprefix")) {
11237 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11238 } else if (!strcasecmp(v->name, "unknownprefix")) {
11239 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11240 } else if (!strcasecmp(v->name, "resetinterval")) {
11241 if (!strcasecmp(v->value, "never"))
11242 confp->pri.resetinterval = -1;
11243 else if (atoi(v->value) >= 60)
11244 confp->pri.resetinterval = atoi(v->value);
11245 else
11246 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11247 v->value, v->lineno);
11248 } else if (!strcasecmp(v->name, "minunused")) {
11249 confp->pri.minunused = atoi(v->value);
11250 } else if (!strcasecmp(v->name, "minidle")) {
11251 confp->pri.minidle = atoi(v->value);
11252 } else if (!strcasecmp(v->name, "idleext")) {
11253 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11254 } else if (!strcasecmp(v->name, "idledial")) {
11255 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11256 } else if (!strcasecmp(v->name, "overlapdial")) {
11257 confp->pri.overlapdial = ast_true(v->value);
11258 #ifdef HAVE_PRI_INBANDDISCONNECT
11259 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11260 confp->pri.inbanddisconnect = ast_true(v->value);
11261 #endif
11262 } else if (!strcasecmp(v->name, "pritimer")) {
11263 #ifdef PRI_GETSET_TIMERS
11264 char *timerc, *c;
11265 int timer, timeridx;
11266 c = v->value;
11267 timerc = strsep(&c, ",");
11268 if (timerc) {
11269 timer = atoi(c);
11270 if (!timer)
11271 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11272 else {
11273 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11274 pritimers[timeridx] = timer;
11275 else
11276 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11278 } else
11279 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11281 } else if (!strcasecmp(v->name, "facilityenable")) {
11282 confp->pri.facilityenable = ast_true(v->value);
11283 #endif /* PRI_GETSET_TIMERS */
11284 #endif /* HAVE_PRI */
11285 } else if (!strcasecmp(v->name, "cadence")) {
11286 /* setup to scan our argument */
11287 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11288 int i;
11289 struct dahdi_ring_cadence new_cadence;
11290 int cid_location = -1;
11291 int firstcadencepos = 0;
11292 char original_args[80];
11293 int cadence_is_ok = 1;
11295 ast_copy_string(original_args, v->value, sizeof(original_args));
11296 /* 16 cadences allowed (8 pairs) */
11297 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]);
11299 /* Cadence must be even (on/off) */
11300 if (element_count % 2 == 1) {
11301 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11302 cadence_is_ok = 0;
11305 /* Ring cadences cannot be negative */
11306 for (i = 0; i < element_count; i++) {
11307 if (c[i] == 0) {
11308 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11309 cadence_is_ok = 0;
11310 break;
11311 } else if (c[i] < 0) {
11312 if (i % 2 == 1) {
11313 /* Silence duration, negative possibly okay */
11314 if (cid_location == -1) {
11315 cid_location = i;
11316 c[i] *= -1;
11317 } else {
11318 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11319 cadence_is_ok = 0;
11320 break;
11322 } else {
11323 if (firstcadencepos == 0) {
11324 firstcadencepos = i; /* only recorded to avoid duplicate specification */
11325 /* duration will be passed negative to the DAHDI driver */
11326 } else {
11327 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11328 cadence_is_ok = 0;
11329 break;
11335 /* Substitute our scanned cadence */
11336 for (i = 0; i < 16; i++) {
11337 new_cadence.ringcadence[i] = c[i];
11340 if (cadence_is_ok) {
11341 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11342 if (element_count < 2) {
11343 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11344 } else {
11345 if (cid_location == -1) {
11346 /* user didn't say; default to first pause */
11347 cid_location = 1;
11348 } else {
11349 /* convert element_index to cidrings value */
11350 cid_location = (cid_location + 1) / 2;
11352 /* ---we like their cadence; try to install it--- */
11353 if (!user_has_defined_cadences++)
11354 /* this is the first user-defined cadence; clear the default user cadences */
11355 num_cadence = 0;
11356 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11357 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11358 else {
11359 cadences[num_cadence] = new_cadence;
11360 cidrings[num_cadence++] = cid_location;
11361 if (option_verbose > 2)
11362 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11366 } else if (!strcasecmp(v->name, "ringtimeout")) {
11367 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11368 } else if (!strcasecmp(v->name, "prewink")) {
11369 confp->timing.prewinktime = atoi(v->value);
11370 } else if (!strcasecmp(v->name, "preflash")) {
11371 confp->timing.preflashtime = atoi(v->value);
11372 } else if (!strcasecmp(v->name, "wink")) {
11373 confp->timing.winktime = atoi(v->value);
11374 } else if (!strcasecmp(v->name, "flash")) {
11375 confp->timing.flashtime = atoi(v->value);
11376 } else if (!strcasecmp(v->name, "start")) {
11377 confp->timing.starttime = atoi(v->value);
11378 } else if (!strcasecmp(v->name, "rxwink")) {
11379 confp->timing.rxwinktime = atoi(v->value);
11380 } else if (!strcasecmp(v->name, "rxflash")) {
11381 confp->timing.rxflashtime = atoi(v->value);
11382 } else if (!strcasecmp(v->name, "debounce")) {
11383 confp->timing.debouncetime = atoi(v->value);
11384 } else if (!strcasecmp(v->name, "toneduration")) {
11385 int toneduration;
11386 int ctlfd;
11387 int res;
11388 DAHDI_DIAL_PARAMS dps;
11390 #ifdef HAVE_ZAPTEL
11391 ctlfd = open("/dev/zap/ctl", O_RDWR);
11392 #else
11393 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11394 #endif
11396 if (ctlfd == -1) {
11397 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11398 return -1;
11401 toneduration = atoi(v->value);
11402 if (toneduration > -1) {
11403 memset(&dps, 0, sizeof(dps));
11405 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11406 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11407 if (res < 0) {
11408 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11409 return -1;
11412 close(ctlfd);
11413 } else if (!strcasecmp(v->name, "defaultcic")) {
11414 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11415 } else if (!strcasecmp(v->name, "defaultozz")) {
11416 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11418 } else if (!skipchannels)
11419 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11421 if (dahdichan[0]) {
11422 /* The user has set 'dahdichan' */
11423 /*< \todo pass proper line number instead of 0 */
11424 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11425 return -1;
11428 /*< \todo why check for the pseudo in the per-channel section.
11429 * Any actual use for manual setup of the pseudo channel? */
11430 if (!found_pseudo && reload == 0) {
11431 /* Make sure pseudo isn't a member of any groups if
11432 we're automatically making it. */
11434 confp->chan.group = 0;
11435 confp->chan.callgroup = 0;
11436 confp->chan.pickupgroup = 0;
11438 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11440 if (tmp) {
11441 if (option_verbose > 2)
11442 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11443 } else {
11444 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11447 return 0;
11450 static int setup_dahdi(int reload)
11452 struct ast_config *cfg;
11453 struct ast_variable *v;
11454 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11455 int res;
11457 #ifdef HAVE_PRI
11458 char *c;
11459 int spanno;
11460 int i, x;
11461 int logicalspan;
11462 int trunkgroup;
11463 int dchannels[NUM_DCHANS];
11464 #endif
11466 #ifdef HAVE_ZAPTEL
11467 if (!(cfg = ast_config_load("zapata.conf"))) {
11468 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11469 return 0;
11471 #else
11472 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11473 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11474 return 0;
11476 #endif
11477 /* It's a little silly to lock it, but we mind as well just to be sure */
11478 ast_mutex_lock(&iflock);
11479 #ifdef HAVE_PRI
11480 if (!reload) {
11481 /* Process trunkgroups first */
11482 v = ast_variable_browse(cfg, "trunkgroups");
11483 while (v) {
11484 if (!strcasecmp(v->name, "trunkgroup")) {
11485 trunkgroup = atoi(v->value);
11486 if (trunkgroup > 0) {
11487 if ((c = strchr(v->value, ','))) {
11488 i = 0;
11489 memset(dchannels, 0, sizeof(dchannels));
11490 while (c && (i < NUM_DCHANS)) {
11491 dchannels[i] = atoi(c + 1);
11492 if (dchannels[i] < 0) {
11493 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);
11494 } else
11495 i++;
11496 c = strchr(c + 1, ',');
11498 if (i) {
11499 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11500 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);
11501 } else if (option_verbose > 1)
11502 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");
11503 } else
11504 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11505 } else
11506 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11507 } else
11508 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11509 } else if (!strcasecmp(v->name, "spanmap")) {
11510 spanno = atoi(v->value);
11511 if (spanno > 0) {
11512 if ((c = strchr(v->value, ','))) {
11513 trunkgroup = atoi(c + 1);
11514 if (trunkgroup > 0) {
11515 if ((c = strchr(c + 1, ',')))
11516 logicalspan = atoi(c + 1);
11517 else
11518 logicalspan = 0;
11519 if (logicalspan >= 0) {
11520 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11521 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11522 } else if (option_verbose > 1)
11523 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11524 } else
11525 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);
11526 } else
11527 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11528 } else
11529 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11530 } else
11531 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11532 } else {
11533 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11535 v = v->next;
11538 #endif
11540 /* Copy the default jb config over global_jbconf */
11541 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11543 v = ast_variable_browse(cfg, "channels");
11544 res = process_dahdi(&conf, "", v, reload, 0);
11545 ast_mutex_unlock(&iflock);
11546 ast_config_destroy(cfg);
11547 if (res)
11548 return res;
11549 cfg = ast_config_load("users.conf");
11550 if (cfg) {
11551 char *cat;
11552 const char *chans;
11553 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11554 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11555 if (!strcasecmp(cat, "general"))
11556 continue;
11557 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11558 if (!ast_strlen_zero(chans)) {
11559 struct dahdi_chan_conf sect_conf;
11560 memcpy(&sect_conf, &conf, sizeof(sect_conf));
11562 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11565 ast_config_destroy(cfg);
11567 #ifdef HAVE_PRI
11568 if (!reload) {
11569 for (x = 0; x < NUM_SPANS; x++) {
11570 if (pris[x].pvts[0]) {
11571 if (start_pri(pris + x)) {
11572 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11573 return -1;
11574 } else if (option_verbose > 1)
11575 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11579 #endif
11580 /* And start the monitor for the first time */
11581 restart_monitor();
11582 return 0;
11585 #define local_astman_register(a, b, c, d) do { \
11586 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11587 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11589 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11590 } while (0)
11592 static int load_module(void)
11594 int res;
11596 #ifdef HAVE_PRI
11597 int y,i;
11598 memset(pris, 0, sizeof(pris));
11599 for (y = 0; y < NUM_SPANS; y++) {
11600 ast_mutex_init(&pris[y].lock);
11601 pris[y].offset = -1;
11602 pris[y].master = AST_PTHREADT_NULL;
11603 for (i = 0; i < NUM_DCHANS; i++)
11604 pris[y].fds[i] = -1;
11606 pri_set_error(dahdi_pri_error);
11607 pri_set_message(dahdi_pri_message);
11608 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11609 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11610 #endif
11611 if ((res = setup_dahdi(0))) {
11612 return AST_MODULE_LOAD_DECLINE;
11614 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11615 chan_tech = &dahdi_tech;
11616 } else {
11617 chan_tech = &zap_tech;
11619 if (ast_channel_register(chan_tech)) {
11620 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11621 __unload_module();
11622 return -1;
11624 #ifdef HAVE_PRI
11625 ast_string_field_init(&inuse, 16);
11626 ast_string_field_set(&inuse, name, "GR-303InUse");
11627 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11628 #endif
11629 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11631 memset(round_robin, 0, sizeof(round_robin));
11632 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11633 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11634 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11635 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11636 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11637 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11638 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11640 return res;
11643 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11645 #define END_SILENCE_LEN 400
11646 #define HEADER_MS 50
11647 #define TRAILER_MS 5
11648 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11649 #define ASCII_BYTES_PER_CHAR 80
11651 unsigned char *buf,*mybuf;
11652 struct dahdi_pvt *p = c->tech_pvt;
11653 struct pollfd fds[1];
11654 int size,res,fd,len,x;
11655 int bytes=0;
11656 /* Initial carrier (imaginary) */
11657 float cr = 1.0;
11658 float ci = 0.0;
11659 float scont = 0.0;
11660 int index;
11662 index = dahdi_get_index(c, p, 0);
11663 if (index < 0) {
11664 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11665 return -1;
11667 if (!text[0]) return(0); /* if nothing to send, dont */
11668 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
11669 if (p->mate)
11670 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11671 else
11672 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11673 if (!buf)
11674 return -1;
11675 mybuf = buf;
11676 if (p->mate) {
11677 int codec = AST_LAW(p);
11678 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
11679 PUT_CLID_MARKMS;
11681 /* Put actual message */
11682 for (x = 0; text[x]; x++) {
11683 PUT_CLID(text[x]);
11685 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
11686 PUT_CLID_MARKMS;
11688 len = bytes;
11689 buf = mybuf;
11690 } else {
11691 len = tdd_generate(p->tdd, buf, text);
11692 if (len < 1) {
11693 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11694 free(mybuf);
11695 return -1;
11698 memset(buf + len, 0x7f, END_SILENCE_LEN);
11699 len += END_SILENCE_LEN;
11700 fd = p->subs[index].dfd;
11701 while (len) {
11702 if (ast_check_hangup(c)) {
11703 free(mybuf);
11704 return -1;
11706 size = len;
11707 if (size > READ_SIZE)
11708 size = READ_SIZE;
11709 fds[0].fd = fd;
11710 fds[0].events = POLLOUT | POLLPRI;
11711 fds[0].revents = 0;
11712 res = poll(fds, 1, -1);
11713 if (!res) {
11714 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11715 continue;
11717 /* if got exception */
11718 if (fds[0].revents & POLLPRI) {
11719 ast_free(mybuf);
11720 return -1;
11722 if (!(fds[0].revents & POLLOUT)) {
11723 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11724 continue;
11726 res = write(fd, buf, size);
11727 if (res != size) {
11728 if (res == -1) {
11729 free(mybuf);
11730 return -1;
11732 if (option_debug)
11733 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11734 break;
11736 len -= size;
11737 buf += size;
11739 free(mybuf);
11740 return(0);
11744 static int reload(void)
11746 int res = 0;
11748 res = setup_dahdi(1);
11749 if (res) {
11750 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
11751 return -1;
11753 return 0;
11756 /* This is a workaround so that menuselect displays a proper description
11757 * AST_MODULE_INFO(, , "DAHDI Telephony"
11760 #ifdef DAHDI_PRI
11761 #define tdesc "DAHDI Telephony w/PRI"
11762 #else
11763 #define tdesc "DAHDI Telephony"
11764 #endif
11766 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
11767 .load = load_module,
11768 .unload = unload_module,
11769 .reload = reload,