declared static mutexes using AST_MUTEX_DEFINE_STATIC macro
[asterisk-bristuff.git] / channels / chan_dahdi.c
blob58050a9e5978e3709aa62547aed0913ee1040464
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;
243 static ast_cond_t ss_thread_complete = PTHREAD_COND_INITIALIZER;
244 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
245 AST_MUTEX_DEFINE_STATIC(restart_lock);
246 static int ss_thread_count = 0;
247 static int num_restart_pending = 0;
249 static int restart_monitor(void);
251 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);
253 static int dahdi_sendtext(struct ast_channel *c, const char *text);
255 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
256 static inline int dahdi_get_event(int fd)
258 int j;
259 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
260 return -1;
261 return j;
264 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
265 static inline int dahdi_wait_event(int fd)
267 int i, j = 0;
268 i = DAHDI_IOMUX_SIGEVENT;
269 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
270 return -1;
271 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
272 return -1;
273 return j;
276 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
277 #define READ_SIZE 160
279 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
280 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
282 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
283 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
284 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
285 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
286 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
288 struct dahdi_pvt;
290 static int ringt_base = DEFAULT_RINGT;
292 #ifdef HAVE_PRI
294 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
295 #define PRI_CHANNEL(p) ((p) & 0xff)
296 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
297 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
299 struct dahdi_pri {
300 pthread_t master; /*!< Thread of master */
301 ast_mutex_t lock; /*!< Mutex */
302 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
303 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
304 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
305 int minunused; /*!< Min # of channels to keep empty */
306 int minidle; /*!< Min # of "idling" calls to keep active */
307 int nodetype; /*!< Node type */
308 int switchtype; /*!< Type of switch to emulate */
309 int nsf; /*!< Network-Specific Facilities */
310 int dialplan; /*!< Dialing plan */
311 int localdialplan; /*!< Local dialing plan */
312 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
313 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
314 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
315 char privateprefix[20]; /*!< for private dialplans */
316 char unknownprefix[20]; /*!< for unknown dialplans */
317 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
318 int trunkgroup; /*!< What our trunkgroup is */
319 int mastertrunkgroup; /*!< What trunk group is our master */
320 int prilogicalspan; /*!< Logical span number within trunk group */
321 int numchans; /*!< Num of channels we represent */
322 int overlapdial; /*!< In overlap dialing mode */
323 int facilityenable; /*!< Enable facility IEs */
324 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
325 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
326 struct pri *pri; /*!< Currently active D-channel */
327 int debug;
328 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
329 int offset;
330 int span;
331 int resetting;
332 int resetpos;
333 #ifdef HAVE_PRI_INBANDDISCONNECT
334 unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */
335 #endif
336 time_t lastreset; /*!< time when unused channels were last reset */
337 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
338 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
339 struct dahdi_pvt *crvs; /*!< Member CRV structs */
340 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
344 static struct dahdi_pri pris[NUM_SPANS];
346 #if 0
347 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
348 #else
349 #define DEFAULT_PRI_DEBUG 0
350 #endif
352 static inline void pri_rel(struct dahdi_pri *pri)
354 ast_mutex_unlock(&pri->lock);
357 #else
358 /*! Shut up the compiler */
359 struct dahdi_pri;
360 #endif
362 #define SUB_REAL 0 /*!< Active call */
363 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
364 #define SUB_THREEWAY 2 /*!< Three-way call */
366 /* Polarity states */
367 #define POLARITY_IDLE 0
368 #define POLARITY_REV 1
371 static struct dahdi_distRings drings;
373 struct distRingData {
374 int ring[3];
376 struct ringContextData {
377 char contextData[AST_MAX_CONTEXT];
379 struct dahdi_distRings {
380 struct distRingData ringnum[3];
381 struct ringContextData ringContext[3];
384 static char *subnames[] = {
385 "Real",
386 "Callwait",
387 "Threeway"
390 struct dahdi_subchannel {
391 int dfd;
392 struct ast_channel *owner;
393 int chan;
394 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
395 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
396 unsigned int needringing:1;
397 unsigned int needbusy:1;
398 unsigned int needcongestion:1;
399 unsigned int needcallerid:1;
400 unsigned int needanswer:1;
401 unsigned int needflash:1;
402 unsigned int needhold:1;
403 unsigned int needunhold:1;
404 unsigned int linear:1;
405 unsigned int inthreeway:1;
406 struct dahdi_confinfo curconf;
409 #define CONF_USER_REAL (1 << 0)
410 #define CONF_USER_THIRDCALL (1 << 1)
412 #define MAX_SLAVES 4
414 static struct dahdi_pvt {
415 ast_mutex_t lock;
416 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
417 /*!< Up to three channels can be associated with this call */
419 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
420 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
421 struct dahdi_confinfo saveconf; /*!< Saved conference info */
423 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
424 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
425 int inconference; /*!< If our real should be in the conference */
427 int sig; /*!< Signalling style */
428 int radio; /*!< radio type */
429 int outsigmod; /*!< Outbound Signalling style (modifier) */
430 int oprmode; /*!< "Operator Services" mode */
431 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
432 float rxgain;
433 float txgain;
434 int tonezone; /*!< tone zone for this chan, or -1 for default */
435 struct dahdi_pvt *next; /*!< Next channel in list */
436 struct dahdi_pvt *prev; /*!< Prev channel in list */
438 /* flags */
439 unsigned int adsi:1;
440 unsigned int answeronpolarityswitch:1;
441 unsigned int busydetect:1;
442 unsigned int callreturn:1;
443 unsigned int callwaiting:1;
444 unsigned int callwaitingcallerid:1;
445 unsigned int cancallforward:1;
446 unsigned int canpark:1;
447 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
448 unsigned int destroy:1;
449 unsigned int didtdd:1; /*!< flag to say its done it once */
450 unsigned int dialednone:1;
451 unsigned int dialing:1;
452 unsigned int digital:1;
453 unsigned int dnd:1;
454 unsigned int echobreak:1;
455 unsigned int echocanbridged:1;
456 unsigned int echocanon:1;
457 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
458 unsigned int firstradio:1;
459 unsigned int hanguponpolarityswitch:1;
460 unsigned int hardwaredtmf:1;
461 unsigned int hidecallerid:1;
462 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
463 unsigned int ignoredtmf:1;
464 unsigned int immediate:1; /*!< Answer before getting digits? */
465 unsigned int inalarm:1;
466 unsigned int unknown_alarm:1;
467 unsigned int mate:1; /*!< flag to say its in MATE mode */
468 unsigned int outgoing:1;
469 unsigned int overlapdial:1;
470 unsigned int permcallwaiting:1;
471 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
472 unsigned int priindication_oob:1;
473 unsigned int priexclusive:1;
474 unsigned int pulse:1;
475 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
476 unsigned int restartpending:1; /*!< flag to ensure counted only once for restart */
477 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
478 unsigned int threewaycalling:1;
479 unsigned int transfer:1;
480 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
481 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
482 unsigned int usedistinctiveringdetection:1;
483 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
484 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
485 #if defined(HAVE_PRI)
486 unsigned int alerting:1;
487 unsigned int alreadyhungup:1;
488 unsigned int isidlecall:1;
489 unsigned int proceeding:1;
490 unsigned int progress:1;
491 unsigned int resetting:1;
492 unsigned int setup_ack:1;
493 #endif
494 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
495 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
497 struct dahdi_distRings drings;
499 char context[AST_MAX_CONTEXT];
500 char defcontext[AST_MAX_CONTEXT];
501 char exten[AST_MAX_EXTENSION];
502 char language[MAX_LANGUAGE];
503 char mohinterpret[MAX_MUSICCLASS];
504 char mohsuggest[MAX_MUSICCLASS];
505 #ifdef PRI_ANI
506 char cid_ani[AST_MAX_EXTENSION];
507 #endif
508 char cid_num[AST_MAX_EXTENSION];
509 int cid_ton; /*!< Type Of Number (TON) */
510 char cid_name[AST_MAX_EXTENSION];
511 char lastcid_num[AST_MAX_EXTENSION];
512 char lastcid_name[AST_MAX_EXTENSION];
513 char *origcid_num; /*!< malloced original callerid */
514 char *origcid_name; /*!< malloced original callerid */
515 char callwait_num[AST_MAX_EXTENSION];
516 char callwait_name[AST_MAX_EXTENSION];
517 char rdnis[AST_MAX_EXTENSION];
518 char dnid[AST_MAX_EXTENSION];
519 ast_group_t group;
520 int law;
521 int confno; /*!< Our conference */
522 int confusers; /*!< Who is using our conference */
523 int propconfno; /*!< Propagated conference number */
524 ast_group_t callgroup;
525 ast_group_t pickupgroup;
526 int channel; /*!< Channel Number or CRV */
527 int span; /*!< Span number */
528 time_t guardtime; /*!< Must wait this much time before using for new call */
529 int cid_signalling; /*!< CID signalling type bell202 or v23 */
530 int cid_start; /*!< CID start indicator, polarity or ring */
531 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
532 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
533 int cidcwexpire; /*!< When to expire our muting for CID/CW */
534 unsigned char *cidspill;
535 int cidpos;
536 int cidlen;
537 int ringt;
538 int ringt_base;
539 int stripmsd;
540 int callwaitcas;
541 int callwaitrings;
542 int echocancel;
543 int echotraining;
544 char echorest[20];
545 int busycount;
546 int busy_tonelength;
547 int busy_quietlength;
548 int callprogress;
549 struct timeval flashtime; /*!< Last flash-hook time */
550 struct ast_dsp *dsp;
551 int cref; /*!< Call reference number */
552 struct dahdi_dialoperation dop;
553 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
554 char finaldial[64];
555 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
556 int amaflags; /*!< AMA Flags */
557 struct tdd_state *tdd; /*!< TDD flag */
558 char call_forward[AST_MAX_EXTENSION];
559 char mailbox[AST_MAX_EXTENSION];
560 char dialdest[256];
561 int onhooktime;
562 int msgstate;
563 int distinctivering; /*!< Which distinctivering to use */
564 int cidrings; /*!< Which ring to deliver CID on */
565 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
566 int fake_event;
567 int polarityonanswerdelay;
568 struct timeval polaritydelaytv;
569 int sendcalleridafter;
570 #ifdef HAVE_PRI
571 struct dahdi_pri *pri;
572 struct dahdi_pvt *bearer;
573 struct dahdi_pvt *realcall;
574 q931_call *call;
575 int prioffset;
576 int logicalspan;
577 #endif
578 int polarity;
579 int dsp_features;
580 char begindigit;
581 } *iflist = NULL, *ifend = NULL;
583 /*! \brief Channel configuration from chan_dahdi.conf .
584 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
585 * Generally there is a field here for every possible configuration item.
587 * The state of fields is saved along the parsing and whenever a 'channel'
588 * statement is reached, the current dahdi_chan_conf is used to configure the
589 * channel (struct dahdi_pvt)
591 * @seealso dahdi_chan_init for the default values.
593 struct dahdi_chan_conf {
594 struct dahdi_pvt chan;
595 #ifdef HAVE_PRI
596 struct dahdi_pri pri;
597 #endif
598 struct dahdi_params timing;
600 char smdi_port[SMDI_MAX_FILENAME_LEN];
603 /** returns a new dahdi_chan_conf with default values (by-value) */
604 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
605 /* recall that if a field is not included here it is initialized
606 * to 0 or equivalent
608 struct dahdi_chan_conf conf = {
609 #ifdef HAVE_PRI
610 .pri = {
611 .nsf = PRI_NSF_NONE,
612 .switchtype = PRI_SWITCH_NI2,
613 .dialplan = PRI_NATIONAL_ISDN + 1,
614 .localdialplan = PRI_NATIONAL_ISDN + 1,
615 .nodetype = PRI_CPE,
617 .minunused = 2,
618 .idleext = "",
619 .idledial = "",
620 .internationalprefix = "",
621 .nationalprefix = "",
622 .localprefix = "",
623 .privateprefix = "",
624 .unknownprefix = "",
626 .resetinterval = 3600
628 #endif
629 .chan = {
630 .context = "default",
631 .cid_num = "",
632 .cid_name = "",
633 .mohinterpret = "default",
634 .mohsuggest = "",
635 .transfertobusy = 1,
637 .cid_signalling = CID_SIG_BELL,
638 .cid_start = CID_START_RING,
639 .dahditrcallerid = 0,
640 .use_callerid = 1,
641 .sig = -1,
642 .outsigmod = -1,
644 .tonezone = -1,
646 .echocancel = 1,
648 .busycount = 3,
650 .accountcode = "",
652 .mailbox = "",
655 .polarityonanswerdelay = 600,
657 .sendcalleridafter = DEFAULT_CIDRINGS
659 .timing = {
660 .prewinktime = -1,
661 .preflashtime = -1,
662 .winktime = -1,
663 .flashtime = -1,
664 .starttime = -1,
665 .rxwinktime = -1,
666 .rxflashtime = -1,
667 .debouncetime = -1
669 .smdi_port = "/dev/ttyS0",
672 return conf;
676 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
677 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
678 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
679 static int dahdi_sendtext(struct ast_channel *c, const char *text);
680 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
681 static int dahdi_hangup(struct ast_channel *ast);
682 static int dahdi_answer(struct ast_channel *ast);
683 static struct ast_frame *dahdi_read(struct ast_channel *ast);
684 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
685 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
686 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
687 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
688 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
689 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
691 static const struct ast_channel_tech dahdi_tech = {
692 .type = "DAHDI",
693 .description = tdesc,
694 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
695 .requester = dahdi_request,
696 .send_digit_begin = dahdi_digit_begin,
697 .send_digit_end = dahdi_digit_end,
698 .send_text = dahdi_sendtext,
699 .call = dahdi_call,
700 .hangup = dahdi_hangup,
701 .answer = dahdi_answer,
702 .read = dahdi_read,
703 .write = dahdi_write,
704 .bridge = dahdi_bridge,
705 .exception = dahdi_exception,
706 .indicate = dahdi_indicate,
707 .fixup = dahdi_fixup,
708 .setoption = dahdi_setoption,
709 .func_channel_read = dahdi_func_read,
712 static const struct ast_channel_tech zap_tech = {
713 .type = "Zap",
714 .description = tdesc,
715 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
716 .requester = dahdi_request,
717 .send_digit_begin = dahdi_digit_begin,
718 .send_digit_end = dahdi_digit_end,
719 .send_text = dahdi_sendtext,
720 .call = dahdi_call,
721 .hangup = dahdi_hangup,
722 .answer = dahdi_answer,
723 .read = dahdi_read,
724 .write = dahdi_write,
725 .bridge = dahdi_bridge,
726 .exception = dahdi_exception,
727 .indicate = dahdi_indicate,
728 .fixup = dahdi_fixup,
729 .setoption = dahdi_setoption,
730 .func_channel_read = dahdi_func_read,
733 static const struct ast_channel_tech *chan_tech;
735 #ifdef HAVE_PRI
736 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
737 #else
738 #define GET_CHANNEL(p) ((p)->channel)
739 #endif
741 struct dahdi_pvt *round_robin[32];
743 #ifdef HAVE_PRI
744 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
746 int res;
747 /* Grab the lock first */
748 do {
749 res = ast_mutex_trylock(&pri->lock);
750 if (res) {
751 DEADLOCK_AVOIDANCE(&pvt->lock);
753 } while (res);
754 /* Then break the poll */
755 if (pri->master != AST_PTHREADT_NULL)
756 pthread_kill(pri->master, SIGURG);
757 return 0;
759 #endif
761 #define NUM_CADENCE_MAX 25
762 static int num_cadence = 4;
763 static int user_has_defined_cadences = 0;
765 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
766 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
767 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
768 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
769 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
772 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
773 * is 1, the second pause is 2 and so on.
776 static int cidrings[NUM_CADENCE_MAX] = {
777 2, /*!< Right after first long ring */
778 4, /*!< Right after long part */
779 3, /*!< After third chirp */
780 2, /*!< Second spell */
783 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
784 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
786 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
787 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
789 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
791 int res;
792 if (p->subs[SUB_REAL].owner == ast)
793 res = 0;
794 else if (p->subs[SUB_CALLWAIT].owner == ast)
795 res = 1;
796 else if (p->subs[SUB_THREEWAY].owner == ast)
797 res = 2;
798 else {
799 res = -1;
800 if (!nullok)
801 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
803 return res;
806 #ifdef HAVE_PRI
807 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
808 #else
809 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
810 #endif
812 #ifdef HAVE_PRI
813 if (pri)
814 ast_mutex_unlock(&pri->lock);
815 #endif
816 for (;;) {
817 if (p->subs[a].owner) {
818 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
819 DEADLOCK_AVOIDANCE(&p->lock);
820 } else {
821 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
822 ast_mutex_unlock(&p->subs[a].owner->lock);
823 break;
825 } else
826 break;
828 #ifdef HAVE_PRI
829 if (pri)
830 ast_mutex_lock(&pri->lock);
831 #endif
834 #ifdef HAVE_PRI
835 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
836 #else
837 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
838 #endif
840 /* We must unlock the PRI to avoid the possibility of a deadlock */
841 #ifdef HAVE_PRI
842 if (pri)
843 ast_mutex_unlock(&pri->lock);
844 #endif
845 for (;;) {
846 if (p->owner) {
847 if (ast_mutex_trylock(&p->owner->lock)) {
848 DEADLOCK_AVOIDANCE(&p->lock);
849 } else {
850 ast_queue_frame(p->owner, f);
851 ast_mutex_unlock(&p->owner->lock);
852 break;
854 } else
855 break;
857 #ifdef HAVE_PRI
858 if (pri)
859 ast_mutex_lock(&pri->lock);
860 #endif
863 static int restore_gains(struct dahdi_pvt *p);
865 static void swap_subs(struct dahdi_pvt *p, int a, int b)
867 int tchan;
868 int tinthreeway;
869 struct ast_channel *towner;
871 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
873 tchan = p->subs[a].chan;
874 towner = p->subs[a].owner;
875 tinthreeway = p->subs[a].inthreeway;
877 p->subs[a].chan = p->subs[b].chan;
878 p->subs[a].owner = p->subs[b].owner;
879 p->subs[a].inthreeway = p->subs[b].inthreeway;
881 p->subs[b].chan = tchan;
882 p->subs[b].owner = towner;
883 p->subs[b].inthreeway = tinthreeway;
885 if (p->subs[a].owner)
886 p->subs[a].owner->fds[0] = p->subs[a].dfd;
887 if (p->subs[b].owner)
888 p->subs[b].owner->fds[0] = p->subs[b].dfd;
889 wakeup_sub(p, a, NULL);
890 wakeup_sub(p, b, NULL);
893 static int dahdi_open(char *fn)
895 int fd;
896 int isnum;
897 int chan = 0;
898 int bs;
899 int x;
900 isnum = 1;
901 for (x = 0; x < strlen(fn); x++) {
902 if (!isdigit(fn[x])) {
903 isnum = 0;
904 break;
907 if (isnum) {
908 chan = atoi(fn);
909 if (chan < 1) {
910 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
911 return -1;
913 #ifdef HAVE_ZAPTEL
914 fn = "/dev/zap/channel";
915 #else
916 fn = "/dev/dahdi/channel";
917 #endif
919 fd = open(fn, O_RDWR | O_NONBLOCK);
920 if (fd < 0) {
921 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
922 return -1;
924 if (chan) {
925 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
926 x = errno;
927 close(fd);
928 errno = x;
929 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
930 return -1;
933 bs = READ_SIZE;
934 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
935 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
936 x = errno;
937 close(fd);
938 errno = x;
939 return -1;
941 return fd;
944 static void dahdi_close(int fd)
946 if (fd > 0)
947 close(fd);
950 static int dahdi_setlinear(int dfd, int linear)
952 int res;
953 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
954 if (res)
955 return res;
956 return 0;
960 static int alloc_sub(struct dahdi_pvt *p, int x)
962 struct dahdi_bufferinfo bi;
963 int res;
964 if (p->subs[x].dfd < 0) {
965 #ifdef HAVE_ZAPTEL
966 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
967 #else
968 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
969 #endif
970 if (p->subs[x].dfd > -1) {
971 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
972 if (!res) {
973 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
974 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
975 bi.numbufs = numbufs;
976 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
977 if (res < 0) {
978 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
980 } else
981 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
982 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
983 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
984 dahdi_close(p->subs[x].dfd);
985 p->subs[x].dfd = -1;
986 return -1;
988 if (option_debug)
989 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
990 return 0;
991 } else
992 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
993 return -1;
995 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
996 return -1;
999 static int unalloc_sub(struct dahdi_pvt *p, int x)
1001 if (!x) {
1002 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
1003 return -1;
1005 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
1006 if (p->subs[x].dfd > -1) {
1007 dahdi_close(p->subs[x].dfd);
1009 p->subs[x].dfd = -1;
1010 p->subs[x].linear = 0;
1011 p->subs[x].chan = 0;
1012 p->subs[x].owner = NULL;
1013 p->subs[x].inthreeway = 0;
1014 p->polarity = POLARITY_IDLE;
1015 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
1016 return 0;
1019 static int digit_to_dtmfindex(char digit)
1021 if (isdigit(digit))
1022 return DAHDI_TONE_DTMF_BASE + (digit - '0');
1023 else if (digit >= 'A' && digit <= 'D')
1024 return DAHDI_TONE_DTMF_A + (digit - 'A');
1025 else if (digit >= 'a' && digit <= 'd')
1026 return DAHDI_TONE_DTMF_A + (digit - 'a');
1027 else if (digit == '*')
1028 return DAHDI_TONE_DTMF_s;
1029 else if (digit == '#')
1030 return DAHDI_TONE_DTMF_p;
1031 else
1032 return -1;
1035 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1037 struct dahdi_pvt *pvt;
1038 int index;
1039 int dtmf = -1;
1041 pvt = chan->tech_pvt;
1043 ast_mutex_lock(&pvt->lock);
1045 index = dahdi_get_index(chan, pvt, 0);
1047 if ((index != SUB_REAL) || !pvt->owner)
1048 goto out;
1050 #ifdef HAVE_PRI
1051 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1052 if (pvt->setup_ack) {
1053 if (!pri_grab(pvt, pvt->pri)) {
1054 pri_information(pvt->pri->pri, pvt->call, digit);
1055 pri_rel(pvt->pri);
1056 } else
1057 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1058 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1059 int res;
1060 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1061 res = strlen(pvt->dialdest);
1062 pvt->dialdest[res++] = digit;
1063 pvt->dialdest[res] = '\0';
1065 goto out;
1067 #endif
1068 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1069 goto out;
1071 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1072 int res;
1073 struct dahdi_dialoperation zo = {
1074 .op = DAHDI_DIAL_OP_APPEND,
1075 .dialstr[0] = 'T',
1076 .dialstr[1] = digit,
1077 .dialstr[2] = 0,
1079 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1080 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1081 else
1082 pvt->dialing = 1;
1083 } else {
1084 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1085 pvt->dialing = 1;
1086 pvt->begindigit = digit;
1089 out:
1090 ast_mutex_unlock(&pvt->lock);
1092 return 0;
1095 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1097 struct dahdi_pvt *pvt;
1098 int res = 0;
1099 int index;
1100 int x;
1102 pvt = chan->tech_pvt;
1104 ast_mutex_lock(&pvt->lock);
1106 index = dahdi_get_index(chan, pvt, 0);
1108 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1109 goto out;
1111 #ifdef HAVE_PRI
1112 /* This means that the digit was already sent via PRI signalling */
1113 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1114 goto out;
1115 #endif
1117 if (pvt->begindigit) {
1118 x = -1;
1119 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1120 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1121 pvt->dialing = 0;
1122 pvt->begindigit = 0;
1125 out:
1126 ast_mutex_unlock(&pvt->lock);
1128 return res;
1131 static char *events[] = {
1132 "No event",
1133 "On hook",
1134 "Ring/Answered",
1135 "Wink/Flash",
1136 "Alarm",
1137 "No more alarm",
1138 "HDLC Abort",
1139 "HDLC Overrun",
1140 "HDLC Bad FCS",
1141 "Dial Complete",
1142 "Ringer On",
1143 "Ringer Off",
1144 "Hook Transition Complete",
1145 "Bits Changed",
1146 "Pulse Start",
1147 "Timer Expired",
1148 "Timer Ping",
1149 "Polarity Reversal",
1150 "Ring Begin",
1153 static struct {
1154 int alarm;
1155 char *name;
1156 } alarms[] = {
1157 { DAHDI_ALARM_RED, "Red Alarm" },
1158 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1159 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1160 { DAHDI_ALARM_RECOVER, "Recovering" },
1161 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1162 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1163 { DAHDI_ALARM_NONE, "None" },
1166 static char *alarm2str(int alarm)
1168 int x;
1169 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1170 if (alarms[x].alarm & alarm)
1171 return alarms[x].name;
1173 return alarm ? "Unknown Alarm" : "No Alarm";
1176 static char *event2str(int event)
1178 static char buf[256];
1179 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1180 return events[event];
1181 sprintf(buf, "Event %d", event); /* safe */
1182 return buf;
1185 #ifdef HAVE_PRI
1186 static char *dialplan2str(int dialplan)
1188 if (dialplan == -1) {
1189 return("Dynamically set dialplan in ISDN");
1191 return (pri_plan2str(dialplan));
1193 #endif
1195 static char *dahdi_sig2str(int sig)
1197 static char buf[256];
1198 switch (sig) {
1199 case SIG_EM:
1200 return "E & M Immediate";
1201 case SIG_EMWINK:
1202 return "E & M Wink";
1203 case SIG_EM_E1:
1204 return "E & M E1";
1205 case SIG_FEATD:
1206 return "Feature Group D (DTMF)";
1207 case SIG_FEATDMF:
1208 return "Feature Group D (MF)";
1209 case SIG_FEATDMF_TA:
1210 return "Feature Groud D (MF) Tandem Access";
1211 case SIG_FEATB:
1212 return "Feature Group B (MF)";
1213 case SIG_E911:
1214 return "E911 (MF)";
1215 case SIG_FGC_CAMA:
1216 return "FGC/CAMA (Dialpulse)";
1217 case SIG_FGC_CAMAMF:
1218 return "FGC/CAMA (MF)";
1219 case SIG_FXSLS:
1220 return "FXS Loopstart";
1221 case SIG_FXSGS:
1222 return "FXS Groundstart";
1223 case SIG_FXSKS:
1224 return "FXS Kewlstart";
1225 case SIG_FXOLS:
1226 return "FXO Loopstart";
1227 case SIG_FXOGS:
1228 return "FXO Groundstart";
1229 case SIG_FXOKS:
1230 return "FXO Kewlstart";
1231 case SIG_PRI:
1232 return "ISDN PRI";
1233 case SIG_SF:
1234 return "SF (Tone) Immediate";
1235 case SIG_SFWINK:
1236 return "SF (Tone) Wink";
1237 case SIG_SF_FEATD:
1238 return "SF (Tone) with Feature Group D (DTMF)";
1239 case SIG_SF_FEATDMF:
1240 return "SF (Tone) with Feature Group D (MF)";
1241 case SIG_SF_FEATB:
1242 return "SF (Tone) with Feature Group B (MF)";
1243 case SIG_GR303FXOKS:
1244 return "GR-303 with FXOKS";
1245 case SIG_GR303FXSKS:
1246 return "GR-303 with FXSKS";
1247 case 0:
1248 return "Pseudo";
1249 default:
1250 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1251 return buf;
1255 #define sig2str dahdi_sig2str
1257 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1259 /* If the conference already exists, and we're already in it
1260 don't bother doing anything */
1261 struct dahdi_confinfo zi;
1263 memset(&zi, 0, sizeof(zi));
1264 zi.chan = 0;
1266 if (slavechannel > 0) {
1267 /* If we have only one slave, do a digital mon */
1268 zi.confmode = DAHDI_CONF_DIGITALMON;
1269 zi.confno = slavechannel;
1270 } else {
1271 if (!index) {
1272 /* Real-side and pseudo-side both participate in conference */
1273 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1274 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1275 } else
1276 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1277 zi.confno = p->confno;
1279 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1280 return 0;
1281 if (c->dfd < 0)
1282 return 0;
1283 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1284 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1285 return -1;
1287 if (slavechannel < 1) {
1288 p->confno = zi.confno;
1290 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1291 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1292 return 0;
1295 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1297 /* If they're listening to our channel, they're ours */
1298 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1299 return 1;
1300 /* If they're a talker on our (allocated) conference, they're ours */
1301 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1302 return 1;
1303 return 0;
1306 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1308 struct dahdi_confinfo zi;
1309 if (/* Can't delete if there's no dfd */
1310 (c->dfd < 0) ||
1311 /* Don't delete from the conference if it's not our conference */
1312 !isourconf(p, c)
1313 /* Don't delete if we don't think it's conferenced at all (implied) */
1314 ) return 0;
1315 memset(&zi, 0, sizeof(zi));
1316 zi.chan = 0;
1317 zi.confno = 0;
1318 zi.confmode = 0;
1319 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1320 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1321 return -1;
1323 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1324 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1325 return 0;
1328 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1330 int x;
1331 int useslavenative;
1332 struct dahdi_pvt *slave = NULL;
1333 /* Start out optimistic */
1334 useslavenative = 1;
1335 /* Update conference state in a stateless fashion */
1336 for (x = 0; x < 3; x++) {
1337 /* Any three-way calling makes slave native mode *definitely* out
1338 of the question */
1339 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1340 useslavenative = 0;
1342 /* If we don't have any 3-way calls, check to see if we have
1343 precisely one slave */
1344 if (useslavenative) {
1345 for (x = 0; x < MAX_SLAVES; x++) {
1346 if (p->slaves[x]) {
1347 if (slave) {
1348 /* Whoops already have a slave! No
1349 slave native and stop right away */
1350 slave = NULL;
1351 useslavenative = 0;
1352 break;
1353 } else {
1354 /* We have one slave so far */
1355 slave = p->slaves[x];
1360 /* If no slave, slave native definitely out */
1361 if (!slave)
1362 useslavenative = 0;
1363 else if (slave->law != p->law) {
1364 useslavenative = 0;
1365 slave = NULL;
1367 if (out)
1368 *out = slave;
1369 return useslavenative;
1372 static int reset_conf(struct dahdi_pvt *p)
1374 struct dahdi_confinfo zi;
1375 memset(&zi, 0, sizeof(zi));
1376 p->confno = -1;
1377 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1378 if (p->subs[SUB_REAL].dfd > -1) {
1379 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1380 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1382 return 0;
1385 static int update_conf(struct dahdi_pvt *p)
1387 int needconf = 0;
1388 int x;
1389 int useslavenative;
1390 struct dahdi_pvt *slave = NULL;
1392 useslavenative = isslavenative(p, &slave);
1393 /* Start with the obvious, general stuff */
1394 for (x = 0; x < 3; x++) {
1395 /* Look for three way calls */
1396 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1397 conf_add(p, &p->subs[x], x, 0);
1398 needconf++;
1399 } else {
1400 conf_del(p, &p->subs[x], x);
1403 /* If we have a slave, add him to our conference now. or DAX
1404 if this is slave native */
1405 for (x = 0; x < MAX_SLAVES; x++) {
1406 if (p->slaves[x]) {
1407 if (useslavenative)
1408 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1409 else {
1410 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1411 needconf++;
1415 /* If we're supposed to be in there, do so now */
1416 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1417 if (useslavenative)
1418 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1419 else {
1420 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1421 needconf++;
1424 /* If we have a master, add ourselves to his conference */
1425 if (p->master) {
1426 if (isslavenative(p->master, NULL)) {
1427 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1428 } else {
1429 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1432 if (!needconf) {
1433 /* Nobody is left (or should be left) in our conference.
1434 Kill it. */
1435 p->confno = -1;
1437 if (option_debug)
1438 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1439 return 0;
1442 static void dahdi_enable_ec(struct dahdi_pvt *p)
1444 int x;
1445 int res;
1446 if (!p)
1447 return;
1448 if (p->echocanon) {
1449 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1450 return;
1452 if (p->digital) {
1453 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
1454 return;
1456 if (p->echocancel) {
1457 if (p->sig == SIG_PRI) {
1458 x = 1;
1459 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1460 if (res)
1461 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1463 x = p->echocancel;
1464 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1465 if (res)
1466 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1467 else {
1468 p->echocanon = 1;
1469 if (option_debug)
1470 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1472 } else if (option_debug)
1473 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1476 static void dahdi_train_ec(struct dahdi_pvt *p)
1478 int x;
1479 int res;
1480 if (p && p->echocancel && p->echotraining) {
1481 x = p->echotraining;
1482 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1483 if (res)
1484 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1485 else {
1486 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1488 } else
1489 ast_log(LOG_DEBUG, "No echo training requested\n");
1492 static void dahdi_disable_ec(struct dahdi_pvt *p)
1494 int x;
1495 int res;
1496 if (p->echocancel) {
1497 x = 0;
1498 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1499 if (res)
1500 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1501 else if (option_debug)
1502 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1504 p->echocanon = 0;
1507 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
1509 int j;
1510 int k;
1511 float linear_gain = pow(10.0, gain / 20.0);
1513 switch (law) {
1514 case DAHDI_LAW_ALAW:
1515 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1516 if (gain) {
1517 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1518 if (k > 32767) k = 32767;
1519 if (k < -32767) k = -32767;
1520 g->txgain[j] = AST_LIN2A(k);
1521 } else {
1522 g->txgain[j] = j;
1525 break;
1526 case DAHDI_LAW_MULAW:
1527 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1528 if (gain) {
1529 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1530 if (k > 32767) k = 32767;
1531 if (k < -32767) k = -32767;
1532 g->txgain[j] = AST_LIN2MU(k);
1533 } else {
1534 g->txgain[j] = j;
1537 break;
1541 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
1543 int j;
1544 int k;
1545 float linear_gain = pow(10.0, gain / 20.0);
1547 switch (law) {
1548 case DAHDI_LAW_ALAW:
1549 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1550 if (gain) {
1551 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1552 if (k > 32767) k = 32767;
1553 if (k < -32767) k = -32767;
1554 g->rxgain[j] = AST_LIN2A(k);
1555 } else {
1556 g->rxgain[j] = j;
1559 break;
1560 case DAHDI_LAW_MULAW:
1561 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1562 if (gain) {
1563 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1564 if (k > 32767) k = 32767;
1565 if (k < -32767) k = -32767;
1566 g->rxgain[j] = AST_LIN2MU(k);
1567 } else {
1568 g->rxgain[j] = j;
1571 break;
1575 static int set_actual_txgain(int fd, int chan, float gain, int law)
1577 struct dahdi_gains g;
1578 int res;
1580 memset(&g, 0, sizeof(g));
1581 g.chan = chan;
1582 res = ioctl(fd, DAHDI_GETGAINS, &g);
1583 if (res) {
1584 if (option_debug)
1585 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1586 return res;
1589 fill_txgain(&g, gain, law);
1591 return ioctl(fd, DAHDI_SETGAINS, &g);
1594 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1596 struct dahdi_gains g;
1597 int res;
1599 memset(&g, 0, sizeof(g));
1600 g.chan = chan;
1601 res = ioctl(fd, DAHDI_GETGAINS, &g);
1602 if (res) {
1603 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1604 return res;
1607 fill_rxgain(&g, gain, law);
1609 return ioctl(fd, DAHDI_SETGAINS, &g);
1612 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1614 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1617 static int bump_gains(struct dahdi_pvt *p)
1619 int res;
1621 /* Bump receive gain by 5.0db */
1622 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1623 if (res) {
1624 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1625 return -1;
1628 return 0;
1631 static int restore_gains(struct dahdi_pvt *p)
1633 int res;
1635 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1636 if (res) {
1637 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1638 return -1;
1641 return 0;
1644 static inline int dahdi_set_hook(int fd, int hs)
1646 int x, res;
1648 x = hs;
1649 res = ioctl(fd, DAHDI_HOOK, &x);
1651 if (res < 0) {
1652 if (errno == EINPROGRESS)
1653 return 0;
1654 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
1655 /* will expectedly fail if phone is off hook during operation, such as during a restart */
1658 return res;
1661 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1663 int x, y, res;
1664 x = muted;
1665 if (p->sig == SIG_PRI) {
1666 y = 1;
1667 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1668 if (res)
1669 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1671 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1672 if (res < 0)
1673 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1674 return res;
1677 static int save_conference(struct dahdi_pvt *p)
1679 struct dahdi_confinfo c;
1680 int res;
1681 if (p->saveconf.confmode) {
1682 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1683 return -1;
1685 p->saveconf.chan = 0;
1686 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1687 if (res) {
1688 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1689 p->saveconf.confmode = 0;
1690 return -1;
1692 c.chan = 0;
1693 c.confno = 0;
1694 c.confmode = DAHDI_CONF_NORMAL;
1695 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1696 if (res) {
1697 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1698 return -1;
1700 if (option_debug)
1701 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1702 return 0;
1705 static int restore_conference(struct dahdi_pvt *p)
1707 int res;
1708 if (p->saveconf.confmode) {
1709 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1710 p->saveconf.confmode = 0;
1711 if (res) {
1712 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1713 return -1;
1716 if (option_debug)
1717 ast_log(LOG_DEBUG, "Restored conferencing\n");
1718 return 0;
1721 static int send_callerid(struct dahdi_pvt *p);
1723 static int send_cwcidspill(struct dahdi_pvt *p)
1725 p->callwaitcas = 0;
1726 p->cidcwexpire = 0;
1727 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1728 return -1;
1729 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1730 /* Make sure we account for the end */
1731 p->cidlen += READ_SIZE * 4;
1732 p->cidpos = 0;
1733 send_callerid(p);
1734 if (option_verbose > 2)
1735 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1736 return 0;
1739 static int has_voicemail(struct dahdi_pvt *p)
1742 return ast_app_has_voicemail(p->mailbox, NULL);
1745 static int send_callerid(struct dahdi_pvt *p)
1747 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1748 int res;
1749 /* Take out of linear mode if necessary */
1750 if (p->subs[SUB_REAL].linear) {
1751 p->subs[SUB_REAL].linear = 0;
1752 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1754 while (p->cidpos < p->cidlen) {
1755 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1756 if (res < 0) {
1757 if (errno == EAGAIN)
1758 return 0;
1759 else {
1760 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1761 return -1;
1764 if (!res)
1765 return 0;
1766 p->cidpos += res;
1768 free(p->cidspill);
1769 p->cidspill = NULL;
1770 if (p->callwaitcas) {
1771 /* Wait for CID/CW to expire */
1772 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1773 } else
1774 restore_conference(p);
1775 return 0;
1778 static int dahdi_callwait(struct ast_channel *ast)
1780 struct dahdi_pvt *p = ast->tech_pvt;
1781 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1782 if (p->cidspill) {
1783 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1784 free(p->cidspill);
1786 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1787 return -1;
1788 save_conference(p);
1789 /* Silence */
1790 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1791 if (!p->callwaitrings && p->callwaitingcallerid) {
1792 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1793 p->callwaitcas = 1;
1794 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1795 } else {
1796 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1797 p->callwaitcas = 0;
1798 p->cidlen = 2400 + READ_SIZE * 4;
1800 p->cidpos = 0;
1801 send_callerid(p);
1803 return 0;
1806 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1808 struct dahdi_pvt *p = ast->tech_pvt;
1809 int x, res, index,mysig;
1810 char *c, *n, *l;
1811 #ifdef HAVE_PRI
1812 char *s = NULL;
1813 #endif
1814 char dest[256]; /* must be same length as p->dialdest */
1815 ast_mutex_lock(&p->lock);
1816 ast_copy_string(dest, rdest, sizeof(dest));
1817 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1818 if ((ast->_state == AST_STATE_BUSY)) {
1819 p->subs[SUB_REAL].needbusy = 1;
1820 ast_mutex_unlock(&p->lock);
1821 return 0;
1823 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1824 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1825 ast_mutex_unlock(&p->lock);
1826 return -1;
1828 p->dialednone = 0;
1829 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1831 /* Special pseudo -- automatically up */
1832 ast_setstate(ast, AST_STATE_UP);
1833 ast_mutex_unlock(&p->lock);
1834 return 0;
1836 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1837 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1838 if (res)
1839 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1840 p->outgoing = 1;
1842 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1844 mysig = p->sig;
1845 if (p->outsigmod > -1)
1846 mysig = p->outsigmod;
1848 switch (mysig) {
1849 case SIG_FXOLS:
1850 case SIG_FXOGS:
1851 case SIG_FXOKS:
1852 if (p->owner == ast) {
1853 /* Normal ring, on hook */
1855 /* Don't send audio while on hook, until the call is answered */
1856 p->dialing = 1;
1857 if (p->use_callerid) {
1858 /* Generate the Caller-ID spill if desired */
1859 if (p->cidspill) {
1860 ast_log(LOG_WARNING, "cidspill already exists??\n");
1861 free(p->cidspill);
1863 p->callwaitcas = 0;
1864 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1865 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1866 p->cidpos = 0;
1867 send_callerid(p);
1870 /* Choose proper cadence */
1871 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1872 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1873 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1874 p->cidrings = cidrings[p->distinctivering - 1];
1875 } else {
1876 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1877 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1878 p->cidrings = p->sendcalleridafter;
1881 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1882 c = strchr(dest, '/');
1883 if (c)
1884 c++;
1885 if (c && (strlen(c) < p->stripmsd)) {
1886 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1887 c = NULL;
1889 if (c) {
1890 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1891 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
1892 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
1893 } else {
1894 p->dop.dialstr[0] = '\0';
1896 x = DAHDI_RING;
1897 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
1898 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
1899 ast_mutex_unlock(&p->lock);
1900 return -1;
1902 p->dialing = 1;
1903 } else {
1904 /* Call waiting call */
1905 p->callwaitrings = 0;
1906 if (ast->cid.cid_num)
1907 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
1908 else
1909 p->callwait_num[0] = '\0';
1910 if (ast->cid.cid_name)
1911 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
1912 else
1913 p->callwait_name[0] = '\0';
1914 /* Call waiting tone instead */
1915 if (dahdi_callwait(ast)) {
1916 ast_mutex_unlock(&p->lock);
1917 return -1;
1919 /* Make ring-back */
1920 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
1921 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
1924 n = ast->cid.cid_name;
1925 l = ast->cid.cid_num;
1926 if (l)
1927 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
1928 else
1929 p->lastcid_num[0] = '\0';
1930 if (n)
1931 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
1932 else
1933 p->lastcid_name[0] = '\0';
1934 ast_setstate(ast, AST_STATE_RINGING);
1935 index = dahdi_get_index(ast, p, 0);
1936 if (index > -1) {
1937 p->subs[index].needringing = 1;
1939 break;
1940 case SIG_FXSLS:
1941 case SIG_FXSGS:
1942 case SIG_FXSKS:
1943 case SIG_EMWINK:
1944 case SIG_EM:
1945 case SIG_EM_E1:
1946 case SIG_FEATD:
1947 case SIG_FEATDMF:
1948 case SIG_E911:
1949 case SIG_FGC_CAMA:
1950 case SIG_FGC_CAMAMF:
1951 case SIG_FEATB:
1952 case SIG_SFWINK:
1953 case SIG_SF:
1954 case SIG_SF_FEATD:
1955 case SIG_SF_FEATDMF:
1956 case SIG_FEATDMF_TA:
1957 case SIG_SF_FEATB:
1958 c = strchr(dest, '/');
1959 if (c)
1960 c++;
1961 else
1962 c = "";
1963 if (strlen(c) < p->stripmsd) {
1964 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1965 ast_mutex_unlock(&p->lock);
1966 return -1;
1968 #ifdef HAVE_PRI
1969 /* Start the trunk, if not GR-303 */
1970 if (!p->pri) {
1971 #endif
1972 x = DAHDI_START;
1973 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
1974 if (res < 0) {
1975 if (errno != EINPROGRESS) {
1976 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
1977 ast_mutex_unlock(&p->lock);
1978 return -1;
1981 #ifdef HAVE_PRI
1983 #endif
1984 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
1985 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1987 c += p->stripmsd;
1989 switch (mysig) {
1990 case SIG_FEATD:
1991 l = ast->cid.cid_num;
1992 if (l)
1993 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
1994 else
1995 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
1996 break;
1997 case SIG_FEATDMF:
1998 l = ast->cid.cid_num;
1999 if (l)
2000 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
2001 else
2002 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
2003 break;
2004 case SIG_FEATDMF_TA:
2006 const char *cic, *ozz;
2008 /* If you have to go through a Tandem Access point you need to use this */
2009 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
2010 if (!ozz)
2011 ozz = defaultozz;
2012 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
2013 if (!cic)
2014 cic = defaultcic;
2015 if (!ozz || !cic) {
2016 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2017 ast_mutex_unlock(&p->lock);
2018 return -1;
2020 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
2021 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
2022 p->whichwink = 0;
2024 break;
2025 case SIG_E911:
2026 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2027 break;
2028 case SIG_FGC_CAMA:
2029 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2030 break;
2031 case SIG_FGC_CAMAMF:
2032 case SIG_FEATB:
2033 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2034 break;
2035 default:
2036 if (p->pulse)
2037 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2038 else
2039 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2040 break;
2043 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2044 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2045 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2046 p->echorest[sizeof(p->echorest) - 1] = '\0';
2047 p->echobreak = 1;
2048 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2049 } else
2050 p->echobreak = 0;
2051 if (!res) {
2052 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2053 int saveerr = errno;
2055 x = DAHDI_ONHOOK;
2056 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2057 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2058 ast_mutex_unlock(&p->lock);
2059 return -1;
2061 } else
2062 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2063 p->dialing = 1;
2064 if (ast_strlen_zero(c))
2065 p->dialednone = 1;
2066 ast_setstate(ast, AST_STATE_DIALING);
2067 break;
2068 case 0:
2069 /* Special pseudo -- automatically up*/
2070 ast_setstate(ast, AST_STATE_UP);
2071 break;
2072 case SIG_PRI:
2073 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2074 p->dialdest[0] = '\0';
2075 break;
2076 default:
2077 ast_log(LOG_DEBUG, "not yet implemented\n");
2078 ast_mutex_unlock(&p->lock);
2079 return -1;
2081 #ifdef HAVE_PRI
2082 if (p->pri) {
2083 struct pri_sr *sr;
2084 #ifdef SUPPORT_USERUSER
2085 const char *useruser;
2086 #endif
2087 int pridialplan;
2088 int dp_strip;
2089 int prilocaldialplan;
2090 int ldp_strip;
2091 int exclusive;
2092 const char *rr_str;
2093 int redirect_reason;
2095 c = strchr(dest, '/');
2096 if (c)
2097 c++;
2098 else
2099 c = dest;
2101 l = NULL;
2102 n = NULL;
2104 if (!p->hidecallerid) {
2105 l = ast->cid.cid_num;
2106 if (!p->hidecalleridname) {
2107 n = ast->cid.cid_name;
2112 if (strlen(c) < p->stripmsd) {
2113 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2114 ast_mutex_unlock(&p->lock);
2115 return -1;
2117 if (mysig != SIG_FXSKS) {
2118 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2119 s = strchr(c + p->stripmsd, 'w');
2120 if (s) {
2121 if (strlen(s) > 1)
2122 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2123 else
2124 p->dop.dialstr[0] = '\0';
2125 *s = '\0';
2126 } else {
2127 p->dop.dialstr[0] = '\0';
2130 if (pri_grab(p, p->pri)) {
2131 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2132 ast_mutex_unlock(&p->lock);
2133 return -1;
2135 if (!(p->call = pri_new_call(p->pri->pri))) {
2136 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2137 pri_rel(p->pri);
2138 ast_mutex_unlock(&p->lock);
2139 return -1;
2141 if (!(sr = pri_sr_new())) {
2142 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2143 pri_destroycall(p->pri->pri, p->call);
2144 p->call = NULL;
2145 pri_rel(p->pri);
2146 ast_mutex_unlock(&p->lock);
2147 return -1;
2149 if (p->bearer || (mysig == SIG_FXSKS)) {
2150 if (p->bearer) {
2151 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);
2152 p->bearer->call = p->call;
2153 } else
2154 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2155 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2157 p->digital = IS_DIGITAL(ast->transfercapability);
2158 /* Add support for exclusive override */
2159 if (p->priexclusive)
2160 exclusive = 1;
2161 else {
2162 /* otherwise, traditional behavior */
2163 if (p->pri->nodetype == PRI_NETWORK)
2164 exclusive = 0;
2165 else
2166 exclusive = 1;
2169 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2170 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2171 (p->digital ? -1 :
2172 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2173 if (p->pri->facilityenable)
2174 pri_facility_enable(p->pri->pri);
2176 if (option_verbose > 2)
2177 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2178 dp_strip = 0;
2179 pridialplan = p->pri->dialplan - 1;
2180 if (pridialplan == -2) { /* compute dynamically */
2181 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2182 dp_strip = strlen(p->pri->internationalprefix);
2183 pridialplan = PRI_INTERNATIONAL_ISDN;
2184 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2185 dp_strip = strlen(p->pri->nationalprefix);
2186 pridialplan = PRI_NATIONAL_ISDN;
2187 } else {
2188 pridialplan = PRI_LOCAL_ISDN;
2191 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2193 ldp_strip = 0;
2194 prilocaldialplan = p->pri->localdialplan - 1;
2195 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2196 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2197 ldp_strip = strlen(p->pri->internationalprefix);
2198 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2199 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2200 ldp_strip = strlen(p->pri->nationalprefix);
2201 prilocaldialplan = PRI_NATIONAL_ISDN;
2202 } else {
2203 prilocaldialplan = PRI_LOCAL_ISDN;
2206 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2207 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2208 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2209 if (!strcasecmp(rr_str, "UNKNOWN"))
2210 redirect_reason = 0;
2211 else if (!strcasecmp(rr_str, "BUSY"))
2212 redirect_reason = 1;
2213 else if (!strcasecmp(rr_str, "NO_REPLY"))
2214 redirect_reason = 2;
2215 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2216 redirect_reason = 15;
2217 else
2218 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2219 } else
2220 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2221 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2223 #ifdef SUPPORT_USERUSER
2224 /* User-user info */
2225 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2227 if (useruser)
2228 pri_sr_set_useruser(sr, useruser);
2229 #endif
2231 if (pri_setup(p->pri->pri, p->call, sr)) {
2232 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2233 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2234 pri_rel(p->pri);
2235 ast_mutex_unlock(&p->lock);
2236 pri_sr_free(sr);
2237 return -1;
2239 pri_sr_free(sr);
2240 ast_setstate(ast, AST_STATE_DIALING);
2241 pri_rel(p->pri);
2243 #endif
2244 ast_mutex_unlock(&p->lock);
2245 return 0;
2248 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2250 struct dahdi_pvt *p = *pvt;
2251 /* Remove channel from the list */
2252 if (p->prev)
2253 p->prev->next = p->next;
2254 if (p->next)
2255 p->next->prev = p->prev;
2256 if (p->use_smdi)
2257 ast_smdi_interface_unref(p->smdi_iface);
2258 ast_mutex_destroy(&p->lock);
2259 if (p->owner)
2260 p->owner->tech_pvt = NULL;
2261 free(p);
2262 *pvt = NULL;
2265 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2267 int owned = 0;
2268 int i = 0;
2270 if (!now) {
2271 if (cur->owner) {
2272 owned = 1;
2275 for (i = 0; i < 3; i++) {
2276 if (cur->subs[i].owner) {
2277 owned = 1;
2280 if (!owned) {
2281 if (prev) {
2282 prev->next = cur->next;
2283 if (prev->next)
2284 prev->next->prev = prev;
2285 else
2286 ifend = prev;
2287 } else {
2288 iflist = cur->next;
2289 if (iflist)
2290 iflist->prev = NULL;
2291 else
2292 ifend = NULL;
2294 if (cur->subs[SUB_REAL].dfd > -1) {
2295 dahdi_close(cur->subs[SUB_REAL].dfd);
2297 destroy_dahdi_pvt(&cur);
2299 } else {
2300 if (prev) {
2301 prev->next = cur->next;
2302 if (prev->next)
2303 prev->next->prev = prev;
2304 else
2305 ifend = prev;
2306 } else {
2307 iflist = cur->next;
2308 if (iflist)
2309 iflist->prev = NULL;
2310 else
2311 ifend = NULL;
2313 if (cur->subs[SUB_REAL].dfd > -1) {
2314 dahdi_close(cur->subs[SUB_REAL].dfd);
2316 destroy_dahdi_pvt(&cur);
2318 return 0;
2321 static void destroy_all_channels(void)
2323 int x;
2324 struct dahdi_pvt *p, *pl;
2326 while (num_restart_pending) {
2327 usleep(1);
2330 ast_mutex_lock(&iflock);
2331 /* Destroy all the interfaces and free their memory */
2332 p = iflist;
2333 while (p) {
2334 /* Free any callerid */
2335 if (p->cidspill)
2336 ast_free(p->cidspill);
2337 /* Close the DAHDI thingy */
2338 if (p->subs[SUB_REAL].dfd > -1)
2339 dahdi_close(p->subs[SUB_REAL].dfd);
2340 pl = p;
2341 p = p->next;
2342 x = pl->channel;
2343 /* Free associated memory */
2344 if (pl)
2345 destroy_dahdi_pvt(&pl);
2346 if (option_verbose > 2)
2347 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
2349 iflist = NULL;
2350 ifcount = 0;
2351 ast_mutex_unlock(&iflock);
2354 #ifdef HAVE_PRI
2355 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2356 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
2358 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2359 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2361 static char *dahdi_send_keypad_facility_descrip =
2362 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2363 " IE over the current channel.\n";
2364 static char *zap_send_keypad_facility_descrip =
2365 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2366 " IE over the current channel.\n";
2368 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
2370 /* Data will be our digit string */
2371 struct dahdi_pvt *p;
2372 char *digits = (char *) data;
2374 if (ast_strlen_zero(digits)) {
2375 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2376 return -1;
2379 p = (struct dahdi_pvt *)chan->tech_pvt;
2381 if (!p) {
2382 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2383 return -1;
2386 ast_mutex_lock(&p->lock);
2388 if (!p->pri || !p->call) {
2389 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2390 ast_mutex_unlock(&p->lock);
2391 return -1;
2394 if (!pri_grab(p, p->pri)) {
2395 pri_keypad_facility(p->pri->pri, p->call, digits);
2396 pri_rel(p->pri);
2397 } else {
2398 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2399 ast_mutex_unlock(&p->lock);
2400 return -1;
2403 ast_mutex_unlock(&p->lock);
2405 return 0;
2408 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2410 return send_keypad_facility_exec(chan, data);
2413 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2415 ast_log(LOG_WARNING, "Use of the command %s is deprecated, please use %s instead.\n", zap_send_keypad_facility_app, dahdi_send_keypad_facility_app);
2416 return send_keypad_facility_exec(chan, data);
2419 static int pri_is_up(struct dahdi_pri *pri)
2421 int x;
2422 for (x = 0; x < NUM_DCHANS; x++) {
2423 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2424 return 1;
2426 return 0;
2429 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2431 bearer->owner = &inuse;
2432 bearer->realcall = crv;
2433 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2434 if (crv->subs[SUB_REAL].owner)
2435 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2436 crv->bearer = bearer;
2437 crv->call = bearer->call;
2438 crv->pri = pri;
2439 return 0;
2442 static char *pri_order(int level)
2444 switch (level) {
2445 case 0:
2446 return "Primary";
2447 case 1:
2448 return "Secondary";
2449 case 2:
2450 return "Tertiary";
2451 case 3:
2452 return "Quaternary";
2453 default:
2454 return "<Unknown>";
2458 /* Returns fd of the active dchan */
2459 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2461 int x = -1;
2463 for (x = 0; x < NUM_DCHANS; x++) {
2464 if ((pri->dchans[x] == pri->pri))
2465 break;
2468 return pri->fds[x];
2471 static int pri_find_dchan(struct dahdi_pri *pri)
2473 int oldslot = -1;
2474 struct pri *old;
2475 int newslot = -1;
2476 int x;
2477 old = pri->pri;
2478 for (x = 0; x < NUM_DCHANS; x++) {
2479 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2480 newslot = x;
2481 if (pri->dchans[x] == old) {
2482 oldslot = x;
2485 if (newslot < 0) {
2486 newslot = 0;
2487 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2488 pri->dchannels[newslot]);
2490 if (old && (oldslot != newslot))
2491 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2492 pri->dchannels[oldslot], pri->dchannels[newslot]);
2493 pri->pri = pri->dchans[newslot];
2494 return 0;
2496 #endif
2498 static int dahdi_hangup(struct ast_channel *ast)
2500 int res;
2501 int index,x, law;
2502 /*static int restore_gains(struct dahdi_pvt *p);*/
2503 struct dahdi_pvt *p = ast->tech_pvt;
2504 struct dahdi_pvt *tmp = NULL;
2505 struct dahdi_pvt *prev = NULL;
2506 struct dahdi_params par;
2508 if (option_debug)
2509 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2510 if (!ast->tech_pvt) {
2511 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2512 return 0;
2515 ast_mutex_lock(&p->lock);
2517 index = dahdi_get_index(ast, p, 1);
2519 if (p->sig == SIG_PRI) {
2520 x = 1;
2521 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2524 x = 0;
2525 dahdi_confmute(p, 0);
2526 restore_gains(p);
2527 if (p->origcid_num) {
2528 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2529 free(p->origcid_num);
2530 p->origcid_num = NULL;
2532 if (p->origcid_name) {
2533 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2534 free(p->origcid_name);
2535 p->origcid_name = NULL;
2537 if (p->dsp)
2538 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2539 if (p->exten)
2540 p->exten[0] = '\0';
2542 if (option_debug)
2543 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2544 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2545 p->ignoredtmf = 0;
2547 if (index > -1) {
2548 /* Real channel, do some fixup */
2549 p->subs[index].owner = NULL;
2550 p->subs[index].needanswer = 0;
2551 p->subs[index].needflash = 0;
2552 p->subs[index].needringing = 0;
2553 p->subs[index].needbusy = 0;
2554 p->subs[index].needcongestion = 0;
2555 p->subs[index].linear = 0;
2556 p->subs[index].needcallerid = 0;
2557 p->polarity = POLARITY_IDLE;
2558 dahdi_setlinear(p->subs[index].dfd, 0);
2559 if (index == SUB_REAL) {
2560 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2561 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2562 if (p->subs[SUB_CALLWAIT].inthreeway) {
2563 /* We had flipped over to answer a callwait and now it's gone */
2564 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2565 /* Move to the call-wait, but un-own us until they flip back. */
2566 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2567 unalloc_sub(p, SUB_CALLWAIT);
2568 p->owner = NULL;
2569 } else {
2570 /* The three way hung up, but we still have a call wait */
2571 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2572 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2573 unalloc_sub(p, SUB_THREEWAY);
2574 if (p->subs[SUB_REAL].inthreeway) {
2575 /* This was part of a three way call. Immediately make way for
2576 another call */
2577 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2578 p->owner = p->subs[SUB_REAL].owner;
2579 } else {
2580 /* This call hasn't been completed yet... Set owner to NULL */
2581 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2582 p->owner = NULL;
2584 p->subs[SUB_REAL].inthreeway = 0;
2586 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2587 /* Move to the call-wait and switch back to them. */
2588 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2589 unalloc_sub(p, SUB_CALLWAIT);
2590 p->owner = p->subs[SUB_REAL].owner;
2591 if (p->owner->_state != AST_STATE_UP)
2592 p->subs[SUB_REAL].needanswer = 1;
2593 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2594 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2595 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2596 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2597 unalloc_sub(p, SUB_THREEWAY);
2598 if (p->subs[SUB_REAL].inthreeway) {
2599 /* This was part of a three way call. Immediately make way for
2600 another call */
2601 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2602 p->owner = p->subs[SUB_REAL].owner;
2603 } else {
2604 /* This call hasn't been completed yet... Set owner to NULL */
2605 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2606 p->owner = NULL;
2608 p->subs[SUB_REAL].inthreeway = 0;
2610 } else if (index == SUB_CALLWAIT) {
2611 /* Ditch the holding callwait call, and immediately make it availabe */
2612 if (p->subs[SUB_CALLWAIT].inthreeway) {
2613 /* This is actually part of a three way, placed on hold. Place the third part
2614 on music on hold now */
2615 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2616 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2617 S_OR(p->mohsuggest, NULL),
2618 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2620 p->subs[SUB_THREEWAY].inthreeway = 0;
2621 /* Make it the call wait now */
2622 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2623 unalloc_sub(p, SUB_THREEWAY);
2624 } else
2625 unalloc_sub(p, SUB_CALLWAIT);
2626 } else if (index == SUB_THREEWAY) {
2627 if (p->subs[SUB_CALLWAIT].inthreeway) {
2628 /* The other party of the three way call is currently in a call-wait state.
2629 Start music on hold for them, and take the main guy out of the third call */
2630 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2631 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2632 S_OR(p->mohsuggest, NULL),
2633 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2635 p->subs[SUB_CALLWAIT].inthreeway = 0;
2637 p->subs[SUB_REAL].inthreeway = 0;
2638 /* If this was part of a three way call index, let us make
2639 another three way call */
2640 unalloc_sub(p, SUB_THREEWAY);
2641 } else {
2642 /* This wasn't any sort of call, but how are we an index? */
2643 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2647 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2648 p->owner = NULL;
2649 p->ringt = 0;
2650 p->distinctivering = 0;
2651 p->confirmanswer = 0;
2652 p->cidrings = 1;
2653 p->outgoing = 0;
2654 p->digital = 0;
2655 p->faxhandled = 0;
2656 p->pulsedial = 0;
2657 p->onhooktime = time(NULL);
2658 #ifdef HAVE_PRI
2659 p->proceeding = 0;
2660 p->progress = 0;
2661 p->alerting = 0;
2662 p->setup_ack = 0;
2663 #endif
2664 if (p->dsp) {
2665 ast_dsp_free(p->dsp);
2666 p->dsp = NULL;
2669 law = DAHDI_LAW_DEFAULT;
2670 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2671 if (res < 0)
2672 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2673 /* Perform low level hangup if no owner left */
2674 #ifdef HAVE_PRI
2675 if (p->pri) {
2676 #ifdef SUPPORT_USERUSER
2677 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2678 #endif
2680 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2681 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2682 if (!pri_grab(p, p->pri)) {
2683 if (p->alreadyhungup) {
2684 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2686 #ifdef SUPPORT_USERUSER
2687 pri_call_set_useruser(p->call, useruser);
2688 #endif
2690 pri_hangup(p->pri->pri, p->call, -1);
2691 p->call = NULL;
2692 if (p->bearer)
2693 p->bearer->call = NULL;
2694 } else {
2695 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2696 int icause = ast->hangupcause ? ast->hangupcause : -1;
2697 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2699 #ifdef SUPPORT_USERUSER
2700 pri_call_set_useruser(p->call, useruser);
2701 #endif
2703 p->alreadyhungup = 1;
2704 if (p->bearer)
2705 p->bearer->alreadyhungup = 1;
2706 if (cause) {
2707 if (atoi(cause))
2708 icause = atoi(cause);
2710 pri_hangup(p->pri->pri, p->call, icause);
2712 if (res < 0)
2713 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2714 pri_rel(p->pri);
2715 } else {
2716 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2717 res = -1;
2719 } else {
2720 if (p->bearer)
2721 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2722 p->call = NULL;
2723 res = 0;
2726 #endif
2727 if (p->sig && (p->sig != SIG_PRI))
2728 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2729 if (res < 0) {
2730 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2732 switch (p->sig) {
2733 case SIG_FXOGS:
2734 case SIG_FXOLS:
2735 case SIG_FXOKS:
2736 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2737 if (!res) {
2738 #if 0
2739 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2740 #endif
2741 /* If they're off hook, try playing congestion */
2742 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2743 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2744 else
2745 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2747 break;
2748 case SIG_FXSGS:
2749 case SIG_FXSLS:
2750 case SIG_FXSKS:
2751 /* Make sure we're not made available for at least two seconds assuming
2752 we were actually used for an inbound or outbound call. */
2753 if (ast->_state != AST_STATE_RESERVED) {
2754 time(&p->guardtime);
2755 p->guardtime += 2;
2757 break;
2758 default:
2759 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2761 if (p->cidspill)
2762 free(p->cidspill);
2763 if (p->sig)
2764 dahdi_disable_ec(p);
2765 x = 0;
2766 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2767 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2768 p->didtdd = 0;
2769 p->cidspill = NULL;
2770 p->callwaitcas = 0;
2771 p->callwaiting = p->permcallwaiting;
2772 p->hidecallerid = p->permhidecallerid;
2773 p->dialing = 0;
2774 p->rdnis[0] = '\0';
2775 update_conf(p);
2776 reset_conf(p);
2777 /* Restore data mode */
2778 if (p->sig == SIG_PRI) {
2779 x = 0;
2780 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2782 #ifdef HAVE_PRI
2783 if (p->bearer) {
2784 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2785 /* Free up the bearer channel as well, and
2786 don't use its file descriptor anymore */
2787 update_conf(p->bearer);
2788 reset_conf(p->bearer);
2789 p->bearer->owner = NULL;
2790 p->bearer->realcall = NULL;
2791 p->bearer = NULL;
2792 p->subs[SUB_REAL].dfd = -1;
2793 p->pri = NULL;
2795 #endif
2796 if (num_restart_pending == 0)
2797 restart_monitor();
2800 p->callwaitingrepeat = 0;
2801 p->cidcwexpire = 0;
2802 p->oprmode = 0;
2803 ast->tech_pvt = NULL;
2804 ast_mutex_unlock(&p->lock);
2805 ast_module_unref(ast_module_info->self);
2806 if (option_verbose > 2)
2807 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2809 ast_mutex_lock(&iflock);
2811 if (p->restartpending) {
2812 num_restart_pending--;
2815 tmp = iflist;
2816 prev = NULL;
2817 if (p->destroy) {
2818 while (tmp) {
2819 if (tmp == p) {
2820 destroy_channel(prev, tmp, 0);
2821 break;
2822 } else {
2823 prev = tmp;
2824 tmp = tmp->next;
2828 ast_mutex_unlock(&iflock);
2829 return 0;
2832 static int dahdi_answer(struct ast_channel *ast)
2834 struct dahdi_pvt *p = ast->tech_pvt;
2835 int res = 0;
2836 int index;
2837 int oldstate = ast->_state;
2838 ast_setstate(ast, AST_STATE_UP);
2839 ast_mutex_lock(&p->lock);
2840 index = dahdi_get_index(ast, p, 0);
2841 if (index < 0)
2842 index = SUB_REAL;
2843 /* nothing to do if a radio channel */
2844 if ((p->radio || (p->oprmode < 0))) {
2845 ast_mutex_unlock(&p->lock);
2846 return 0;
2848 switch (p->sig) {
2849 case SIG_FXSLS:
2850 case SIG_FXSGS:
2851 case SIG_FXSKS:
2852 p->ringt = 0;
2853 /* Fall through */
2854 case SIG_EM:
2855 case SIG_EM_E1:
2856 case SIG_EMWINK:
2857 case SIG_FEATD:
2858 case SIG_FEATDMF:
2859 case SIG_FEATDMF_TA:
2860 case SIG_E911:
2861 case SIG_FGC_CAMA:
2862 case SIG_FGC_CAMAMF:
2863 case SIG_FEATB:
2864 case SIG_SF:
2865 case SIG_SFWINK:
2866 case SIG_SF_FEATD:
2867 case SIG_SF_FEATDMF:
2868 case SIG_SF_FEATB:
2869 case SIG_FXOLS:
2870 case SIG_FXOGS:
2871 case SIG_FXOKS:
2872 /* Pick up the line */
2873 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
2874 if (p->hanguponpolarityswitch) {
2875 gettimeofday(&p->polaritydelaytv, NULL);
2877 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2878 tone_zone_play_tone(p->subs[index].dfd, -1);
2879 p->dialing = 0;
2880 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
2881 if (oldstate == AST_STATE_RINGING) {
2882 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
2883 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
2884 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2885 p->owner = p->subs[SUB_REAL].owner;
2888 if (p->sig & __DAHDI_SIG_FXS) {
2889 dahdi_enable_ec(p);
2890 dahdi_train_ec(p);
2892 break;
2893 #ifdef HAVE_PRI
2894 case SIG_PRI:
2895 /* Send a pri acknowledge */
2896 if (!pri_grab(p, p->pri)) {
2897 p->proceeding = 1;
2898 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2899 pri_rel(p->pri);
2900 } else {
2901 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2902 res = -1;
2904 break;
2905 #endif
2906 case 0:
2907 ast_mutex_unlock(&p->lock);
2908 return 0;
2909 default:
2910 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
2911 res = -1;
2913 ast_mutex_unlock(&p->lock);
2914 return res;
2917 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
2919 char *cp;
2920 signed char *scp;
2921 int x;
2922 int index;
2923 struct dahdi_pvt *p = chan->tech_pvt, *pp;
2924 struct oprmode *oprmode;
2927 /* all supported options require data */
2928 if (!data || (datalen < 1)) {
2929 errno = EINVAL;
2930 return -1;
2933 switch (option) {
2934 case AST_OPTION_TXGAIN:
2935 scp = (signed char *) data;
2936 index = dahdi_get_index(chan, p, 0);
2937 if (index < 0) {
2938 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
2939 return -1;
2941 if (option_debug)
2942 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
2943 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
2944 case AST_OPTION_RXGAIN:
2945 scp = (signed char *) data;
2946 index = dahdi_get_index(chan, p, 0);
2947 if (index < 0) {
2948 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
2949 return -1;
2951 if (option_debug)
2952 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
2953 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
2954 case AST_OPTION_TONE_VERIFY:
2955 if (!p->dsp)
2956 break;
2957 cp = (char *) data;
2958 switch (*cp) {
2959 case 1:
2960 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
2961 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
2962 break;
2963 case 2:
2964 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
2965 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
2966 break;
2967 default:
2968 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
2969 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
2970 break;
2972 break;
2973 case AST_OPTION_TDD:
2974 /* turn on or off TDD */
2975 cp = (char *) data;
2976 p->mate = 0;
2977 if (!*cp) { /* turn it off */
2978 if (option_debug)
2979 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
2980 if (p->tdd)
2981 tdd_free(p->tdd);
2982 p->tdd = 0;
2983 break;
2985 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
2986 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
2987 dahdi_disable_ec(p);
2988 /* otherwise, turn it on */
2989 if (!p->didtdd) { /* if havent done it yet */
2990 unsigned char mybuf[41000], *buf;
2991 int size, res, fd, len;
2992 struct pollfd fds[1];
2994 buf = mybuf;
2995 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
2996 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
2997 len = 40000;
2998 index = dahdi_get_index(chan, p, 0);
2999 if (index < 0) {
3000 ast_log(LOG_WARNING, "No index in TDD?\n");
3001 return -1;
3003 fd = p->subs[index].dfd;
3004 while (len) {
3005 if (ast_check_hangup(chan))
3006 return -1;
3007 size = len;
3008 if (size > READ_SIZE)
3009 size = READ_SIZE;
3010 fds[0].fd = fd;
3011 fds[0].events = POLLPRI | POLLOUT;
3012 fds[0].revents = 0;
3013 res = poll(fds, 1, -1);
3014 if (!res) {
3015 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
3016 continue;
3018 /* if got exception */
3019 if (fds[0].revents & POLLPRI)
3020 return -1;
3021 if (!(fds[0].revents & POLLOUT)) {
3022 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
3023 continue;
3025 res = write(fd, buf, size);
3026 if (res != size) {
3027 if (res == -1) return -1;
3028 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
3029 break;
3031 len -= size;
3032 buf += size;
3034 p->didtdd = 1; /* set to have done it now */
3036 if (*cp == 2) { /* Mate mode */
3037 if (p->tdd)
3038 tdd_free(p->tdd);
3039 p->tdd = 0;
3040 p->mate = 1;
3041 break;
3043 if (!p->tdd) { /* if we dont have one yet */
3044 p->tdd = tdd_new(); /* allocate one */
3046 break;
3047 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
3048 if (!p->dsp)
3049 break;
3050 cp = (char *) data;
3051 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3052 *cp ? "ON" : "OFF", (int) *cp, chan->name);
3053 p->dtmfrelax = 0;
3054 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
3055 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
3056 break;
3057 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
3058 cp = (char *) data;
3059 if (!*cp) {
3060 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
3061 x = 0;
3062 dahdi_disable_ec(p);
3063 } else {
3064 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
3065 x = 1;
3067 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
3068 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
3069 break;
3070 case AST_OPTION_OPRMODE: /* Operator services mode */
3071 oprmode = (struct oprmode *) data;
3072 pp = oprmode->peer->tech_pvt;
3073 p->oprmode = pp->oprmode = 0;
3074 /* setup peers */
3075 p->oprpeer = pp;
3076 pp->oprpeer = p;
3077 /* setup modes, if any */
3078 if (oprmode->mode)
3080 pp->oprmode = oprmode->mode;
3081 p->oprmode = -oprmode->mode;
3083 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
3084 oprmode->mode, chan->name,oprmode->peer->name);;
3085 break;
3086 case AST_OPTION_ECHOCAN:
3087 cp = (char *) data;
3088 if (*cp) {
3089 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3090 dahdi_enable_ec(p);
3091 } else {
3092 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3093 dahdi_disable_ec(p);
3095 break;
3097 errno = 0;
3099 return 0;
3102 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3104 struct dahdi_pvt *p = chan->tech_pvt;
3106 if (!strcasecmp(data, "rxgain")) {
3107 ast_mutex_lock(&p->lock);
3108 snprintf(buf, len, "%f", p->rxgain);
3109 ast_mutex_unlock(&p->lock);
3110 } else if (!strcasecmp(data, "txgain")) {
3111 ast_mutex_lock(&p->lock);
3112 snprintf(buf, len, "%f", p->txgain);
3113 ast_mutex_unlock(&p->lock);
3114 } else {
3115 ast_copy_string(buf, "", len);
3117 return 0;
3121 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3123 /* Unlink a specific slave or all slaves/masters from a given master */
3124 int x;
3125 int hasslaves;
3126 if (!master)
3127 return;
3128 if (needlock) {
3129 ast_mutex_lock(&master->lock);
3130 if (slave) {
3131 while (ast_mutex_trylock(&slave->lock)) {
3132 DEADLOCK_AVOIDANCE(&master->lock);
3136 hasslaves = 0;
3137 for (x = 0; x < MAX_SLAVES; x++) {
3138 if (master->slaves[x]) {
3139 if (!slave || (master->slaves[x] == slave)) {
3140 /* Take slave out of the conference */
3141 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3142 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3143 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3144 master->slaves[x]->master = NULL;
3145 master->slaves[x] = NULL;
3146 } else
3147 hasslaves = 1;
3149 if (!hasslaves)
3150 master->inconference = 0;
3152 if (!slave) {
3153 if (master->master) {
3154 /* Take master out of the conference */
3155 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3156 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3157 hasslaves = 0;
3158 for (x = 0; x < MAX_SLAVES; x++) {
3159 if (master->master->slaves[x] == master)
3160 master->master->slaves[x] = NULL;
3161 else if (master->master->slaves[x])
3162 hasslaves = 1;
3164 if (!hasslaves)
3165 master->master->inconference = 0;
3167 master->master = NULL;
3169 update_conf(master);
3170 if (needlock) {
3171 if (slave)
3172 ast_mutex_unlock(&slave->lock);
3173 ast_mutex_unlock(&master->lock);
3177 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3178 int x;
3179 if (!slave || !master) {
3180 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3181 return;
3183 for (x = 0; x < MAX_SLAVES; x++) {
3184 if (!master->slaves[x]) {
3185 master->slaves[x] = slave;
3186 break;
3189 if (x >= MAX_SLAVES) {
3190 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3191 master->slaves[MAX_SLAVES - 1] = slave;
3193 if (slave->master)
3194 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3195 slave->master = master;
3197 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3200 static void disable_dtmf_detect(struct dahdi_pvt *p)
3202 #ifdef DAHDI_TONEDETECT
3203 int val;
3204 #endif
3206 p->ignoredtmf = 1;
3208 #ifdef DAHDI_TONEDETECT
3209 val = 0;
3210 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3211 #endif
3212 if (!p->hardwaredtmf && p->dsp) {
3213 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3214 ast_dsp_set_features(p->dsp, p->dsp_features);
3218 static void enable_dtmf_detect(struct dahdi_pvt *p)
3220 #ifdef DAHDI_TONEDETECT
3221 int val;
3222 #endif
3224 if (p->channel == CHAN_PSEUDO)
3225 return;
3227 p->ignoredtmf = 0;
3229 #ifdef DAHDI_TONEDETECT
3230 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3231 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3232 #endif
3233 if (!p->hardwaredtmf && p->dsp) {
3234 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3235 ast_dsp_set_features(p->dsp, p->dsp_features);
3239 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)
3241 struct ast_channel *who;
3242 struct dahdi_pvt *p0, *p1, *op0, *op1;
3243 struct dahdi_pvt *master = NULL, *slave = NULL;
3244 struct ast_frame *f;
3245 int inconf = 0;
3246 int nothingok = 1;
3247 int ofd0, ofd1;
3248 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3249 int os0 = -1, os1 = -1;
3250 int priority = 0;
3251 struct ast_channel *oc0, *oc1;
3252 enum ast_bridge_result res;
3254 #ifdef PRI_2BCT
3255 int triedtopribridge = 0;
3256 q931_call *q931c0 = NULL, *q931c1 = NULL;
3257 #endif
3259 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3260 There is code below to handle it properly until DTMF is actually seen,
3261 but due to currently unresolved issues it's ignored...
3264 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3265 return AST_BRIDGE_FAILED_NOWARN;
3267 ast_mutex_lock(&c0->lock);
3268 while (ast_mutex_trylock(&c1->lock)) {
3269 DEADLOCK_AVOIDANCE(&c0->lock);
3272 p0 = c0->tech_pvt;
3273 p1 = c1->tech_pvt;
3274 /* cant do pseudo-channels here */
3275 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3276 ast_mutex_unlock(&c0->lock);
3277 ast_mutex_unlock(&c1->lock);
3278 return AST_BRIDGE_FAILED_NOWARN;
3281 oi0 = dahdi_get_index(c0, p0, 0);
3282 oi1 = dahdi_get_index(c1, p1, 0);
3283 if ((oi0 < 0) || (oi1 < 0)) {
3284 ast_mutex_unlock(&c0->lock);
3285 ast_mutex_unlock(&c1->lock);
3286 return AST_BRIDGE_FAILED;
3289 op0 = p0 = c0->tech_pvt;
3290 op1 = p1 = c1->tech_pvt;
3291 ofd0 = c0->fds[0];
3292 ofd1 = c1->fds[0];
3293 oc0 = p0->owner;
3294 oc1 = p1->owner;
3296 if (ast_mutex_trylock(&p0->lock)) {
3297 /* Don't block, due to potential for deadlock */
3298 ast_mutex_unlock(&c0->lock);
3299 ast_mutex_unlock(&c1->lock);
3300 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3301 return AST_BRIDGE_RETRY;
3303 if (ast_mutex_trylock(&p1->lock)) {
3304 /* Don't block, due to potential for deadlock */
3305 ast_mutex_unlock(&p0->lock);
3306 ast_mutex_unlock(&c0->lock);
3307 ast_mutex_unlock(&c1->lock);
3308 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3309 return AST_BRIDGE_RETRY;
3312 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3313 if (p0->owner && p1->owner) {
3314 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3315 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3316 master = p0;
3317 slave = p1;
3318 inconf = 1;
3319 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3320 master = p1;
3321 slave = p0;
3322 inconf = 1;
3323 } else {
3324 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3325 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3326 p0->channel,
3327 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3328 p0->subs[SUB_REAL].inthreeway, p0->channel,
3329 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3330 p1->subs[SUB_REAL].inthreeway);
3332 nothingok = 0;
3334 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3335 if (p1->subs[SUB_THREEWAY].inthreeway) {
3336 master = p1;
3337 slave = p0;
3338 nothingok = 0;
3340 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3341 if (p0->subs[SUB_THREEWAY].inthreeway) {
3342 master = p0;
3343 slave = p1;
3344 nothingok = 0;
3346 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3347 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3348 don't put us in anything */
3349 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3350 master = p1;
3351 slave = p0;
3352 nothingok = 0;
3354 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3355 /* Same as previous */
3356 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3357 master = p0;
3358 slave = p1;
3359 nothingok = 0;
3362 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3363 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3364 if (master && slave) {
3365 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3366 in an active threeway call with a channel that is ringing, we should
3367 indicate ringing. */
3368 if ((oi1 == SUB_THREEWAY) &&
3369 p1->subs[SUB_THREEWAY].inthreeway &&
3370 p1->subs[SUB_REAL].owner &&
3371 p1->subs[SUB_REAL].inthreeway &&
3372 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3373 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3374 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3375 os1 = p1->subs[SUB_REAL].owner->_state;
3376 } else {
3377 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3378 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3380 if ((oi0 == SUB_THREEWAY) &&
3381 p0->subs[SUB_THREEWAY].inthreeway &&
3382 p0->subs[SUB_REAL].owner &&
3383 p0->subs[SUB_REAL].inthreeway &&
3384 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3385 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3386 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3387 os0 = p0->subs[SUB_REAL].owner->_state;
3388 } else {
3389 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3390 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3392 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3393 if (!p0->echocanbridged || !p1->echocanbridged) {
3394 /* Disable echo cancellation if appropriate */
3395 dahdi_disable_ec(p0);
3396 dahdi_disable_ec(p1);
3399 dahdi_link(slave, master);
3400 master->inconference = inconf;
3401 } else if (!nothingok)
3402 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3404 update_conf(p0);
3405 update_conf(p1);
3406 t0 = p0->subs[SUB_REAL].inthreeway;
3407 t1 = p1->subs[SUB_REAL].inthreeway;
3409 ast_mutex_unlock(&p0->lock);
3410 ast_mutex_unlock(&p1->lock);
3412 ast_mutex_unlock(&c0->lock);
3413 ast_mutex_unlock(&c1->lock);
3415 /* Native bridge failed */
3416 if ((!master || !slave) && !nothingok) {
3417 dahdi_enable_ec(p0);
3418 dahdi_enable_ec(p1);
3419 return AST_BRIDGE_FAILED;
3422 if (option_verbose > 2)
3423 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3425 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3426 disable_dtmf_detect(op0);
3428 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3429 disable_dtmf_detect(op1);
3431 for (;;) {
3432 struct ast_channel *c0_priority[2] = {c0, c1};
3433 struct ast_channel *c1_priority[2] = {c1, c0};
3435 /* Here's our main loop... Start by locking things, looking for private parts,
3436 and then balking if anything is wrong */
3437 ast_mutex_lock(&c0->lock);
3438 while (ast_mutex_trylock(&c1->lock)) {
3439 DEADLOCK_AVOIDANCE(&c0->lock);
3442 p0 = c0->tech_pvt;
3443 p1 = c1->tech_pvt;
3445 if (op0 == p0)
3446 i0 = dahdi_get_index(c0, p0, 1);
3447 if (op1 == p1)
3448 i1 = dahdi_get_index(c1, p1, 1);
3449 ast_mutex_unlock(&c0->lock);
3450 ast_mutex_unlock(&c1->lock);
3452 if (!timeoutms ||
3453 (op0 != p0) ||
3454 (op1 != p1) ||
3455 (ofd0 != c0->fds[0]) ||
3456 (ofd1 != c1->fds[0]) ||
3457 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3458 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3459 (oc0 != p0->owner) ||
3460 (oc1 != p1->owner) ||
3461 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3462 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3463 (oi0 != i0) ||
3464 (oi1 != i1)) {
3465 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3466 op0->channel, oi0, op1->channel, oi1);
3467 res = AST_BRIDGE_RETRY;
3468 goto return_from_bridge;
3471 #ifdef PRI_2BCT
3472 q931c0 = p0->call;
3473 q931c1 = p1->call;
3474 if (p0->transfer && p1->transfer
3475 && q931c0 && q931c1
3476 && !triedtopribridge) {
3477 pri_channel_bridge(q931c0, q931c1);
3478 triedtopribridge = 1;
3480 #endif
3482 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3483 if (!who) {
3484 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3485 continue;
3487 f = ast_read(who);
3488 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3489 *fo = f;
3490 *rc = who;
3491 res = AST_BRIDGE_COMPLETE;
3492 goto return_from_bridge;
3494 if (f->frametype == AST_FRAME_DTMF) {
3495 if ((who == c0) && p0->pulsedial) {
3496 ast_write(c1, f);
3497 } else if ((who == c1) && p1->pulsedial) {
3498 ast_write(c0, f);
3499 } else {
3500 *fo = f;
3501 *rc = who;
3502 res = AST_BRIDGE_COMPLETE;
3503 goto return_from_bridge;
3506 ast_frfree(f);
3508 /* Swap who gets priority */
3509 priority = !priority;
3512 return_from_bridge:
3513 if (op0 == p0)
3514 dahdi_enable_ec(p0);
3516 if (op1 == p1)
3517 dahdi_enable_ec(p1);
3519 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3520 enable_dtmf_detect(op0);
3522 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3523 enable_dtmf_detect(op1);
3525 dahdi_unlink(slave, master, 1);
3527 return res;
3530 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3532 struct dahdi_pvt *p = newchan->tech_pvt;
3533 int x;
3534 ast_mutex_lock(&p->lock);
3535 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3536 if (p->owner == oldchan) {
3537 p->owner = newchan;
3539 for (x = 0; x < 3; x++)
3540 if (p->subs[x].owner == oldchan) {
3541 if (!x)
3542 dahdi_unlink(NULL, p, 0);
3543 p->subs[x].owner = newchan;
3545 if (newchan->_state == AST_STATE_RINGING)
3546 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3547 update_conf(p);
3548 ast_mutex_unlock(&p->lock);
3549 return 0;
3552 static int dahdi_ring_phone(struct dahdi_pvt *p)
3554 int x;
3555 int res;
3556 /* Make sure our transmit state is on hook */
3557 x = 0;
3558 x = DAHDI_ONHOOK;
3559 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3560 do {
3561 x = DAHDI_RING;
3562 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3563 if (res) {
3564 switch (errno) {
3565 case EBUSY:
3566 case EINTR:
3567 /* Wait just in case */
3568 usleep(10000);
3569 continue;
3570 case EINPROGRESS:
3571 res = 0;
3572 break;
3573 default:
3574 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3575 res = 0;
3578 } while (res);
3579 return res;
3582 static void *ss_thread(void *data);
3584 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3586 static int attempt_transfer(struct dahdi_pvt *p)
3588 /* In order to transfer, we need at least one of the channels to
3589 actually be in a call bridge. We can't conference two applications
3590 together (but then, why would we want to?) */
3591 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3592 /* The three-way person we're about to transfer to could still be in MOH, so
3593 stop if now if appropriate */
3594 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3595 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3596 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3597 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3599 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3600 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3602 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3603 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3604 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3605 return -1;
3607 /* Orphan the channel after releasing the lock */
3608 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3609 unalloc_sub(p, SUB_THREEWAY);
3610 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3611 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3612 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3613 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3615 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3616 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3618 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3619 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3620 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3621 return -1;
3623 /* Three-way is now the REAL */
3624 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3625 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3626 unalloc_sub(p, SUB_THREEWAY);
3627 /* Tell the caller not to hangup */
3628 return 1;
3629 } else {
3630 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3631 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3632 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3633 return -1;
3635 return 0;
3638 static int check_for_conference(struct dahdi_pvt *p)
3640 struct dahdi_confinfo ci;
3641 /* Fine if we already have a master, etc */
3642 if (p->master || (p->confno > -1))
3643 return 0;
3644 memset(&ci, 0, sizeof(ci));
3645 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3646 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3647 return 0;
3649 /* If we have no master and don't have a confno, then
3650 if we're in a conference, it's probably a MeetMe room or
3651 some such, so don't let us 3-way out! */
3652 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3653 if (option_verbose > 2)
3654 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3655 return 1;
3657 return 0;
3660 static int get_alarms(struct dahdi_pvt *p)
3662 int res;
3663 struct dahdi_spaninfo zi;
3664 memset(&zi, 0, sizeof(zi));
3665 zi.spanno = p->span;
3666 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi);
3667 if (res < 0) {
3668 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3669 return 0;
3671 return zi.alarms;
3674 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3676 struct dahdi_pvt *p = ast->tech_pvt;
3677 struct ast_frame *f = *dest;
3679 if (option_debug)
3680 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3682 if (p->confirmanswer) {
3683 if (option_debug)
3684 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3685 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3686 of a DTMF digit */
3687 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3688 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3689 *dest = &p->subs[index].f;
3690 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3691 p->confirmanswer = 0;
3692 } else if (p->callwaitcas) {
3693 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3694 if (option_debug)
3695 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3696 if (p->cidspill)
3697 free(p->cidspill);
3698 send_cwcidspill(p);
3700 if ((f->subclass != 'm') && (f->subclass != 'u'))
3701 p->callwaitcas = 0;
3702 p->subs[index].f.frametype = AST_FRAME_NULL;
3703 p->subs[index].f.subclass = 0;
3704 *dest = &p->subs[index].f;
3705 } else if (f->subclass == 'f') {
3706 /* Fax tone -- Handle and return NULL */
3707 if ((p->callprogress & 0x6) && !p->faxhandled) {
3708 p->faxhandled++;
3709 if (strcmp(ast->exten, "fax")) {
3710 const char *target_context = S_OR(ast->macrocontext, ast->context);
3712 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3713 if (option_verbose > 2)
3714 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3715 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3716 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3717 if (ast_async_goto(ast, target_context, "fax", 1))
3718 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3719 } else
3720 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3721 } else if (option_debug)
3722 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3723 } else if (option_debug)
3724 ast_log(LOG_DEBUG, "Fax already handled\n");
3725 dahdi_confmute(p, 0);
3726 p->subs[index].f.frametype = AST_FRAME_NULL;
3727 p->subs[index].f.subclass = 0;
3728 *dest = &p->subs[index].f;
3729 } else if (f->subclass == 'm') {
3730 /* Confmute request */
3731 dahdi_confmute(p, 1);
3732 p->subs[index].f.frametype = AST_FRAME_NULL;
3733 p->subs[index].f.subclass = 0;
3734 *dest = &p->subs[index].f;
3735 } else if (f->subclass == 'u') {
3736 /* Unmute */
3737 dahdi_confmute(p, 0);
3738 p->subs[index].f.frametype = AST_FRAME_NULL;
3739 p->subs[index].f.subclass = 0;
3740 *dest = &p->subs[index].f;
3741 } else
3742 dahdi_confmute(p, 0);
3745 static void handle_alarms(struct dahdi_pvt *p, int alarms)
3747 const char *alarm_str = alarm2str(alarms);
3749 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3750 * doesn't know what to do with it. Don't confuse users with log messages. */
3751 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3752 p->unknown_alarm = 1;
3753 return;
3754 } else {
3755 p->unknown_alarm = 0;
3758 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3759 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3760 "Alarm: %s\r\n"
3761 "Channel: %d\r\n",
3762 alarm_str, p->channel);
3765 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
3767 int res, x;
3768 int index, mysig;
3769 char *c;
3770 struct dahdi_pvt *p = ast->tech_pvt;
3771 pthread_t threadid;
3772 pthread_attr_t attr;
3773 struct ast_channel *chan;
3774 struct ast_frame *f;
3776 index = dahdi_get_index(ast, p, 0);
3777 mysig = p->sig;
3778 if (p->outsigmod > -1)
3779 mysig = p->outsigmod;
3780 p->subs[index].f.frametype = AST_FRAME_NULL;
3781 p->subs[index].f.subclass = 0;
3782 p->subs[index].f.datalen = 0;
3783 p->subs[index].f.samples = 0;
3784 p->subs[index].f.mallocd = 0;
3785 p->subs[index].f.offset = 0;
3786 p->subs[index].f.src = "dahdi_handle_event";
3787 p->subs[index].f.data = NULL;
3788 f = &p->subs[index].f;
3790 if (index < 0)
3791 return &p->subs[index].f;
3792 if (p->fake_event) {
3793 res = p->fake_event;
3794 p->fake_event = 0;
3795 } else
3796 res = dahdi_get_event(p->subs[index].dfd);
3798 if (option_debug)
3799 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
3801 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
3802 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
3804 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
3805 #ifdef HAVE_PRI
3806 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
3807 /* absorb event */
3808 } else {
3809 #endif
3810 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
3811 p->subs[index].f.subclass = res & 0xff;
3812 #ifdef HAVE_PRI
3814 #endif
3815 dahdi_handle_dtmfup(ast, index, &f);
3816 return f;
3819 if (res & DAHDI_EVENT_DTMFDOWN) {
3820 if (option_debug)
3821 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
3822 /* Mute conference */
3823 dahdi_confmute(p, 1);
3824 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
3825 p->subs[index].f.subclass = res & 0xff;
3826 return &p->subs[index].f;
3829 switch (res) {
3830 #ifdef DAHDI_EVENT_EC_DISABLED
3831 case DAHDI_EVENT_EC_DISABLED:
3832 if (option_verbose > 2)
3833 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
3834 p->echocanon = 0;
3835 break;
3836 #endif
3837 case DAHDI_EVENT_BITSCHANGED:
3838 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
3839 case DAHDI_EVENT_PULSE_START:
3840 /* Stop tone if there's a pulse start and the PBX isn't started */
3841 if (!ast->pbx)
3842 tone_zone_play_tone(p->subs[index].dfd, -1);
3843 break;
3844 case DAHDI_EVENT_DIALCOMPLETE:
3845 if (p->inalarm) break;
3846 if ((p->radio || (p->oprmode < 0))) break;
3847 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
3848 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
3849 return NULL;
3851 if (!x) { /* if not still dialing in driver */
3852 dahdi_enable_ec(p);
3853 if (p->echobreak) {
3854 dahdi_train_ec(p);
3855 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
3856 p->dop.op = DAHDI_DIAL_OP_REPLACE;
3857 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
3858 p->echobreak = 0;
3859 } else {
3860 p->dialing = 0;
3861 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
3862 /* if thru with dialing after offhook */
3863 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
3864 ast_setstate(ast, AST_STATE_UP);
3865 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3866 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3867 break;
3868 } else { /* if to state wait for offhook to dial rest */
3869 /* we now wait for off hook */
3870 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
3873 if (ast->_state == AST_STATE_DIALING) {
3874 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3875 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
3876 } 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)))) {
3877 ast_setstate(ast, AST_STATE_RINGING);
3878 } else if (!p->answeronpolarityswitch) {
3879 ast_setstate(ast, AST_STATE_UP);
3880 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3881 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3882 /* If aops=0 and hops=1, this is necessary */
3883 p->polarity = POLARITY_REV;
3884 } else {
3885 /* Start clean, so we can catch the change to REV polarity when party answers */
3886 p->polarity = POLARITY_IDLE;
3891 break;
3892 case DAHDI_EVENT_ALARM:
3893 #ifdef HAVE_PRI
3894 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
3895 /* T309 is not enabled : hangup calls when alarm occurs */
3896 if (p->call) {
3897 if (p->pri && p->pri->pri) {
3898 if (!pri_grab(p, p->pri)) {
3899 pri_hangup(p->pri->pri, p->call, -1);
3900 pri_destroycall(p->pri->pri, p->call);
3901 p->call = NULL;
3902 pri_rel(p->pri);
3903 } else
3904 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3905 } else
3906 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
3908 if (p->owner)
3909 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3911 if (p->bearer)
3912 p->bearer->inalarm = 1;
3913 else
3914 #endif
3915 p->inalarm = 1;
3916 res = get_alarms(p);
3917 handle_alarms(p, res);
3918 #ifdef HAVE_LIBPRI
3919 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3920 /* fall through intentionally */
3921 } else {
3922 break;
3924 #endif
3925 case DAHDI_EVENT_ONHOOK:
3926 if (p->radio) {
3927 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3928 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
3929 break;
3931 if (p->oprmode < 0)
3933 if (p->oprmode != -1) break;
3934 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3936 /* Make sure it starts ringing */
3937 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3938 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
3939 save_conference(p->oprpeer);
3940 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3942 break;
3944 switch (p->sig) {
3945 case SIG_FXOLS:
3946 case SIG_FXOGS:
3947 case SIG_FXOKS:
3948 p->onhooktime = time(NULL);
3949 p->msgstate = -1;
3950 /* Check for some special conditions regarding call waiting */
3951 if (index == SUB_REAL) {
3952 /* The normal line was hung up */
3953 if (p->subs[SUB_CALLWAIT].owner) {
3954 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3955 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3956 if (option_verbose > 2)
3957 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
3958 unalloc_sub(p, SUB_CALLWAIT);
3959 #if 0
3960 p->subs[index].needanswer = 0;
3961 p->subs[index].needringing = 0;
3962 #endif
3963 p->callwaitingrepeat = 0;
3964 p->cidcwexpire = 0;
3965 p->owner = NULL;
3966 /* Don't start streaming audio yet if the incoming call isn't up yet */
3967 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
3968 p->dialing = 1;
3969 dahdi_ring_phone(p);
3970 } else if (p->subs[SUB_THREEWAY].owner) {
3971 unsigned int mssinceflash;
3972 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3973 the private structure -- not especially easy or clean */
3974 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
3975 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
3976 ast_mutex_unlock(&p->lock);
3977 DEADLOCK_AVOIDANCE(&ast->lock);
3978 /* We can grab ast and p in that order, without worry. We should make sure
3979 nothing seriously bad has happened though like some sort of bizarre double
3980 masquerade! */
3981 ast_mutex_lock(&p->lock);
3982 if (p->owner != ast) {
3983 ast_log(LOG_WARNING, "This isn't good...\n");
3984 return NULL;
3987 if (!p->subs[SUB_THREEWAY].owner) {
3988 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
3989 return NULL;
3991 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
3992 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
3993 if (mssinceflash < MIN_MS_SINCE_FLASH) {
3994 /* It hasn't been long enough since the last flashook. This is probably a bounce on
3995 hanging up. Hangup both channels now */
3996 if (p->subs[SUB_THREEWAY].owner)
3997 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
3998 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3999 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
4000 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4001 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
4002 if (p->transfer) {
4003 /* In any case this isn't a threeway call anymore */
4004 p->subs[SUB_REAL].inthreeway = 0;
4005 p->subs[SUB_THREEWAY].inthreeway = 0;
4006 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4007 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
4008 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4009 /* Swap subs and dis-own channel */
4010 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4011 p->owner = NULL;
4012 /* Ring the phone */
4013 dahdi_ring_phone(p);
4014 } else {
4015 if ((res = attempt_transfer(p)) < 0) {
4016 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4017 if (p->subs[SUB_THREEWAY].owner)
4018 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4019 } else if (res) {
4020 /* Don't actually hang up at this point */
4021 if (p->subs[SUB_THREEWAY].owner)
4022 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4023 break;
4026 } else {
4027 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4028 if (p->subs[SUB_THREEWAY].owner)
4029 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4031 } else {
4032 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4033 /* Swap subs and dis-own channel */
4034 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4035 p->owner = NULL;
4036 /* Ring the phone */
4037 dahdi_ring_phone(p);
4040 } else {
4041 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
4043 /* Fall through */
4044 default:
4045 dahdi_disable_ec(p);
4046 return NULL;
4048 break;
4049 case DAHDI_EVENT_RINGOFFHOOK:
4050 if (p->inalarm) break;
4051 if (p->oprmode < 0)
4053 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4055 /* Make sure it stops ringing */
4056 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4057 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
4058 restore_conference(p->oprpeer);
4060 break;
4062 if (p->radio)
4064 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4065 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4066 break;
4068 /* for E911, its supposed to wait for offhook then dial
4069 the second half of the dial string */
4070 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
4071 c = strchr(p->dialdest, '/');
4072 if (c)
4073 c++;
4074 else
4075 c = p->dialdest;
4076 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
4077 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
4078 if (strlen(p->dop.dialstr) > 4) {
4079 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
4080 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
4081 p->echorest[sizeof(p->echorest) - 1] = '\0';
4082 p->echobreak = 1;
4083 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
4084 } else
4085 p->echobreak = 0;
4086 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
4087 int saveerr = errno;
4089 x = DAHDI_ONHOOK;
4090 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4091 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4092 return NULL;
4094 p->dialing = 1;
4095 return &p->subs[index].f;
4097 switch (p->sig) {
4098 case SIG_FXOLS:
4099 case SIG_FXOGS:
4100 case SIG_FXOKS:
4101 switch (ast->_state) {
4102 case AST_STATE_RINGING:
4103 dahdi_enable_ec(p);
4104 dahdi_train_ec(p);
4105 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4106 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4107 /* Make sure it stops ringing */
4108 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4109 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4110 if (p->cidspill) {
4111 /* Cancel any running CallerID spill */
4112 free(p->cidspill);
4113 p->cidspill = NULL;
4115 p->dialing = 0;
4116 p->callwaitcas = 0;
4117 if (p->confirmanswer) {
4118 /* Ignore answer if "confirm answer" is enabled */
4119 p->subs[index].f.frametype = AST_FRAME_NULL;
4120 p->subs[index].f.subclass = 0;
4121 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4122 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4123 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4124 if (res < 0) {
4125 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4126 p->dop.dialstr[0] = '\0';
4127 return NULL;
4128 } else {
4129 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4130 p->subs[index].f.frametype = AST_FRAME_NULL;
4131 p->subs[index].f.subclass = 0;
4132 p->dialing = 1;
4134 p->dop.dialstr[0] = '\0';
4135 ast_setstate(ast, AST_STATE_DIALING);
4136 } else
4137 ast_setstate(ast, AST_STATE_UP);
4138 return &p->subs[index].f;
4139 case AST_STATE_DOWN:
4140 ast_setstate(ast, AST_STATE_RING);
4141 ast->rings = 1;
4142 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4143 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4144 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4145 return &p->subs[index].f;
4146 case AST_STATE_UP:
4147 /* Make sure it stops ringing */
4148 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4149 /* Okay -- probably call waiting*/
4150 if (ast_bridged_channel(p->owner))
4151 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4152 p->subs[index].needunhold = 1;
4153 break;
4154 case AST_STATE_RESERVED:
4155 /* Start up dialtone */
4156 if (has_voicemail(p))
4157 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4158 else
4159 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4160 break;
4161 default:
4162 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4164 break;
4165 case SIG_FXSLS:
4166 case SIG_FXSGS:
4167 case SIG_FXSKS:
4168 if (ast->_state == AST_STATE_RING) {
4169 p->ringt = p->ringt_base;
4172 /* Fall through */
4173 case SIG_EM:
4174 case SIG_EM_E1:
4175 case SIG_EMWINK:
4176 case SIG_FEATD:
4177 case SIG_FEATDMF:
4178 case SIG_FEATDMF_TA:
4179 case SIG_E911:
4180 case SIG_FGC_CAMA:
4181 case SIG_FGC_CAMAMF:
4182 case SIG_FEATB:
4183 case SIG_SF:
4184 case SIG_SFWINK:
4185 case SIG_SF_FEATD:
4186 case SIG_SF_FEATDMF:
4187 case SIG_SF_FEATB:
4188 if (ast->_state == AST_STATE_PRERING)
4189 ast_setstate(ast, AST_STATE_RING);
4190 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4191 if (option_debug)
4192 ast_log(LOG_DEBUG, "Ring detected\n");
4193 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4194 p->subs[index].f.subclass = AST_CONTROL_RING;
4195 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4196 if (option_debug)
4197 ast_log(LOG_DEBUG, "Line answered\n");
4198 if (p->confirmanswer) {
4199 p->subs[index].f.frametype = AST_FRAME_NULL;
4200 p->subs[index].f.subclass = 0;
4201 } else {
4202 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4203 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4204 ast_setstate(ast, AST_STATE_UP);
4206 } else if (ast->_state != AST_STATE_RING)
4207 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4208 break;
4209 default:
4210 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4212 break;
4213 #ifdef DAHDI_EVENT_RINGBEGIN
4214 case DAHDI_EVENT_RINGBEGIN:
4215 switch (p->sig) {
4216 case SIG_FXSLS:
4217 case SIG_FXSGS:
4218 case SIG_FXSKS:
4219 if (ast->_state == AST_STATE_RING) {
4220 p->ringt = p->ringt_base;
4222 break;
4224 break;
4225 #endif
4226 case DAHDI_EVENT_RINGEROFF:
4227 if (p->inalarm) break;
4228 if ((p->radio || (p->oprmode < 0))) break;
4229 ast->rings++;
4230 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4231 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4232 free(p->cidspill);
4233 p->cidspill = NULL;
4234 p->callwaitcas = 0;
4236 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4237 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4238 break;
4239 case DAHDI_EVENT_RINGERON:
4240 break;
4241 case DAHDI_EVENT_NOALARM:
4242 p->inalarm = 0;
4243 #ifdef HAVE_PRI
4244 /* Extremely unlikely but just in case */
4245 if (p->bearer)
4246 p->bearer->inalarm = 0;
4247 #endif
4248 if (!p->unknown_alarm) {
4249 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4250 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4251 "Channel: %d\r\n", p->channel);
4252 } else {
4253 p->unknown_alarm = 0;
4255 break;
4256 case DAHDI_EVENT_WINKFLASH:
4257 if (p->inalarm) break;
4258 if (p->radio) break;
4259 if (p->oprmode < 0) break;
4260 if (p->oprmode > 1)
4262 struct dahdi_params par;
4264 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4266 if (!par.rxisoffhook)
4268 /* Make sure it stops ringing */
4269 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4270 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4271 save_conference(p);
4272 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4275 break;
4277 /* Remember last time we got a flash-hook */
4278 gettimeofday(&p->flashtime, NULL);
4279 switch (mysig) {
4280 case SIG_FXOLS:
4281 case SIG_FXOGS:
4282 case SIG_FXOKS:
4283 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4284 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4285 p->callwaitcas = 0;
4287 if (index != SUB_REAL) {
4288 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4289 goto winkflashdone;
4292 if (p->subs[SUB_CALLWAIT].owner) {
4293 /* Swap to call-wait */
4294 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4295 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4296 p->owner = p->subs[SUB_REAL].owner;
4297 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4298 if (p->owner->_state == AST_STATE_RINGING) {
4299 ast_setstate(p->owner, AST_STATE_UP);
4300 p->subs[SUB_REAL].needanswer = 1;
4302 p->callwaitingrepeat = 0;
4303 p->cidcwexpire = 0;
4304 /* Start music on hold if appropriate */
4305 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4306 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4307 S_OR(p->mohsuggest, NULL),
4308 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4310 p->subs[SUB_CALLWAIT].needhold = 1;
4311 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4312 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4313 S_OR(p->mohsuggest, NULL),
4314 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4316 p->subs[SUB_REAL].needunhold = 1;
4317 } else if (!p->subs[SUB_THREEWAY].owner) {
4318 char cid_num[256];
4319 char cid_name[256];
4321 if (!p->threewaycalling) {
4322 /* Just send a flash if no 3-way calling */
4323 p->subs[SUB_REAL].needflash = 1;
4324 goto winkflashdone;
4325 } else if (!check_for_conference(p)) {
4326 if (p->dahditrcallerid && p->owner) {
4327 if (p->owner->cid.cid_num)
4328 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4329 if (p->owner->cid.cid_name)
4330 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4332 /* XXX This section needs much more error checking!!! XXX */
4333 /* Start a 3-way call if feasible */
4334 if (!((ast->pbx) ||
4335 (ast->_state == AST_STATE_UP) ||
4336 (ast->_state == AST_STATE_RING))) {
4337 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4338 goto winkflashdone;
4340 if (alloc_sub(p, SUB_THREEWAY)) {
4341 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4342 goto winkflashdone;
4344 /* Make new channel */
4345 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4346 if (p->dahditrcallerid) {
4347 if (!p->origcid_num)
4348 p->origcid_num = ast_strdup(p->cid_num);
4349 if (!p->origcid_name)
4350 p->origcid_name = ast_strdup(p->cid_name);
4351 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4352 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4354 /* Swap things around between the three-way and real call */
4355 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4356 /* Disable echo canceller for better dialing */
4357 dahdi_disable_ec(p);
4358 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4359 if (res)
4360 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4361 p->owner = chan;
4362 pthread_attr_init(&attr);
4363 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4364 if (!chan) {
4365 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4366 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4367 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4368 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4369 dahdi_enable_ec(p);
4370 ast_hangup(chan);
4371 } else {
4372 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4373 int way3bridge = 0, cdr3way = 0;
4375 if (!other) {
4376 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4377 } else
4378 way3bridge = 1;
4380 if (p->subs[SUB_THREEWAY].owner->cdr)
4381 cdr3way = 1;
4383 if (option_verbose > 2)
4384 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4385 /* Start music on hold if appropriate */
4386 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4387 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4388 S_OR(p->mohsuggest, NULL),
4389 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4391 p->subs[SUB_THREEWAY].needhold = 1;
4393 pthread_attr_destroy(&attr);
4395 } else {
4396 /* Already have a 3 way call */
4397 if (p->subs[SUB_THREEWAY].inthreeway) {
4398 /* Call is already up, drop the last person */
4399 if (option_debug)
4400 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4401 /* If the primary call isn't answered yet, use it */
4402 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4403 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4404 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4405 p->owner = p->subs[SUB_REAL].owner;
4407 /* Drop the last call and stop the conference */
4408 if (option_verbose > 2)
4409 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4410 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4411 p->subs[SUB_REAL].inthreeway = 0;
4412 p->subs[SUB_THREEWAY].inthreeway = 0;
4413 } else {
4414 /* Lets see what we're up to */
4415 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4416 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4417 int otherindex = SUB_THREEWAY;
4418 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4419 int way3bridge = 0, cdr3way = 0;
4421 if (!other) {
4422 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4423 } else
4424 way3bridge = 1;
4426 if (p->subs[SUB_THREEWAY].owner->cdr)
4427 cdr3way = 1;
4429 if (option_verbose > 2)
4430 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);
4431 /* Put them in the threeway, and flip */
4432 p->subs[SUB_THREEWAY].inthreeway = 1;
4433 p->subs[SUB_REAL].inthreeway = 1;
4434 if (ast->_state == AST_STATE_UP) {
4435 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4436 otherindex = SUB_REAL;
4438 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4439 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4440 p->subs[otherindex].needunhold = 1;
4441 p->owner = p->subs[SUB_REAL].owner;
4442 if (ast->_state == AST_STATE_RINGING) {
4443 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4444 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4445 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4447 } else {
4448 if (option_verbose > 2)
4449 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4450 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4451 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4452 p->owner = p->subs[SUB_REAL].owner;
4453 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4454 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4455 p->subs[SUB_REAL].needunhold = 1;
4456 dahdi_enable_ec(p);
4461 winkflashdone:
4462 update_conf(p);
4463 break;
4464 case SIG_EM:
4465 case SIG_EM_E1:
4466 case SIG_EMWINK:
4467 case SIG_FEATD:
4468 case SIG_SF:
4469 case SIG_SFWINK:
4470 case SIG_SF_FEATD:
4471 case SIG_FXSLS:
4472 case SIG_FXSGS:
4473 if (p->dialing)
4474 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4475 else
4476 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4477 break;
4478 case SIG_FEATDMF_TA:
4479 switch (p->whichwink) {
4480 case 0:
4481 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4482 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4483 break;
4484 case 1:
4485 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4486 break;
4487 case 2:
4488 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4489 return NULL;
4491 p->whichwink++;
4492 /* Fall through */
4493 case SIG_FEATDMF:
4494 case SIG_E911:
4495 case SIG_FGC_CAMAMF:
4496 case SIG_FGC_CAMA:
4497 case SIG_FEATB:
4498 case SIG_SF_FEATDMF:
4499 case SIG_SF_FEATB:
4500 /* FGD MF *Must* wait for wink */
4501 if (!ast_strlen_zero(p->dop.dialstr)) {
4502 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4503 if (res < 0) {
4504 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4505 p->dop.dialstr[0] = '\0';
4506 return NULL;
4507 } else
4508 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4510 p->dop.dialstr[0] = '\0';
4511 break;
4512 default:
4513 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4515 break;
4516 case DAHDI_EVENT_HOOKCOMPLETE:
4517 if (p->inalarm) break;
4518 if ((p->radio || (p->oprmode < 0))) break;
4519 switch (mysig) {
4520 case SIG_FXSLS: /* only interesting for FXS */
4521 case SIG_FXSGS:
4522 case SIG_FXSKS:
4523 case SIG_EM:
4524 case SIG_EM_E1:
4525 case SIG_EMWINK:
4526 case SIG_FEATD:
4527 case SIG_SF:
4528 case SIG_SFWINK:
4529 case SIG_SF_FEATD:
4530 if (!ast_strlen_zero(p->dop.dialstr)) {
4531 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4532 if (res < 0) {
4533 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4534 p->dop.dialstr[0] = '\0';
4535 return NULL;
4536 } else
4537 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4539 p->dop.dialstr[0] = '\0';
4540 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4541 break;
4542 case SIG_FEATDMF:
4543 case SIG_FEATDMF_TA:
4544 case SIG_E911:
4545 case SIG_FGC_CAMA:
4546 case SIG_FGC_CAMAMF:
4547 case SIG_FEATB:
4548 case SIG_SF_FEATDMF:
4549 case SIG_SF_FEATB:
4550 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4551 break;
4552 default:
4553 break;
4555 break;
4556 case DAHDI_EVENT_POLARITY:
4558 * If we get a Polarity Switch event, check to see
4559 * if we should change the polarity state and
4560 * mark the channel as UP or if this is an indication
4561 * of remote end disconnect.
4563 if (p->polarity == POLARITY_IDLE) {
4564 p->polarity = POLARITY_REV;
4565 if (p->answeronpolarityswitch &&
4566 ((ast->_state == AST_STATE_DIALING) ||
4567 (ast->_state == AST_STATE_RINGING))) {
4568 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4569 ast_setstate(p->owner, AST_STATE_UP);
4570 if (p->hanguponpolarityswitch) {
4571 gettimeofday(&p->polaritydelaytv, NULL);
4573 } else
4574 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4576 /* Removed else statement from here as it was preventing hangups from ever happening*/
4577 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4578 if (p->hanguponpolarityswitch &&
4579 (p->polarityonanswerdelay > 0) &&
4580 (p->polarity == POLARITY_REV) &&
4581 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4582 /* Added log_debug information below to provide a better indication of what is going on */
4583 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) );
4585 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4586 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4587 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4588 p->polarity = POLARITY_IDLE;
4589 } else {
4590 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);
4592 } else {
4593 p->polarity = POLARITY_IDLE;
4594 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4596 /* Added more log_debug information below to provide a better indication of what is going on */
4597 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) );
4598 break;
4599 default:
4600 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4602 return &p->subs[index].f;
4605 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4607 struct dahdi_pvt *p = ast->tech_pvt;
4608 int res;
4609 int usedindex=-1;
4610 int index;
4611 struct ast_frame *f;
4614 index = dahdi_get_index(ast, p, 1);
4616 p->subs[index].f.frametype = AST_FRAME_NULL;
4617 p->subs[index].f.datalen = 0;
4618 p->subs[index].f.samples = 0;
4619 p->subs[index].f.mallocd = 0;
4620 p->subs[index].f.offset = 0;
4621 p->subs[index].f.subclass = 0;
4622 p->subs[index].f.delivery = ast_tv(0,0);
4623 p->subs[index].f.src = "dahdi_exception";
4624 p->subs[index].f.data = NULL;
4627 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4628 /* If nobody owns us, absorb the event appropriately, otherwise
4629 we loop indefinitely. This occurs when, during call waiting, the
4630 other end hangs up our channel so that it no longer exists, but we
4631 have neither FLASH'd nor ONHOOK'd to signify our desire to
4632 change to the other channel. */
4633 if (p->fake_event) {
4634 res = p->fake_event;
4635 p->fake_event = 0;
4636 } else
4637 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4638 /* Switch to real if there is one and this isn't something really silly... */
4639 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4640 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4641 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4642 p->owner = p->subs[SUB_REAL].owner;
4643 if (p->owner && ast_bridged_channel(p->owner))
4644 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4645 p->subs[SUB_REAL].needunhold = 1;
4647 switch (res) {
4648 case DAHDI_EVENT_ONHOOK:
4649 dahdi_disable_ec(p);
4650 if (p->owner) {
4651 if (option_verbose > 2)
4652 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4653 dahdi_ring_phone(p);
4654 p->callwaitingrepeat = 0;
4655 p->cidcwexpire = 0;
4656 } else
4657 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4658 update_conf(p);
4659 break;
4660 case DAHDI_EVENT_RINGOFFHOOK:
4661 dahdi_enable_ec(p);
4662 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4663 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4664 p->subs[SUB_REAL].needanswer = 1;
4665 p->dialing = 0;
4667 break;
4668 case DAHDI_EVENT_HOOKCOMPLETE:
4669 case DAHDI_EVENT_RINGERON:
4670 case DAHDI_EVENT_RINGEROFF:
4671 /* Do nothing */
4672 break;
4673 case DAHDI_EVENT_WINKFLASH:
4674 gettimeofday(&p->flashtime, NULL);
4675 if (p->owner) {
4676 if (option_verbose > 2)
4677 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4678 if (p->owner->_state != AST_STATE_UP) {
4679 /* Answer if necessary */
4680 usedindex = dahdi_get_index(p->owner, p, 0);
4681 if (usedindex > -1) {
4682 p->subs[usedindex].needanswer = 1;
4684 ast_setstate(p->owner, AST_STATE_UP);
4686 p->callwaitingrepeat = 0;
4687 p->cidcwexpire = 0;
4688 if (ast_bridged_channel(p->owner))
4689 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4690 p->subs[SUB_REAL].needunhold = 1;
4691 } else
4692 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4693 update_conf(p);
4694 break;
4695 default:
4696 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4698 f = &p->subs[index].f;
4699 return f;
4701 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4702 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4703 /* If it's not us, return NULL immediately */
4704 if (ast != p->owner) {
4705 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4706 f = &p->subs[index].f;
4707 return f;
4709 f = dahdi_handle_event(ast);
4710 return f;
4713 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4715 struct dahdi_pvt *p = ast->tech_pvt;
4716 struct ast_frame *f;
4717 ast_mutex_lock(&p->lock);
4718 f = __dahdi_exception(ast);
4719 ast_mutex_unlock(&p->lock);
4720 return f;
4723 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4725 struct dahdi_pvt *p = ast->tech_pvt;
4726 int res;
4727 int index;
4728 void *readbuf;
4729 struct ast_frame *f;
4731 while (ast_mutex_trylock(&p->lock)) {
4732 DEADLOCK_AVOIDANCE(&ast->lock);
4735 index = dahdi_get_index(ast, p, 0);
4737 /* Hang up if we don't really exist */
4738 if (index < 0) {
4739 ast_log(LOG_WARNING, "We dont exist?\n");
4740 ast_mutex_unlock(&p->lock);
4741 return NULL;
4744 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4746 p->subs[index].f.frametype = AST_FRAME_NULL;
4747 p->subs[index].f.datalen = 0;
4748 p->subs[index].f.samples = 0;
4749 p->subs[index].f.mallocd = 0;
4750 p->subs[index].f.offset = 0;
4751 p->subs[index].f.subclass = 0;
4752 p->subs[index].f.delivery = ast_tv(0,0);
4753 p->subs[index].f.src = "dahdi_read";
4754 p->subs[index].f.data = NULL;
4756 /* make sure it sends initial key state as first frame */
4757 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4759 struct dahdi_params ps;
4761 ps.channo = p->channel;
4762 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4763 ast_mutex_unlock(&p->lock);
4764 return NULL;
4766 p->firstradio = 1;
4767 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4768 if (ps.rxisoffhook)
4770 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4772 else
4774 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4776 ast_mutex_unlock(&p->lock);
4777 return &p->subs[index].f;
4779 if (p->ringt == 1) {
4780 ast_mutex_unlock(&p->lock);
4781 return NULL;
4783 else if (p->ringt > 0)
4784 p->ringt--;
4786 if (p->subs[index].needringing) {
4787 /* Send ringing frame if requested */
4788 p->subs[index].needringing = 0;
4789 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4790 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4791 ast_setstate(ast, AST_STATE_RINGING);
4792 ast_mutex_unlock(&p->lock);
4793 return &p->subs[index].f;
4796 if (p->subs[index].needbusy) {
4797 /* Send busy frame if requested */
4798 p->subs[index].needbusy = 0;
4799 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4800 p->subs[index].f.subclass = AST_CONTROL_BUSY;
4801 ast_mutex_unlock(&p->lock);
4802 return &p->subs[index].f;
4805 if (p->subs[index].needcongestion) {
4806 /* Send congestion frame if requested */
4807 p->subs[index].needcongestion = 0;
4808 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4809 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
4810 ast_mutex_unlock(&p->lock);
4811 return &p->subs[index].f;
4814 if (p->subs[index].needcallerid) {
4815 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
4816 S_OR(p->lastcid_name, NULL),
4817 S_OR(p->lastcid_num, NULL)
4819 p->subs[index].needcallerid = 0;
4822 if (p->subs[index].needanswer) {
4823 /* Send answer frame if requested */
4824 p->subs[index].needanswer = 0;
4825 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4826 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4827 ast_mutex_unlock(&p->lock);
4828 return &p->subs[index].f;
4831 if (p->subs[index].needflash) {
4832 /* Send answer frame if requested */
4833 p->subs[index].needflash = 0;
4834 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4835 p->subs[index].f.subclass = AST_CONTROL_FLASH;
4836 ast_mutex_unlock(&p->lock);
4837 return &p->subs[index].f;
4840 if (p->subs[index].needhold) {
4841 /* Send answer frame if requested */
4842 p->subs[index].needhold = 0;
4843 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4844 p->subs[index].f.subclass = AST_CONTROL_HOLD;
4845 ast_mutex_unlock(&p->lock);
4846 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
4847 return &p->subs[index].f;
4850 if (p->subs[index].needunhold) {
4851 /* Send answer frame if requested */
4852 p->subs[index].needunhold = 0;
4853 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4854 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
4855 ast_mutex_unlock(&p->lock);
4856 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
4857 return &p->subs[index].f;
4860 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
4861 if (!p->subs[index].linear) {
4862 p->subs[index].linear = 1;
4863 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4864 if (res)
4865 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
4867 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
4868 (ast->rawreadformat == AST_FORMAT_ALAW)) {
4869 if (p->subs[index].linear) {
4870 p->subs[index].linear = 0;
4871 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4872 if (res)
4873 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
4875 } else {
4876 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
4877 ast_mutex_unlock(&p->lock);
4878 return NULL;
4880 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
4881 CHECK_BLOCKING(ast);
4882 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4883 ast_clear_flag(ast, AST_FLAG_BLOCKING);
4884 /* Check for hangup */
4885 if (res < 0) {
4886 f = NULL;
4887 if (res == -1) {
4888 if (errno == EAGAIN) {
4889 /* Return "NULL" frame if there is nobody there */
4890 ast_mutex_unlock(&p->lock);
4891 return &p->subs[index].f;
4892 } else if (errno == ELAST) {
4893 f = __dahdi_exception(ast);
4894 } else
4895 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
4897 ast_mutex_unlock(&p->lock);
4898 return f;
4900 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
4901 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4902 f = __dahdi_exception(ast);
4903 ast_mutex_unlock(&p->lock);
4904 return f;
4906 if (p->tdd) { /* if in TDD mode, see if we receive that */
4907 int c;
4909 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
4910 if (c < 0) {
4911 ast_log(LOG_DEBUG,"tdd_feed failed\n");
4912 ast_mutex_unlock(&p->lock);
4913 return NULL;
4915 if (c) { /* if a char to return */
4916 p->subs[index].f.subclass = 0;
4917 p->subs[index].f.frametype = AST_FRAME_TEXT;
4918 p->subs[index].f.mallocd = 0;
4919 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4920 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
4921 p->subs[index].f.datalen = 1;
4922 *((char *) p->subs[index].f.data) = c;
4923 ast_mutex_unlock(&p->lock);
4924 return &p->subs[index].f;
4927 /* Ensure the CW timer decrements only on a single subchannel */
4928 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
4929 p->callwaitingrepeat--;
4931 if (p->cidcwexpire)
4932 p->cidcwexpire--;
4933 /* Repeat callwaiting */
4934 if (p->callwaitingrepeat == 1) {
4935 p->callwaitrings++;
4936 dahdi_callwait(ast);
4938 /* Expire CID/CW */
4939 if (p->cidcwexpire == 1) {
4940 if (option_verbose > 2)
4941 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
4942 restore_conference(p);
4944 if (p->subs[index].linear) {
4945 p->subs[index].f.datalen = READ_SIZE * 2;
4946 } else
4947 p->subs[index].f.datalen = READ_SIZE;
4949 /* Handle CallerID Transmission */
4950 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
4951 send_callerid(p);
4954 p->subs[index].f.frametype = AST_FRAME_VOICE;
4955 p->subs[index].f.subclass = ast->rawreadformat;
4956 p->subs[index].f.samples = READ_SIZE;
4957 p->subs[index].f.mallocd = 0;
4958 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4959 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
4960 #if 0
4961 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
4962 #endif
4963 if (p->dialing || /* Transmitting something */
4964 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
4965 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
4967 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4968 don't send anything */
4969 p->subs[index].f.frametype = AST_FRAME_NULL;
4970 p->subs[index].f.subclass = 0;
4971 p->subs[index].f.samples = 0;
4972 p->subs[index].f.mallocd = 0;
4973 p->subs[index].f.offset = 0;
4974 p->subs[index].f.data = NULL;
4975 p->subs[index].f.datalen= 0;
4977 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
4978 /* Perform busy detection. etc on the dahdi line */
4979 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
4980 if (f) {
4981 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
4982 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
4983 /* Treat this as a "hangup" instead of a "busy" on the assumption that
4984 a busy */
4985 f = NULL;
4987 } else if (f->frametype == AST_FRAME_DTMF) {
4988 #ifdef HAVE_PRI
4989 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
4990 /* Don't accept in-band DTMF when in overlap dial mode */
4991 f->frametype = AST_FRAME_NULL;
4992 f->subclass = 0;
4994 #endif
4995 /* DSP clears us of being pulse */
4996 p->pulsedial = 0;
4999 } else
5000 f = &p->subs[index].f;
5002 if (f && (f->frametype == AST_FRAME_DTMF))
5003 dahdi_handle_dtmfup(ast, index, &f);
5005 /* If we have a fake_event, trigger exception to handle it */
5006 if (p->fake_event)
5007 ast_set_flag(ast, AST_FLAG_EXCEPTION);
5009 ast_mutex_unlock(&p->lock);
5010 return f;
5013 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
5015 int sent=0;
5016 int size;
5017 int res;
5018 int fd;
5019 fd = p->subs[index].dfd;
5020 while (len) {
5021 size = len;
5022 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
5023 size = (linear ? READ_SIZE * 2 : READ_SIZE);
5024 res = write(fd, buf, size);
5025 if (res != size) {
5026 if (option_debug)
5027 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
5028 return sent;
5030 len -= size;
5031 buf += size;
5033 return sent;
5036 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
5038 struct dahdi_pvt *p = ast->tech_pvt;
5039 int res;
5040 int index;
5041 index = dahdi_get_index(ast, p, 0);
5042 if (index < 0) {
5043 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
5044 return -1;
5047 #if 0
5048 #ifdef HAVE_PRI
5049 ast_mutex_lock(&p->lock);
5050 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5051 if (p->pri->pri) {
5052 if (!pri_grab(p, p->pri)) {
5053 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5054 pri_rel(p->pri);
5055 } else
5056 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5058 p->proceeding=1;
5060 ast_mutex_unlock(&p->lock);
5061 #endif
5062 #endif
5063 /* Write a frame of (presumably voice) data */
5064 if (frame->frametype != AST_FRAME_VOICE) {
5065 if (frame->frametype != AST_FRAME_IMAGE)
5066 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
5067 return 0;
5069 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
5070 (frame->subclass != AST_FORMAT_ULAW) &&
5071 (frame->subclass != AST_FORMAT_ALAW)) {
5072 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
5073 return -1;
5075 if (p->dialing) {
5076 if (option_debug)
5077 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
5078 return 0;
5080 if (!p->owner) {
5081 if (option_debug)
5082 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
5083 return 0;
5085 if (p->cidspill) {
5086 if (option_debug)
5087 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5088 return 0;
5090 /* Return if it's not valid data */
5091 if (!frame->data || !frame->datalen)
5092 return 0;
5094 if (frame->subclass == AST_FORMAT_SLINEAR) {
5095 if (!p->subs[index].linear) {
5096 p->subs[index].linear = 1;
5097 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5098 if (res)
5099 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5101 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5102 } else {
5103 /* x-law already */
5104 if (p->subs[index].linear) {
5105 p->subs[index].linear = 0;
5106 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5107 if (res)
5108 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5110 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5112 if (res < 0) {
5113 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5114 return -1;
5116 return 0;
5119 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5121 struct dahdi_pvt *p = chan->tech_pvt;
5122 int res=-1;
5123 int index;
5124 int func = DAHDI_FLASH;
5125 ast_mutex_lock(&p->lock);
5126 index = dahdi_get_index(chan, p, 0);
5127 if (option_debug)
5128 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5129 if (index == SUB_REAL) {
5130 switch (condition) {
5131 case AST_CONTROL_BUSY:
5132 #ifdef HAVE_PRI
5133 if (p->priindication_oob && p->sig == SIG_PRI) {
5134 chan->hangupcause = AST_CAUSE_USER_BUSY;
5135 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5136 res = 0;
5137 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5138 if (p->pri->pri) {
5139 if (!pri_grab(p, p->pri)) {
5140 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5141 pri_rel(p->pri);
5143 else
5144 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5146 p->progress = 1;
5147 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5148 } else
5149 #endif
5150 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5151 break;
5152 case AST_CONTROL_RINGING:
5153 #ifdef HAVE_PRI
5154 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5155 if (p->pri->pri) {
5156 if (!pri_grab(p, p->pri)) {
5157 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5158 pri_rel(p->pri);
5160 else
5161 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5163 p->alerting = 1;
5165 #endif
5166 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5167 if (chan->_state != AST_STATE_UP) {
5168 if ((chan->_state != AST_STATE_RING) ||
5169 ((p->sig != SIG_FXSKS) &&
5170 (p->sig != SIG_FXSLS) &&
5171 (p->sig != SIG_FXSGS)))
5172 ast_setstate(chan, AST_STATE_RINGING);
5174 break;
5175 case AST_CONTROL_PROCEEDING:
5176 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5177 #ifdef HAVE_PRI
5178 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5179 if (p->pri->pri) {
5180 if (!pri_grab(p, p->pri)) {
5181 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5182 pri_rel(p->pri);
5184 else
5185 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5187 p->proceeding = 1;
5189 #endif
5190 /* don't continue in ast_indicate */
5191 res = 0;
5192 break;
5193 case AST_CONTROL_PROGRESS:
5194 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5195 #ifdef HAVE_PRI
5196 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5197 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5198 if (p->pri->pri) {
5199 if (!pri_grab(p, p->pri)) {
5200 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5201 pri_rel(p->pri);
5203 else
5204 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5206 p->progress = 1;
5208 #endif
5209 /* don't continue in ast_indicate */
5210 res = 0;
5211 break;
5212 case AST_CONTROL_CONGESTION:
5213 chan->hangupcause = AST_CAUSE_CONGESTION;
5214 #ifdef HAVE_PRI
5215 if (p->priindication_oob && p->sig == SIG_PRI) {
5216 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5217 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5218 res = 0;
5219 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5220 if (p->pri) {
5221 if (!pri_grab(p, p->pri)) {
5222 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5223 pri_rel(p->pri);
5224 } else
5225 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5227 p->progress = 1;
5228 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5229 } else
5230 #endif
5231 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5232 break;
5233 case AST_CONTROL_HOLD:
5234 #ifdef HAVE_PRI
5235 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5236 if (!pri_grab(p, p->pri)) {
5237 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5238 pri_rel(p->pri);
5239 } else
5240 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5241 } else
5242 #endif
5243 ast_moh_start(chan, data, p->mohinterpret);
5244 break;
5245 case AST_CONTROL_UNHOLD:
5246 #ifdef HAVE_PRI
5247 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5248 if (!pri_grab(p, p->pri)) {
5249 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5250 pri_rel(p->pri);
5251 } else
5252 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5253 } else
5254 #endif
5255 ast_moh_stop(chan);
5256 break;
5257 case AST_CONTROL_RADIO_KEY:
5258 if (p->radio)
5259 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5260 res = 0;
5261 break;
5262 case AST_CONTROL_RADIO_UNKEY:
5263 if (p->radio)
5264 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5265 res = 0;
5266 break;
5267 case AST_CONTROL_FLASH:
5268 /* flash hookswitch */
5269 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5270 /* Clear out the dial buffer */
5271 p->dop.dialstr[0] = '\0';
5272 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5273 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5274 chan->name, strerror(errno));
5275 } else
5276 res = 0;
5277 } else
5278 res = 0;
5279 break;
5280 case AST_CONTROL_SRCUPDATE:
5281 res = 0;
5282 break;
5283 case -1:
5284 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5285 break;
5287 } else
5288 res = 0;
5289 ast_mutex_unlock(&p->lock);
5290 return res;
5293 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5295 struct ast_channel *tmp;
5296 int deflaw;
5297 int res;
5298 int x,y;
5299 int features;
5300 char *b2 = NULL;
5301 struct dahdi_params ps;
5302 char chanprefix[*dahdi_chan_name_len + 4];
5304 if (i->subs[index].owner) {
5305 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5306 return NULL;
5308 y = 1;
5309 do {
5310 if (b2)
5311 free(b2);
5312 #ifdef HAVE_PRI
5313 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5314 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5315 else
5316 #endif
5317 if (i->channel == CHAN_PSEUDO)
5318 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5319 else
5320 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5321 for (x = 0; x < 3; x++) {
5322 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
5323 break;
5325 y++;
5326 } while (x < 3);
5327 strcpy(chanprefix, dahdi_chan_name);
5328 strcat(chanprefix, "/%s");
5329 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
5330 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5331 free(b2);
5332 if (!tmp)
5333 return NULL;
5334 tmp->tech = chan_tech;
5335 ps.channo = i->channel;
5336 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5337 if (res) {
5338 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5339 ps.curlaw = DAHDI_LAW_MULAW;
5341 if (ps.curlaw == DAHDI_LAW_ALAW)
5342 deflaw = AST_FORMAT_ALAW;
5343 else
5344 deflaw = AST_FORMAT_ULAW;
5345 if (law) {
5346 if (law == DAHDI_LAW_ALAW)
5347 deflaw = AST_FORMAT_ALAW;
5348 else
5349 deflaw = AST_FORMAT_ULAW;
5351 tmp->fds[0] = i->subs[index].dfd;
5352 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5353 /* Start out assuming ulaw since it's smaller :) */
5354 tmp->rawreadformat = deflaw;
5355 tmp->readformat = deflaw;
5356 tmp->rawwriteformat = deflaw;
5357 tmp->writeformat = deflaw;
5358 i->subs[index].linear = 0;
5359 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5360 features = 0;
5361 if (index == SUB_REAL) {
5362 if (i->busydetect && CANBUSYDETECT(i))
5363 features |= DSP_FEATURE_BUSY_DETECT;
5364 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5365 features |= DSP_FEATURE_CALL_PROGRESS;
5366 if ((!i->outgoing && (i->callprogress & 4)) ||
5367 (i->outgoing && (i->callprogress & 2))) {
5368 features |= DSP_FEATURE_FAX_DETECT;
5370 #ifdef DAHDI_TONEDETECT
5371 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5372 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5373 #endif
5374 i->hardwaredtmf = 0;
5375 features |= DSP_FEATURE_DTMF_DETECT;
5376 #ifdef DAHDI_TONEDETECT
5377 } else if (NEED_MFDETECT(i)) {
5378 i->hardwaredtmf = 1;
5379 features |= DSP_FEATURE_DTMF_DETECT;
5381 #endif
5383 if (features) {
5384 if (i->dsp) {
5385 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5386 } else {
5387 if (i->channel != CHAN_PSEUDO)
5388 i->dsp = ast_dsp_new();
5389 else
5390 i->dsp = NULL;
5391 if (i->dsp) {
5392 i->dsp_features = features;
5393 #ifdef HAVE_PRI
5394 /* We cannot do progress detection until receives PROGRESS message */
5395 if (i->outgoing && (i->sig == SIG_PRI)) {
5396 /* Remember requested DSP features, don't treat
5397 talking as ANSWER */
5398 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5399 features = 0;
5401 #endif
5402 ast_dsp_set_features(i->dsp, features);
5403 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5404 if (!ast_strlen_zero(progzone))
5405 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5406 if (i->busydetect && CANBUSYDETECT(i)) {
5407 ast_dsp_set_busy_count(i->dsp, i->busycount);
5408 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5414 if (state == AST_STATE_RING)
5415 tmp->rings = 1;
5416 tmp->tech_pvt = i;
5417 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5418 /* Only FXO signalled stuff can be picked up */
5419 tmp->callgroup = i->callgroup;
5420 tmp->pickupgroup = i->pickupgroup;
5422 if (!ast_strlen_zero(i->language))
5423 ast_string_field_set(tmp, language, i->language);
5424 if (!i->owner)
5425 i->owner = tmp;
5426 if (!ast_strlen_zero(i->accountcode))
5427 ast_string_field_set(tmp, accountcode, i->accountcode);
5428 if (i->amaflags)
5429 tmp->amaflags = i->amaflags;
5430 i->subs[index].owner = tmp;
5431 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5432 ast_string_field_set(tmp, call_forward, i->call_forward);
5433 /* If we've been told "no ADSI" then enforce it */
5434 if (!i->adsi)
5435 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5436 if (!ast_strlen_zero(i->exten))
5437 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5438 if (!ast_strlen_zero(i->rdnis))
5439 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5440 if (!ast_strlen_zero(i->dnid))
5441 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5443 /* Don't use ast_set_callerid() here because it will
5444 * generate a needless NewCallerID event */
5445 #ifdef PRI_ANI
5446 if (!ast_strlen_zero(i->cid_ani))
5447 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5448 else
5449 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5450 #else
5451 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5452 #endif
5453 tmp->cid.cid_pres = i->callingpres;
5454 tmp->cid.cid_ton = i->cid_ton;
5455 #ifdef HAVE_PRI
5456 tmp->transfercapability = transfercapability;
5457 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5458 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5459 i->digital = 1;
5460 /* Assume calls are not idle calls unless we're told differently */
5461 i->isidlecall = 0;
5462 i->alreadyhungup = 0;
5463 #endif
5464 /* clear the fake event in case we posted one before we had ast_channel */
5465 i->fake_event = 0;
5466 /* Assure there is no confmute on this channel */
5467 dahdi_confmute(i, 0);
5468 /* Configure the new channel jb */
5469 ast_jb_configure(tmp, &global_jbconf);
5470 if (startpbx) {
5471 if (ast_pbx_start(tmp)) {
5472 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5473 ast_hangup(tmp);
5474 i->owner = NULL;
5475 return NULL;
5479 ast_module_ref(ast_module_info->self);
5481 return tmp;
5485 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5487 char c;
5489 *str = 0; /* start with empty output buffer */
5490 for (;;)
5492 /* Wait for the first digit (up to specified ms). */
5493 c = ast_waitfordigit(chan, ms);
5494 /* if timeout, hangup or error, return as such */
5495 if (c < 1)
5496 return c;
5497 *str++ = c;
5498 *str = 0;
5499 if (strchr(term, c))
5500 return 1;
5504 static int dahdi_wink(struct dahdi_pvt *p, int index)
5506 int j;
5507 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5508 for (;;)
5510 /* set bits of interest */
5511 j = DAHDI_IOMUX_SIGEVENT;
5512 /* wait for some happening */
5513 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5514 /* exit loop if we have it */
5515 if (j & DAHDI_IOMUX_SIGEVENT) break;
5517 /* get the event info */
5518 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5519 return 0;
5522 static void *ss_thread(void *data)
5524 struct ast_channel *chan = data;
5525 struct dahdi_pvt *p = chan->tech_pvt;
5526 char exten[AST_MAX_EXTENSION] = "";
5527 char exten2[AST_MAX_EXTENSION] = "";
5528 unsigned char buf[256];
5529 char dtmfcid[300];
5530 char dtmfbuf[300];
5531 struct callerid_state *cs = NULL;
5532 char *name = NULL, *number = NULL;
5533 int distMatches;
5534 int curRingData[3];
5535 int receivedRingT;
5536 int counter1;
5537 int counter;
5538 int samples = 0;
5539 struct ast_smdi_md_message *smdi_msg = NULL;
5540 int flags;
5541 int i;
5542 int timeout;
5543 int getforward = 0;
5544 char *s1, *s2;
5545 int len = 0;
5546 int res;
5547 int index;
5549 ss_thread_count++;
5550 /* in the bizarre case where the channel has become a zombie before we
5551 even get started here, abort safely
5553 if (!p) {
5554 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5555 ast_hangup(chan);
5556 goto quit;
5558 if (option_verbose > 2)
5559 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5560 index = dahdi_get_index(chan, p, 1);
5561 if (index < 0) {
5562 ast_log(LOG_WARNING, "Huh?\n");
5563 ast_hangup(chan);
5564 goto quit;
5566 if (p->dsp)
5567 ast_dsp_digitreset(p->dsp);
5568 switch (p->sig) {
5569 #ifdef HAVE_PRI
5570 case SIG_PRI:
5571 /* Now loop looking for an extension */
5572 ast_copy_string(exten, p->exten, sizeof(exten));
5573 len = strlen(exten);
5574 res = 0;
5575 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5576 if (len && !ast_ignore_pattern(chan->context, exten))
5577 tone_zone_play_tone(p->subs[index].dfd, -1);
5578 else
5579 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5580 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5581 timeout = matchdigittimeout;
5582 else
5583 timeout = gendigittimeout;
5584 res = ast_waitfordigit(chan, timeout);
5585 if (res < 0) {
5586 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5587 ast_hangup(chan);
5588 goto quit;
5589 } else if (res) {
5590 exten[len++] = res;
5591 exten[len] = '\0';
5592 } else
5593 break;
5595 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5596 if (ast_strlen_zero(exten)) {
5597 if (option_verbose > 2)
5598 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5599 exten[0] = 's';
5600 exten[1] = '\0';
5602 tone_zone_play_tone(p->subs[index].dfd, -1);
5603 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5604 /* Start the real PBX */
5605 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5606 if (p->dsp) ast_dsp_digitreset(p->dsp);
5607 dahdi_enable_ec(p);
5608 ast_setstate(chan, AST_STATE_RING);
5609 res = ast_pbx_run(chan);
5610 if (res) {
5611 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5613 } else {
5614 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5615 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5616 ast_hangup(chan);
5617 p->exten[0] = '\0';
5618 /* Since we send release complete here, we won't get one */
5619 p->call = NULL;
5621 goto quit;
5622 break;
5623 #endif
5624 case SIG_FEATD:
5625 case SIG_FEATDMF:
5626 case SIG_FEATDMF_TA:
5627 case SIG_E911:
5628 case SIG_FGC_CAMAMF:
5629 case SIG_FEATB:
5630 case SIG_EMWINK:
5631 case SIG_SF_FEATD:
5632 case SIG_SF_FEATDMF:
5633 case SIG_SF_FEATB:
5634 case SIG_SFWINK:
5635 if (dahdi_wink(p, index))
5636 goto quit;
5637 /* Fall through */
5638 case SIG_EM:
5639 case SIG_EM_E1:
5640 case SIG_SF:
5641 case SIG_FGC_CAMA:
5642 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5643 if (p->dsp)
5644 ast_dsp_digitreset(p->dsp);
5645 /* set digit mode appropriately */
5646 if (p->dsp) {
5647 if (NEED_MFDETECT(p))
5648 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5649 else
5650 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5652 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5653 /* Wait for the first digit only if immediate=no */
5654 if (!p->immediate)
5655 /* Wait for the first digit (up to 5 seconds). */
5656 res = ast_waitfordigit(chan, 5000);
5657 else
5658 res = 0;
5659 if (res > 0) {
5660 /* save first char */
5661 dtmfbuf[0] = res;
5662 switch (p->sig) {
5663 case SIG_FEATD:
5664 case SIG_SF_FEATD:
5665 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5666 if (res > 0)
5667 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5668 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5669 break;
5670 case SIG_FEATDMF_TA:
5671 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5672 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5673 if (dahdi_wink(p, index)) goto quit;
5674 dtmfbuf[0] = 0;
5675 /* Wait for the first digit (up to 5 seconds). */
5676 res = ast_waitfordigit(chan, 5000);
5677 if (res <= 0) break;
5678 dtmfbuf[0] = res;
5679 /* fall through intentionally */
5680 case SIG_FEATDMF:
5681 case SIG_E911:
5682 case SIG_FGC_CAMAMF:
5683 case SIG_SF_FEATDMF:
5684 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5685 /* if international caca, do it again to get real ANO */
5686 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5688 if (dahdi_wink(p, index)) goto quit;
5689 dtmfbuf[0] = 0;
5690 /* Wait for the first digit (up to 5 seconds). */
5691 res = ast_waitfordigit(chan, 5000);
5692 if (res <= 0) break;
5693 dtmfbuf[0] = res;
5694 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5696 if (res > 0) {
5697 /* if E911, take off hook */
5698 if (p->sig == SIG_E911)
5699 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5700 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5702 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5703 break;
5704 case SIG_FEATB:
5705 case SIG_SF_FEATB:
5706 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5707 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5708 break;
5709 case SIG_EMWINK:
5710 /* if we received a '*', we are actually receiving Feature Group D
5711 dial syntax, so use that mode; otherwise, fall through to normal
5712 mode
5714 if (res == '*') {
5715 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5716 if (res > 0)
5717 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5718 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5719 break;
5721 default:
5722 /* If we got the first digit, get the rest */
5723 len = 1;
5724 dtmfbuf[len] = '\0';
5725 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5726 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5727 timeout = matchdigittimeout;
5728 } else {
5729 timeout = gendigittimeout;
5731 res = ast_waitfordigit(chan, timeout);
5732 if (res < 0) {
5733 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5734 ast_hangup(chan);
5735 goto quit;
5736 } else if (res) {
5737 dtmfbuf[len++] = res;
5738 dtmfbuf[len] = '\0';
5739 } else {
5740 break;
5743 break;
5746 if (res == -1) {
5747 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5748 ast_hangup(chan);
5749 goto quit;
5750 } else if (res < 0) {
5751 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
5752 ast_hangup(chan);
5753 goto quit;
5756 if (p->sig == SIG_FGC_CAMA) {
5757 char anibuf[100];
5759 if (ast_safe_sleep(chan,1000) == -1) {
5760 ast_hangup(chan);
5761 goto quit;
5763 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5764 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5765 res = my_getsigstr(chan, anibuf, "#", 10000);
5766 if ((res > 0) && (strlen(anibuf) > 2)) {
5767 if (anibuf[strlen(anibuf) - 1] == '#')
5768 anibuf[strlen(anibuf) - 1] = 0;
5769 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
5771 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5774 ast_copy_string(exten, dtmfbuf, sizeof(exten));
5775 if (ast_strlen_zero(exten))
5776 ast_copy_string(exten, "s", sizeof(exten));
5777 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
5778 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5779 if (exten[0] == '*') {
5780 char *stringp=NULL;
5781 ast_copy_string(exten2, exten, sizeof(exten2));
5782 /* Parse out extension and callerid */
5783 stringp=exten2 +1;
5784 s1 = strsep(&stringp, "*");
5785 s2 = strsep(&stringp, "*");
5786 if (s2) {
5787 if (!ast_strlen_zero(p->cid_num))
5788 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5789 else
5790 ast_set_callerid(chan, s1, NULL, s1);
5791 ast_copy_string(exten, s2, sizeof(exten));
5792 } else
5793 ast_copy_string(exten, s1, sizeof(exten));
5794 } else if (p->sig == SIG_FEATD)
5795 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5797 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5798 if (exten[0] == '*') {
5799 char *stringp=NULL;
5800 ast_copy_string(exten2, exten, sizeof(exten2));
5801 /* Parse out extension and callerid */
5802 stringp=exten2 +1;
5803 s1 = strsep(&stringp, "#");
5804 s2 = strsep(&stringp, "#");
5805 if (s2) {
5806 if (!ast_strlen_zero(p->cid_num))
5807 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5808 else
5809 if (*(s1 + 2))
5810 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
5811 ast_copy_string(exten, s2 + 1, sizeof(exten));
5812 } else
5813 ast_copy_string(exten, s1 + 2, sizeof(exten));
5814 } else
5815 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5817 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
5818 if (exten[0] == '*') {
5819 char *stringp=NULL;
5820 ast_copy_string(exten2, exten, sizeof(exten2));
5821 /* Parse out extension and callerid */
5822 stringp=exten2 +1;
5823 s1 = strsep(&stringp, "#");
5824 s2 = strsep(&stringp, "#");
5825 if (s2 && (*(s2 + 1) == '0')) {
5826 if (*(s2 + 2))
5827 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
5829 if (s1) ast_copy_string(exten, s1, sizeof(exten));
5830 else ast_copy_string(exten, "911", sizeof(exten));
5831 } else
5832 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
5834 if (p->sig == SIG_FEATB) {
5835 if (exten[0] == '*') {
5836 char *stringp=NULL;
5837 ast_copy_string(exten2, exten, sizeof(exten2));
5838 /* Parse out extension and callerid */
5839 stringp=exten2 +1;
5840 s1 = strsep(&stringp, "#");
5841 ast_copy_string(exten, exten2 + 1, sizeof(exten));
5842 } else
5843 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
5845 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5846 dahdi_wink(p, index);
5847 /* some switches require a minimum guard time between
5848 the last FGD wink and something that answers
5849 immediately. This ensures it */
5850 if (ast_safe_sleep(chan,100)) goto quit;
5852 dahdi_enable_ec(p);
5853 if (NEED_MFDETECT(p)) {
5854 if (p->dsp) {
5855 if (!p->hardwaredtmf)
5856 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5857 else {
5858 ast_dsp_free(p->dsp);
5859 p->dsp = NULL;
5864 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
5865 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5866 if (p->dsp) ast_dsp_digitreset(p->dsp);
5867 res = ast_pbx_run(chan);
5868 if (res) {
5869 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5870 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5872 goto quit;
5873 } else {
5874 if (option_verbose > 2)
5875 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
5876 sleep(2);
5877 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
5878 if (res < 0)
5879 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
5880 else
5881 sleep(1);
5882 res = ast_streamfile(chan, "ss-noservice", chan->language);
5883 if (res >= 0)
5884 ast_waitstream(chan, "");
5885 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5886 ast_hangup(chan);
5887 goto quit;
5889 break;
5890 case SIG_FXOLS:
5891 case SIG_FXOGS:
5892 case SIG_FXOKS:
5893 /* Read the first digit */
5894 timeout = firstdigittimeout;
5895 /* If starting a threeway call, never timeout on the first digit so someone
5896 can use flash-hook as a "hold" feature */
5897 if (p->subs[SUB_THREEWAY].owner)
5898 timeout = 999999;
5899 while (len < AST_MAX_EXTENSION-1) {
5900 /* Read digit unless it's supposed to be immediate, in which case the
5901 only answer is 's' */
5902 if (p->immediate)
5903 res = 's';
5904 else
5905 res = ast_waitfordigit(chan, timeout);
5906 timeout = 0;
5907 if (res < 0) {
5908 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5909 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5910 ast_hangup(chan);
5911 goto quit;
5912 } else if (res) {
5913 exten[len++]=res;
5914 exten[len] = '\0';
5916 if (!ast_ignore_pattern(chan->context, exten))
5917 tone_zone_play_tone(p->subs[index].dfd, -1);
5918 else
5919 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5920 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
5921 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5922 if (getforward) {
5923 /* Record this as the forwarding extension */
5924 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
5925 if (option_verbose > 2)
5926 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
5927 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5928 if (res)
5929 break;
5930 usleep(500000);
5931 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5932 sleep(1);
5933 memset(exten, 0, sizeof(exten));
5934 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5935 len = 0;
5936 getforward = 0;
5937 } else {
5938 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5939 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5940 if (!ast_strlen_zero(p->cid_num)) {
5941 if (!p->hidecallerid)
5942 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5943 else
5944 ast_set_callerid(chan, NULL, NULL, p->cid_num);
5946 if (!ast_strlen_zero(p->cid_name)) {
5947 if (!p->hidecallerid)
5948 ast_set_callerid(chan, NULL, p->cid_name, NULL);
5950 ast_setstate(chan, AST_STATE_RING);
5951 dahdi_enable_ec(p);
5952 res = ast_pbx_run(chan);
5953 if (res) {
5954 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5955 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5957 goto quit;
5959 } else {
5960 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5961 so just set the timeout to matchdigittimeout and wait some more */
5962 timeout = matchdigittimeout;
5964 } else if (res == 0) {
5965 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
5966 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5967 dahdi_wait_event(p->subs[index].dfd);
5968 ast_hangup(chan);
5969 goto quit;
5970 } else if (p->callwaiting && !strcmp(exten, "*70")) {
5971 if (option_verbose > 2)
5972 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
5973 /* Disable call waiting if enabled */
5974 p->callwaiting = 0;
5975 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5976 if (res) {
5977 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
5978 chan->name, strerror(errno));
5980 len = 0;
5981 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
5982 memset(exten, 0, sizeof(exten));
5983 timeout = firstdigittimeout;
5985 } else if (!strcmp(exten,ast_pickup_ext())) {
5986 /* Scan all channels and see if there are any
5987 * ringing channels that have call groups
5988 * that equal this channels pickup group
5990 if (index == SUB_REAL) {
5991 /* Switch us from Third call to Call Wait */
5992 if (p->subs[SUB_THREEWAY].owner) {
5993 /* If you make a threeway call and the *8# a call, it should actually
5994 look like a callwait */
5995 alloc_sub(p, SUB_CALLWAIT);
5996 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
5997 unalloc_sub(p, SUB_THREEWAY);
5999 dahdi_enable_ec(p);
6000 if (ast_pickup_call(chan)) {
6001 ast_log(LOG_DEBUG, "No call pickup possible...\n");
6002 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6003 dahdi_wait_event(p->subs[index].dfd);
6005 ast_hangup(chan);
6006 goto quit;
6007 } else {
6008 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
6009 ast_hangup(chan);
6010 goto quit;
6013 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
6014 if (option_verbose > 2)
6015 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
6016 /* Disable Caller*ID if enabled */
6017 p->hidecallerid = 1;
6018 if (chan->cid.cid_num)
6019 free(chan->cid.cid_num);
6020 chan->cid.cid_num = NULL;
6021 if (chan->cid.cid_name)
6022 free(chan->cid.cid_name);
6023 chan->cid.cid_name = NULL;
6024 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6025 if (res) {
6026 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6027 chan->name, strerror(errno));
6029 len = 0;
6030 memset(exten, 0, sizeof(exten));
6031 timeout = firstdigittimeout;
6032 } else if (p->callreturn && !strcmp(exten, "*69")) {
6033 res = 0;
6034 if (!ast_strlen_zero(p->lastcid_num)) {
6035 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
6037 if (!res)
6038 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6039 break;
6040 } else if (!strcmp(exten, "*78")) {
6041 /* Do not disturb */
6042 if (option_verbose > 2)
6043 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
6044 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6045 "Channel: %s/%d\r\n"
6046 "Status: enabled\r\n", dahdi_chan_name, p->channel);
6047 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6048 p->dnd = 1;
6049 getforward = 0;
6050 memset(exten, 0, sizeof(exten));
6051 len = 0;
6052 } else if (!strcmp(exten, "*79")) {
6053 /* Do not disturb */
6054 if (option_verbose > 2)
6055 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
6056 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6057 "Channel: %s/%d\r\n"
6058 "Status: disabled\r\n", dahdi_chan_name, p->channel);
6059 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6060 p->dnd = 0;
6061 getforward = 0;
6062 memset(exten, 0, sizeof(exten));
6063 len = 0;
6064 } else if (p->cancallforward && !strcmp(exten, "*72")) {
6065 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6066 getforward = 1;
6067 memset(exten, 0, sizeof(exten));
6068 len = 0;
6069 } else if (p->cancallforward && !strcmp(exten, "*73")) {
6070 if (option_verbose > 2)
6071 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
6072 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6073 memset(p->call_forward, 0, sizeof(p->call_forward));
6074 getforward = 0;
6075 memset(exten, 0, sizeof(exten));
6076 len = 0;
6077 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
6078 p->subs[SUB_THREEWAY].owner &&
6079 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6080 /* This is a three way call, the main call being a real channel,
6081 and we're parking the first call. */
6082 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
6083 if (option_verbose > 2)
6084 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
6085 break;
6086 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
6087 if (option_verbose > 2)
6088 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
6089 res = ast_db_put("blacklist", p->lastcid_num, "1");
6090 if (!res) {
6091 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6092 memset(exten, 0, sizeof(exten));
6093 len = 0;
6095 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6096 if (option_verbose > 2)
6097 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6098 /* Enable Caller*ID if enabled */
6099 p->hidecallerid = 0;
6100 if (chan->cid.cid_num)
6101 free(chan->cid.cid_num);
6102 chan->cid.cid_num = NULL;
6103 if (chan->cid.cid_name)
6104 free(chan->cid.cid_name);
6105 chan->cid.cid_name = NULL;
6106 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6107 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6108 if (res) {
6109 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6110 chan->name, strerror(errno));
6112 len = 0;
6113 memset(exten, 0, sizeof(exten));
6114 timeout = firstdigittimeout;
6115 } else if (!strcmp(exten, "*0")) {
6116 struct ast_channel *nbridge =
6117 p->subs[SUB_THREEWAY].owner;
6118 struct dahdi_pvt *pbridge = NULL;
6119 /* set up the private struct of the bridged one, if any */
6120 if (nbridge && ast_bridged_channel(nbridge))
6121 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6122 if (nbridge && pbridge &&
6123 (nbridge->tech == chan_tech) &&
6124 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
6125 ISTRUNK(pbridge)) {
6126 int func = DAHDI_FLASH;
6127 /* Clear out the dial buffer */
6128 p->dop.dialstr[0] = '\0';
6129 /* flash hookswitch */
6130 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6131 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6132 nbridge->name, strerror(errno));
6134 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6135 unalloc_sub(p, SUB_THREEWAY);
6136 p->owner = p->subs[SUB_REAL].owner;
6137 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6138 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6139 ast_hangup(chan);
6140 goto quit;
6141 } else {
6142 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6143 dahdi_wait_event(p->subs[index].dfd);
6144 tone_zone_play_tone(p->subs[index].dfd, -1);
6145 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6146 unalloc_sub(p, SUB_THREEWAY);
6147 p->owner = p->subs[SUB_REAL].owner;
6148 ast_hangup(chan);
6149 goto quit;
6151 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6152 ((exten[0] != '*') || (strlen(exten) > 2))) {
6153 if (option_debug)
6154 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);
6155 break;
6157 if (!timeout)
6158 timeout = gendigittimeout;
6159 if (len && !ast_ignore_pattern(chan->context, exten))
6160 tone_zone_play_tone(p->subs[index].dfd, -1);
6162 break;
6163 case SIG_FXSLS:
6164 case SIG_FXSGS:
6165 case SIG_FXSKS:
6166 #ifdef HAVE_PRI
6167 if (p->pri) {
6168 /* This is a GR-303 trunk actually. Wait for the first ring... */
6169 struct ast_frame *f;
6170 int res;
6171 time_t start;
6173 time(&start);
6174 ast_setstate(chan, AST_STATE_RING);
6175 while (time(NULL) < start + 3) {
6176 res = ast_waitfor(chan, 1000);
6177 if (res) {
6178 f = ast_read(chan);
6179 if (!f) {
6180 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6181 ast_hangup(chan);
6182 goto quit;
6183 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6184 res = 1;
6185 } else
6186 res = 0;
6187 ast_frfree(f);
6188 if (res) {
6189 ast_log(LOG_DEBUG, "Got ring!\n");
6190 res = 0;
6191 break;
6196 #endif
6197 /* check for SMDI messages */
6198 if (p->use_smdi && p->smdi_iface) {
6199 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6201 if (smdi_msg != NULL) {
6202 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6204 if (smdi_msg->type == 'B')
6205 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6206 else if (smdi_msg->type == 'N')
6207 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6209 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6210 } else {
6211 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6215 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6216 number = smdi_msg->calling_st;
6218 /* If we want caller id, we're in a prering state due to a polarity reversal
6219 * and we're set to use a polarity reversal to trigger the start of caller id,
6220 * grab the caller id and wait for ringing to start... */
6221 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6222 /* If set to use DTMF CID signalling, listen for DTMF */
6223 if (p->cid_signalling == CID_SIG_DTMF) {
6224 int i = 0;
6225 cs = NULL;
6226 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6227 "channel %s\n", chan->name);
6228 dahdi_setlinear(p->subs[index].dfd, 0);
6229 res = 2000;
6230 for (;;) {
6231 struct ast_frame *f;
6232 res = ast_waitfor(chan, res);
6233 if (res <= 0) {
6234 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6235 "Exiting simple switch\n");
6236 ast_hangup(chan);
6237 goto quit;
6239 f = ast_read(chan);
6240 if (!f)
6241 break;
6242 if (f->frametype == AST_FRAME_DTMF) {
6243 dtmfbuf[i++] = f->subclass;
6244 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6245 res = 2000;
6247 ast_frfree(f);
6248 if (chan->_state == AST_STATE_RING ||
6249 chan->_state == AST_STATE_RINGING)
6250 break; /* Got ring */
6252 dtmfbuf[i] = '\0';
6253 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6254 /* Got cid and ring. */
6255 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6256 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6257 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6258 dtmfcid, flags);
6259 /* If first byte is NULL, we have no cid */
6260 if (!ast_strlen_zero(dtmfcid))
6261 number = dtmfcid;
6262 else
6263 number = NULL;
6264 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6265 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6266 cs = callerid_new(p->cid_signalling);
6267 if (cs) {
6268 samples = 0;
6269 #if 1
6270 bump_gains(p);
6271 #endif
6272 /* Take out of linear mode for Caller*ID processing */
6273 dahdi_setlinear(p->subs[index].dfd, 0);
6275 /* First we wait and listen for the Caller*ID */
6276 for (;;) {
6277 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6278 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6279 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6280 callerid_free(cs);
6281 ast_hangup(chan);
6282 goto quit;
6284 if (i & DAHDI_IOMUX_SIGEVENT) {
6285 res = dahdi_get_event(p->subs[index].dfd);
6286 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6288 if (p->cid_signalling == CID_SIG_V23_JP) {
6289 #ifdef DAHDI_EVENT_RINGBEGIN
6290 if (res == DAHDI_EVENT_RINGBEGIN) {
6291 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6292 usleep(1);
6294 #endif
6295 } else {
6296 res = 0;
6297 break;
6299 } else if (i & DAHDI_IOMUX_READ) {
6300 res = read(p->subs[index].dfd, buf, sizeof(buf));
6301 if (res < 0) {
6302 if (errno != ELAST) {
6303 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6304 callerid_free(cs);
6305 ast_hangup(chan);
6306 goto quit;
6308 break;
6310 samples += res;
6312 if (p->cid_signalling == CID_SIG_V23_JP) {
6313 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6314 } else {
6315 res = callerid_feed(cs, buf, res, AST_LAW(p));
6318 if (res < 0) {
6319 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6320 break;
6321 } else if (res)
6322 break;
6323 else if (samples > (8000 * 10))
6324 break;
6327 if (res == 1) {
6328 callerid_get(cs, &name, &number, &flags);
6329 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6332 if (p->cid_signalling == CID_SIG_V23_JP) {
6333 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6334 usleep(1);
6335 res = 4000;
6336 } else {
6338 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6339 res = 2000;
6342 for (;;) {
6343 struct ast_frame *f;
6344 res = ast_waitfor(chan, res);
6345 if (res <= 0) {
6346 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6347 "Exiting simple switch\n");
6348 ast_hangup(chan);
6349 goto quit;
6351 if (!(f = ast_read(chan))) {
6352 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6353 ast_hangup(chan);
6354 goto quit;
6356 ast_frfree(f);
6357 if (chan->_state == AST_STATE_RING ||
6358 chan->_state == AST_STATE_RINGING)
6359 break; /* Got ring */
6362 /* We must have a ring by now, so, if configured, lets try to listen for
6363 * distinctive ringing */
6364 if (p->usedistinctiveringdetection == 1) {
6365 len = 0;
6366 distMatches = 0;
6367 /* Clear the current ring data array so we dont have old data in it. */
6368 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6369 curRingData[receivedRingT] = 0;
6370 receivedRingT = 0;
6371 counter = 0;
6372 counter1 = 0;
6373 /* Check to see if context is what it should be, if not set to be. */
6374 if (strcmp(p->context,p->defcontext) != 0) {
6375 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6376 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6379 for (;;) {
6380 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6381 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6382 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6383 callerid_free(cs);
6384 ast_hangup(chan);
6385 goto quit;
6387 if (i & DAHDI_IOMUX_SIGEVENT) {
6388 res = dahdi_get_event(p->subs[index].dfd);
6389 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6390 res = 0;
6391 /* Let us detect distinctive ring */
6393 curRingData[receivedRingT] = p->ringt;
6395 if (p->ringt < p->ringt_base/2)
6396 break;
6397 /* Increment the ringT counter so we can match it against
6398 values in chan_dahdi.conf for distinctive ring */
6399 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6400 break;
6401 } else if (i & DAHDI_IOMUX_READ) {
6402 res = read(p->subs[index].dfd, buf, sizeof(buf));
6403 if (res < 0) {
6404 if (errno != ELAST) {
6405 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6406 callerid_free(cs);
6407 ast_hangup(chan);
6408 goto quit;
6410 break;
6412 if (p->ringt)
6413 p->ringt--;
6414 if (p->ringt == 1) {
6415 res = -1;
6416 break;
6420 if (option_verbose > 2)
6421 /* this only shows up if you have n of the dring patterns filled in */
6422 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6424 for (counter = 0; counter < 3; counter++) {
6425 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6426 channel */
6427 distMatches = 0;
6428 for (counter1 = 0; counter1 < 3; counter1++) {
6429 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6430 (p->drings.ringnum[counter].ring[counter1]-10)) {
6431 distMatches++;
6434 if (distMatches == 3) {
6435 /* The ring matches, set the context to whatever is for distinctive ring.. */
6436 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6437 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6438 if (option_verbose > 2)
6439 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6440 break;
6444 /* Restore linear mode (if appropriate) for Caller*ID processing */
6445 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6446 #if 1
6447 restore_gains(p);
6448 #endif
6449 } else
6450 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6451 } else {
6452 ast_log(LOG_WARNING, "Channel %s in prering "
6453 "state, but I have nothing to do. "
6454 "Terminating simple switch, should be "
6455 "restarted by the actual ring.\n",
6456 chan->name);
6457 ast_hangup(chan);
6458 goto quit;
6460 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6461 /* FSK Bell202 callerID */
6462 cs = callerid_new(p->cid_signalling);
6463 if (cs) {
6464 #if 1
6465 bump_gains(p);
6466 #endif
6467 samples = 0;
6468 len = 0;
6469 distMatches = 0;
6470 /* Clear the current ring data array so we dont have old data in it. */
6471 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6472 curRingData[receivedRingT] = 0;
6473 receivedRingT = 0;
6474 counter = 0;
6475 counter1 = 0;
6476 /* Check to see if context is what it should be, if not set to be. */
6477 if (strcmp(p->context,p->defcontext) != 0) {
6478 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6479 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6482 /* Take out of linear mode for Caller*ID processing */
6483 dahdi_setlinear(p->subs[index].dfd, 0);
6484 for (;;) {
6485 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6486 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6487 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6488 callerid_free(cs);
6489 ast_hangup(chan);
6490 goto quit;
6492 if (i & DAHDI_IOMUX_SIGEVENT) {
6493 res = dahdi_get_event(p->subs[index].dfd);
6494 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6495 /* If we get a PR event, they hung up while processing calerid */
6496 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6497 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6498 p->polarity = POLARITY_IDLE;
6499 callerid_free(cs);
6500 ast_hangup(chan);
6501 goto quit;
6503 res = 0;
6504 /* Let us detect callerid when the telco uses distinctive ring */
6506 curRingData[receivedRingT] = p->ringt;
6508 if (p->ringt < p->ringt_base/2)
6509 break;
6510 /* Increment the ringT counter so we can match it against
6511 values in chan_dahdi.conf for distinctive ring */
6512 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6513 break;
6514 } else if (i & DAHDI_IOMUX_READ) {
6515 res = read(p->subs[index].dfd, buf, sizeof(buf));
6516 if (res < 0) {
6517 if (errno != ELAST) {
6518 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6519 callerid_free(cs);
6520 ast_hangup(chan);
6521 goto quit;
6523 break;
6525 if (p->ringt)
6526 p->ringt--;
6527 if (p->ringt == 1) {
6528 res = -1;
6529 break;
6531 samples += res;
6532 res = callerid_feed(cs, buf, res, AST_LAW(p));
6533 if (res < 0) {
6534 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6535 break;
6536 } else if (res)
6537 break;
6538 else if (samples > (8000 * 10))
6539 break;
6542 if (res == 1) {
6543 callerid_get(cs, &name, &number, &flags);
6544 if (option_debug)
6545 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6547 if (distinctiveringaftercid == 1) {
6548 /* Clear the current ring data array so we dont have old data in it. */
6549 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6550 curRingData[receivedRingT] = 0;
6552 receivedRingT = 0;
6553 if (option_verbose > 2)
6554 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6555 for (;;) {
6556 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6557 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6558 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6559 callerid_free(cs);
6560 ast_hangup(chan);
6561 goto quit;
6563 if (i & DAHDI_IOMUX_SIGEVENT) {
6564 res = dahdi_get_event(p->subs[index].dfd);
6565 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6566 res = 0;
6567 /* Let us detect callerid when the telco uses distinctive ring */
6569 curRingData[receivedRingT] = p->ringt;
6571 if (p->ringt < p->ringt_base/2)
6572 break;
6573 /* Increment the ringT counter so we can match it against
6574 values in chan_dahdi.conf for distinctive ring */
6575 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6576 break;
6577 } else if (i & DAHDI_IOMUX_READ) {
6578 res = read(p->subs[index].dfd, buf, sizeof(buf));
6579 if (res < 0) {
6580 if (errno != ELAST) {
6581 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6582 callerid_free(cs);
6583 ast_hangup(chan);
6584 goto quit;
6586 break;
6588 if (p->ringt)
6589 p->ringt--;
6590 if (p->ringt == 1) {
6591 res = -1;
6592 break;
6597 if (p->usedistinctiveringdetection == 1) {
6598 if (option_verbose > 2)
6599 /* this only shows up if you have n of the dring patterns filled in */
6600 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6602 for (counter = 0; counter < 3; counter++) {
6603 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6604 channel */
6605 if (option_verbose > 2)
6606 /* this only shows up if you have n of the dring patterns filled in */
6607 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6608 p->drings.ringnum[counter].ring[0],
6609 p->drings.ringnum[counter].ring[1],
6610 p->drings.ringnum[counter].ring[2]);
6611 distMatches = 0;
6612 for (counter1 = 0; counter1 < 3; counter1++) {
6613 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6614 (p->drings.ringnum[counter].ring[counter1]-10)) {
6615 distMatches++;
6618 if (distMatches == 3) {
6619 /* The ring matches, set the context to whatever is for distinctive ring.. */
6620 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6621 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6622 if (option_verbose > 2)
6623 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6624 break;
6628 /* Restore linear mode (if appropriate) for Caller*ID processing */
6629 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6630 #if 1
6631 restore_gains(p);
6632 #endif
6633 if (res < 0) {
6634 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6636 } else
6637 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6639 else
6640 cs = NULL;
6642 if (number)
6643 ast_shrink_phone_number(number);
6644 ast_set_callerid(chan, number, name, number);
6646 if (smdi_msg)
6647 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6649 if (cs)
6650 callerid_free(cs);
6652 ast_setstate(chan, AST_STATE_RING);
6653 chan->rings = 1;
6654 p->ringt = p->ringt_base;
6655 res = ast_pbx_run(chan);
6656 if (res) {
6657 ast_hangup(chan);
6658 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6660 goto quit;
6661 default:
6662 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6663 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6664 if (res < 0)
6665 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6667 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6668 if (res < 0)
6669 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6670 ast_hangup(chan);
6671 quit:
6672 ast_mutex_lock(&ss_thread_lock);
6673 ss_thread_count--;
6674 ast_cond_signal(&ss_thread_complete);
6675 ast_mutex_unlock(&ss_thread_lock);
6676 return NULL;
6679 /* destroy a DAHDI channel, identified by its number */
6680 static int dahdi_destroy_channel_bynum(int channel)
6682 struct dahdi_pvt *tmp = NULL;
6683 struct dahdi_pvt *prev = NULL;
6685 tmp = iflist;
6686 while (tmp) {
6687 if (tmp->channel == channel) {
6688 int x = DAHDI_FLASH;
6689 ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
6690 destroy_channel(prev, tmp, 1);
6691 return RESULT_SUCCESS;
6693 prev = tmp;
6694 tmp = tmp->next;
6696 return RESULT_FAILURE;
6699 static int handle_init_event(struct dahdi_pvt *i, int event)
6701 int res;
6702 pthread_t threadid;
6703 pthread_attr_t attr;
6704 struct ast_channel *chan;
6705 pthread_attr_init(&attr);
6706 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6707 /* Handle an event on a given channel for the monitor thread. */
6708 switch (event) {
6709 case DAHDI_EVENT_NONE:
6710 case DAHDI_EVENT_BITSCHANGED:
6711 break;
6712 case DAHDI_EVENT_WINKFLASH:
6713 case DAHDI_EVENT_RINGOFFHOOK:
6714 if (i->inalarm) break;
6715 if (i->radio) break;
6716 /* Got a ring/answer. What kind of channel are we? */
6717 switch (i->sig) {
6718 case SIG_FXOLS:
6719 case SIG_FXOGS:
6720 case SIG_FXOKS:
6721 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6722 if (res && (errno == EBUSY))
6723 break;
6724 if (i->cidspill) {
6725 /* Cancel VMWI spill */
6726 free(i->cidspill);
6727 i->cidspill = NULL;
6729 if (i->immediate) {
6730 dahdi_enable_ec(i);
6731 /* The channel is immediately up. Start right away */
6732 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6733 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6734 if (!chan) {
6735 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6736 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6737 if (res < 0)
6738 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6740 } else {
6741 /* Check for callerid, digits, etc */
6742 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6743 if (chan) {
6744 if (has_voicemail(i))
6745 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6746 else
6747 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6748 if (res < 0)
6749 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
6750 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6751 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6752 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6753 if (res < 0)
6754 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6755 ast_hangup(chan);
6757 } else
6758 ast_log(LOG_WARNING, "Unable to create channel\n");
6760 break;
6761 case SIG_FXSLS:
6762 case SIG_FXSGS:
6763 case SIG_FXSKS:
6764 i->ringt = i->ringt_base;
6765 /* Fall through */
6766 case SIG_EMWINK:
6767 case SIG_FEATD:
6768 case SIG_FEATDMF:
6769 case SIG_FEATDMF_TA:
6770 case SIG_E911:
6771 case SIG_FGC_CAMA:
6772 case SIG_FGC_CAMAMF:
6773 case SIG_FEATB:
6774 case SIG_EM:
6775 case SIG_EM_E1:
6776 case SIG_SFWINK:
6777 case SIG_SF_FEATD:
6778 case SIG_SF_FEATDMF:
6779 case SIG_SF_FEATB:
6780 case SIG_SF:
6781 /* Check for callerid, digits, etc */
6782 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
6783 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6784 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6785 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6786 if (res < 0)
6787 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6788 ast_hangup(chan);
6789 } else if (!chan) {
6790 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
6792 break;
6793 default:
6794 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6795 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6796 if (res < 0)
6797 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6798 return -1;
6800 break;
6801 case DAHDI_EVENT_NOALARM:
6802 i->inalarm = 0;
6803 if (!i->unknown_alarm) {
6804 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
6805 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6806 "Channel: %d\r\n", i->channel);
6807 } else {
6808 i->unknown_alarm = 0;
6810 break;
6811 case DAHDI_EVENT_ALARM:
6812 i->inalarm = 1;
6813 res = get_alarms(i);
6814 handle_alarms(i, res);
6815 /* fall thru intentionally */
6816 case DAHDI_EVENT_ONHOOK:
6817 if (i->radio)
6818 break;
6819 /* Back on hook. Hang up. */
6820 switch (i->sig) {
6821 case SIG_FXOLS:
6822 case SIG_FXOGS:
6823 case SIG_FEATD:
6824 case SIG_FEATDMF:
6825 case SIG_FEATDMF_TA:
6826 case SIG_E911:
6827 case SIG_FGC_CAMA:
6828 case SIG_FGC_CAMAMF:
6829 case SIG_FEATB:
6830 case SIG_EM:
6831 case SIG_EM_E1:
6832 case SIG_EMWINK:
6833 case SIG_SF_FEATD:
6834 case SIG_SF_FEATDMF:
6835 case SIG_SF_FEATB:
6836 case SIG_SF:
6837 case SIG_SFWINK:
6838 case SIG_FXSLS:
6839 case SIG_FXSGS:
6840 case SIG_FXSKS:
6841 case SIG_GR303FXSKS:
6842 dahdi_disable_ec(i);
6843 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6844 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6845 break;
6846 case SIG_GR303FXOKS:
6847 case SIG_FXOKS:
6848 dahdi_disable_ec(i);
6849 /* Diddle the battery for the zhone */
6850 #ifdef ZHONE_HACK
6851 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6852 usleep(1);
6853 #endif
6854 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6855 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6856 break;
6857 case SIG_PRI:
6858 dahdi_disable_ec(i);
6859 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6860 break;
6861 default:
6862 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6863 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6864 return -1;
6866 break;
6867 case DAHDI_EVENT_POLARITY:
6868 switch (i->sig) {
6869 case SIG_FXSLS:
6870 case SIG_FXSKS:
6871 case SIG_FXSGS:
6872 /* We have already got a PR before the channel was
6873 created, but it wasn't handled. We need polarity
6874 to be REV for remote hangup detection to work.
6875 At least in Spain */
6876 if (i->hanguponpolarityswitch)
6877 i->polarity = POLARITY_REV;
6879 if (i->cid_start == CID_START_POLARITY) {
6880 i->polarity = POLARITY_REV;
6881 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
6882 "CID detection on channel %d\n",
6883 i->channel);
6884 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
6885 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6886 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6889 break;
6890 default:
6891 ast_log(LOG_WARNING, "handle_init_event detected "
6892 "polarity reversal on non-FXO (SIG_FXS) "
6893 "interface %d\n", i->channel);
6895 break;
6896 case DAHDI_EVENT_REMOVED: /* destroy channel */
6897 ast_log(LOG_NOTICE,
6898 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6899 i->channel);
6900 dahdi_destroy_channel_bynum(i->channel);
6901 break;
6903 pthread_attr_destroy(&attr);
6904 return 0;
6907 static void *do_monitor(void *data)
6909 int count, res, res2, spoint, pollres=0;
6910 struct dahdi_pvt *i;
6911 struct dahdi_pvt *last = NULL;
6912 time_t thispass = 0, lastpass = 0;
6913 int found;
6914 char buf[1024];
6915 struct pollfd *pfds=NULL;
6916 int lastalloc = -1;
6917 /* This thread monitors all the frame relay interfaces which are not yet in use
6918 (and thus do not have a separate thread) indefinitely */
6919 /* From here on out, we die whenever asked */
6920 #if 0
6921 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
6922 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
6923 return NULL;
6925 ast_log(LOG_DEBUG, "Monitor starting...\n");
6926 #endif
6927 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
6929 for (;;) {
6930 /* Lock the interface list */
6931 ast_mutex_lock(&iflock);
6932 if (!pfds || (lastalloc != ifcount)) {
6933 if (pfds) {
6934 free(pfds);
6935 pfds = NULL;
6937 if (ifcount) {
6938 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
6939 ast_mutex_unlock(&iflock);
6940 return NULL;
6943 lastalloc = ifcount;
6945 /* Build the stuff we're going to poll on, that is the socket of every
6946 dahdi_pvt that does not have an associated owner channel */
6947 count = 0;
6948 i = iflist;
6949 while (i) {
6950 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
6951 if (!i->owner && !i->subs[SUB_REAL].owner) {
6952 /* This needs to be watched, as it lacks an owner */
6953 pfds[count].fd = i->subs[SUB_REAL].dfd;
6954 pfds[count].events = POLLPRI;
6955 pfds[count].revents = 0;
6956 /* Message waiting or r2 channels also get watched for reading */
6957 if (i->cidspill)
6958 pfds[count].events |= POLLIN;
6959 count++;
6962 i = i->next;
6964 /* Okay, now that we know what to do, release the interface lock */
6965 ast_mutex_unlock(&iflock);
6967 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
6968 pthread_testcancel();
6969 /* Wait at least a second for something to happen */
6970 res = poll(pfds, count, 1000);
6971 pthread_testcancel();
6972 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
6974 /* Okay, poll has finished. Let's see what happened. */
6975 if (res < 0) {
6976 if ((errno != EAGAIN) && (errno != EINTR))
6977 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
6978 continue;
6980 /* Alright, lock the interface list again, and let's look and see what has
6981 happened */
6982 ast_mutex_lock(&iflock);
6983 found = 0;
6984 spoint = 0;
6985 lastpass = thispass;
6986 thispass = time(NULL);
6987 i = iflist;
6988 while (i) {
6989 if (thispass != lastpass) {
6990 if (!found && ((i == last) || ((i == iflist) && !last))) {
6991 last = i;
6992 if (last) {
6993 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
6994 (last->sig & __DAHDI_SIG_FXO)) {
6995 res = ast_app_has_voicemail(last->mailbox, NULL);
6996 if (last->msgstate != res) {
6997 int x;
6998 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
6999 x = DAHDI_FLUSH_BOTH;
7000 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
7001 if (res2)
7002 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
7003 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
7004 /* Turn on on hook transfer for 4 seconds */
7005 x = 4000;
7006 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
7007 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
7008 last->cidpos = 0;
7009 last->msgstate = res;
7010 last->onhooktime = thispass;
7012 found ++;
7015 last = last->next;
7019 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
7020 if (i->radio && !i->owner)
7022 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7023 if (res)
7025 if (option_debug)
7026 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
7027 /* Don't hold iflock while handling init events */
7028 ast_mutex_unlock(&iflock);
7029 handle_init_event(i, res);
7030 ast_mutex_lock(&iflock);
7032 i = i->next;
7033 continue;
7035 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
7036 if (pollres & POLLIN) {
7037 if (i->owner || i->subs[SUB_REAL].owner) {
7038 #ifdef HAVE_PRI
7039 if (!i->pri)
7040 #endif
7041 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
7042 i = i->next;
7043 continue;
7045 if (!i->cidspill) {
7046 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
7047 i = i->next;
7048 continue;
7050 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
7051 if (res > 0) {
7052 /* We read some number of bytes. Write an equal amount of data */
7053 if (res > i->cidlen - i->cidpos)
7054 res = i->cidlen - i->cidpos;
7055 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
7056 if (res2 > 0) {
7057 i->cidpos += res2;
7058 if (i->cidpos >= i->cidlen) {
7059 free(i->cidspill);
7060 i->cidspill = 0;
7061 i->cidpos = 0;
7062 i->cidlen = 0;
7064 } else {
7065 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
7066 i->msgstate = -1;
7068 } else {
7069 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
7072 if (pollres & POLLPRI) {
7073 if (i->owner || i->subs[SUB_REAL].owner) {
7074 #ifdef HAVE_PRI
7075 if (!i->pri)
7076 #endif
7077 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
7078 i = i->next;
7079 continue;
7081 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7082 if (option_debug)
7083 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
7084 /* Don't hold iflock while handling init events */
7085 ast_mutex_unlock(&iflock);
7086 handle_init_event(i, res);
7087 ast_mutex_lock(&iflock);
7090 i=i->next;
7092 ast_mutex_unlock(&iflock);
7094 /* Never reached */
7095 return NULL;
7099 static int restart_monitor(void)
7101 pthread_attr_t attr;
7102 pthread_attr_init(&attr);
7103 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7104 /* If we're supposed to be stopped -- stay stopped */
7105 if (monitor_thread == AST_PTHREADT_STOP)
7106 return 0;
7107 ast_mutex_lock(&monlock);
7108 if (monitor_thread == pthread_self()) {
7109 ast_mutex_unlock(&monlock);
7110 ast_log(LOG_WARNING, "Cannot kill myself\n");
7111 return -1;
7113 if (monitor_thread != AST_PTHREADT_NULL) {
7114 /* Wake up the thread */
7115 pthread_kill(monitor_thread, SIGURG);
7116 } else {
7117 /* Start a new monitor */
7118 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7119 ast_mutex_unlock(&monlock);
7120 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7121 pthread_attr_destroy(&attr);
7122 return -1;
7125 ast_mutex_unlock(&monlock);
7126 pthread_attr_destroy(&attr);
7127 return 0;
7130 #ifdef HAVE_PRI
7131 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
7133 int x;
7134 int trunkgroup;
7135 /* Get appropriate trunk group if there is one */
7136 trunkgroup = pris[*span].mastertrunkgroup;
7137 if (trunkgroup) {
7138 /* Select a specific trunk group */
7139 for (x = 0; x < NUM_SPANS; x++) {
7140 if (pris[x].trunkgroup == trunkgroup) {
7141 *span = x;
7142 return 0;
7145 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7146 *span = -1;
7147 } else {
7148 if (pris[*span].trunkgroup) {
7149 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7150 *span = -1;
7151 } else if (pris[*span].mastertrunkgroup) {
7152 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7153 *span = -1;
7154 } else {
7155 if (si->totalchans == 31) {
7156 /* E1 */
7157 pris[*span].dchannels[0] = 16 + offset;
7158 } else if (si->totalchans == 24) {
7159 /* T1 or J1 */
7160 pris[*span].dchannels[0] = 24 + offset;
7161 } else if (si->totalchans == 3) {
7162 /* BRI */
7163 pris[*span].dchannels[0] = 3 + offset;
7164 } else {
7165 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);
7166 *span = -1;
7167 return 0;
7169 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7170 pris[*span].offset = offset;
7171 pris[*span].span = *span + 1;
7174 return 0;
7177 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7179 struct dahdi_spaninfo si;
7180 struct dahdi_params p;
7181 int fd;
7182 int span;
7183 int ospan=0;
7184 int x,y;
7185 for (x = 0; x < NUM_SPANS; x++) {
7186 if (pris[x].trunkgroup == trunkgroup) {
7187 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7188 return -1;
7191 for (y = 0; y < NUM_DCHANS; y++) {
7192 if (!channels[y])
7193 break;
7194 memset(&si, 0, sizeof(si));
7195 memset(&p, 0, sizeof(p));
7196 #ifdef HAVE_ZAPTEL
7197 fd = open("/dev/zap/channel", O_RDWR);
7198 #else
7199 fd = open("/dev/dahdi/channel", O_RDWR);
7200 #endif
7201 if (fd < 0) {
7202 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7203 return -1;
7205 x = channels[y];
7206 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7207 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7208 dahdi_close(fd);
7209 return -1;
7211 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7212 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7213 return -1;
7215 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7216 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7217 dahdi_close(fd);
7218 return -1;
7220 span = p.spanno - 1;
7221 if (pris[span].trunkgroup) {
7222 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7223 dahdi_close(fd);
7224 return -1;
7226 if (pris[span].pvts[0]) {
7227 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7228 dahdi_close(fd);
7229 return -1;
7231 if (!y) {
7232 pris[span].trunkgroup = trunkgroup;
7233 pris[span].offset = channels[y] - p.chanpos;
7234 ospan = span;
7236 pris[ospan].dchannels[y] = channels[y];
7237 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7238 pris[span].span = span + 1;
7239 dahdi_close(fd);
7241 return 0;
7244 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7246 if (pris[span].mastertrunkgroup) {
7247 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);
7248 return -1;
7250 pris[span].mastertrunkgroup = trunkgroup;
7251 pris[span].prilogicalspan = logicalspan;
7252 return 0;
7255 #endif
7257 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7259 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7260 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7261 char fn[80];
7262 #if 1
7263 struct dahdi_bufferinfo bi;
7264 #endif
7265 int res;
7266 int span=0;
7267 int here = 0;
7268 int x;
7269 struct dahdi_pvt **wlist;
7270 struct dahdi_pvt **wend;
7271 struct dahdi_params p;
7273 wlist = &iflist;
7274 wend = &ifend;
7276 #ifdef HAVE_PRI
7277 if (pri) {
7278 wlist = &pri->crvs;
7279 wend = &pri->crvend;
7281 #endif
7283 tmp2 = *wlist;
7284 prev = NULL;
7286 while (tmp2) {
7287 if (!tmp2->destroy) {
7288 if (tmp2->channel == channel) {
7289 tmp = tmp2;
7290 here = 1;
7291 break;
7293 if (tmp2->channel > channel) {
7294 break;
7297 prev = tmp2;
7298 tmp2 = tmp2->next;
7301 if (!here && reloading != 1) {
7302 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7303 if (tmp)
7304 free(tmp);
7305 return NULL;
7307 ast_mutex_init(&tmp->lock);
7308 ifcount++;
7309 for (x = 0; x < 3; x++)
7310 tmp->subs[x].dfd = -1;
7311 tmp->channel = channel;
7314 if (tmp) {
7315 int chan_sig = conf->chan.sig;
7316 if (!here) {
7317 if ((channel != CHAN_PSEUDO) && !pri) {
7318 snprintf(fn, sizeof(fn), "%d", channel);
7319 /* Open non-blocking */
7320 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7321 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
7322 usleep(1);
7323 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7325 /* Allocate a DAHDI structure */
7326 if (tmp->subs[SUB_REAL].dfd < 0) {
7327 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);
7328 destroy_dahdi_pvt(&tmp);
7329 return NULL;
7331 memset(&p, 0, sizeof(p));
7332 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7333 if (res < 0) {
7334 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7335 destroy_dahdi_pvt(&tmp);
7336 return NULL;
7338 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7339 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));
7340 destroy_dahdi_pvt(&tmp);
7341 return NULL;
7343 tmp->law = p.curlaw;
7344 tmp->span = p.spanno;
7345 span = p.spanno - 1;
7346 } else {
7347 if (channel == CHAN_PSEUDO)
7348 chan_sig = 0;
7349 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7350 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7351 return NULL;
7354 #ifdef HAVE_PRI
7355 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7356 int offset;
7357 int myswitchtype;
7358 int matchesdchan;
7359 int x,y;
7360 offset = 0;
7361 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7362 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7363 destroy_dahdi_pvt(&tmp);
7364 return NULL;
7366 if (span >= NUM_SPANS) {
7367 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7368 destroy_dahdi_pvt(&tmp);
7369 return NULL;
7370 } else {
7371 struct dahdi_spaninfo si;
7372 si.spanno = 0;
7373 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7374 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7375 destroy_dahdi_pvt(&tmp);
7376 return NULL;
7378 /* Store the logical span first based upon the real span */
7379 tmp->logicalspan = pris[span].prilogicalspan;
7380 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7381 if (span < 0) {
7382 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7383 destroy_dahdi_pvt(&tmp);
7384 return NULL;
7386 if (chan_sig == SIG_PRI)
7387 myswitchtype = conf->pri.switchtype;
7388 else
7389 myswitchtype = PRI_SWITCH_GR303_TMC;
7390 /* Make sure this isn't a d-channel */
7391 matchesdchan=0;
7392 for (x = 0; x < NUM_SPANS; x++) {
7393 for (y = 0; y < NUM_DCHANS; y++) {
7394 if (pris[x].dchannels[y] == tmp->channel) {
7395 matchesdchan = 1;
7396 break;
7400 offset = p.chanpos;
7401 if (!matchesdchan) {
7402 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7403 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7404 destroy_dahdi_pvt(&tmp);
7405 return NULL;
7407 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7408 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7409 destroy_dahdi_pvt(&tmp);
7410 return NULL;
7412 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7413 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7414 destroy_dahdi_pvt(&tmp);
7415 return NULL;
7417 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7418 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7419 destroy_dahdi_pvt(&tmp);
7420 return NULL;
7422 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7423 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7424 destroy_dahdi_pvt(&tmp);
7425 return NULL;
7427 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7428 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7429 destroy_dahdi_pvt(&tmp);
7430 return NULL;
7432 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7433 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7434 destroy_dahdi_pvt(&tmp);
7435 return NULL;
7437 if (pris[span].numchans >= MAX_CHANNELS) {
7438 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7439 pris[span].trunkgroup);
7440 destroy_dahdi_pvt(&tmp);
7441 return NULL;
7443 pris[span].nodetype = conf->pri.nodetype;
7444 pris[span].switchtype = myswitchtype;
7445 pris[span].nsf = conf->pri.nsf;
7446 pris[span].dialplan = conf->pri.dialplan;
7447 pris[span].localdialplan = conf->pri.localdialplan;
7448 pris[span].pvts[pris[span].numchans++] = tmp;
7449 pris[span].minunused = conf->pri.minunused;
7450 pris[span].minidle = conf->pri.minidle;
7451 pris[span].overlapdial = conf->pri.overlapdial;
7452 #ifdef HAVE_PRI_INBANDDISCONNECT
7453 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
7454 #endif
7455 pris[span].facilityenable = conf->pri.facilityenable;
7456 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7457 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7458 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7459 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7460 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7461 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7462 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7463 pris[span].resetinterval = conf->pri.resetinterval;
7465 tmp->pri = &pris[span];
7466 tmp->prioffset = offset;
7467 tmp->call = NULL;
7468 } else {
7469 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7470 destroy_dahdi_pvt(&tmp);
7471 return NULL;
7474 } else {
7475 tmp->prioffset = 0;
7477 #endif
7478 } else {
7479 chan_sig = tmp->sig;
7480 memset(&p, 0, sizeof(p));
7481 if (tmp->subs[SUB_REAL].dfd > -1)
7482 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7484 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7485 switch (chan_sig) {
7486 case SIG_FXSKS:
7487 case SIG_FXSLS:
7488 case SIG_EM:
7489 case SIG_EM_E1:
7490 case SIG_EMWINK:
7491 case SIG_FEATD:
7492 case SIG_FEATDMF:
7493 case SIG_FEATDMF_TA:
7494 case SIG_FEATB:
7495 case SIG_E911:
7496 case SIG_SF:
7497 case SIG_SFWINK:
7498 case SIG_FGC_CAMA:
7499 case SIG_FGC_CAMAMF:
7500 case SIG_SF_FEATD:
7501 case SIG_SF_FEATDMF:
7502 case SIG_SF_FEATB:
7503 p.starttime = 250;
7504 break;
7507 if (tmp->radio) {
7508 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7509 p.channo = channel;
7510 p.rxwinktime = 1;
7511 p.rxflashtime = 1;
7512 p.starttime = 1;
7513 p.debouncetime = 5;
7515 if (!tmp->radio) {
7516 p.channo = channel;
7517 /* Override timing settings based on config file */
7518 if (conf->timing.prewinktime >= 0)
7519 p.prewinktime = conf->timing.prewinktime;
7520 if (conf->timing.preflashtime >= 0)
7521 p.preflashtime = conf->timing.preflashtime;
7522 if (conf->timing.winktime >= 0)
7523 p.winktime = conf->timing.winktime;
7524 if (conf->timing.flashtime >= 0)
7525 p.flashtime = conf->timing.flashtime;
7526 if (conf->timing.starttime >= 0)
7527 p.starttime = conf->timing.starttime;
7528 if (conf->timing.rxwinktime >= 0)
7529 p.rxwinktime = conf->timing.rxwinktime;
7530 if (conf->timing.rxflashtime >= 0)
7531 p.rxflashtime = conf->timing.rxflashtime;
7532 if (conf->timing.debouncetime >= 0)
7533 p.debouncetime = conf->timing.debouncetime;
7536 /* dont set parms on a pseudo-channel (or CRV) */
7537 if (tmp->subs[SUB_REAL].dfd >= 0)
7539 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7540 if (res < 0) {
7541 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7542 destroy_dahdi_pvt(&tmp);
7543 return NULL;
7546 #if 1
7547 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7548 memset(&bi, 0, sizeof(bi));
7549 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7550 if (!res) {
7551 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7552 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7553 bi.numbufs = numbufs;
7554 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7555 if (res < 0) {
7556 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7558 } else
7559 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7561 #endif
7562 tmp->immediate = conf->chan.immediate;
7563 tmp->transfertobusy = conf->chan.transfertobusy;
7564 tmp->sig = chan_sig;
7565 tmp->outsigmod = conf->chan.outsigmod;
7566 tmp->ringt_base = ringt_base;
7567 tmp->firstradio = 0;
7568 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7569 tmp->permcallwaiting = conf->chan.callwaiting;
7570 else
7571 tmp->permcallwaiting = 0;
7572 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7573 tmp->destroy = 0;
7574 tmp->drings = drings;
7575 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7576 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7577 tmp->threewaycalling = conf->chan.threewaycalling;
7578 tmp->adsi = conf->chan.adsi;
7579 tmp->use_smdi = conf->chan.use_smdi;
7580 tmp->permhidecallerid = conf->chan.hidecallerid;
7581 tmp->callreturn = conf->chan.callreturn;
7582 tmp->echocancel = conf->chan.echocancel;
7583 tmp->echotraining = conf->chan.echotraining;
7584 tmp->pulse = conf->chan.pulse;
7585 if (tmp->echocancel)
7586 tmp->echocanbridged = conf->chan.echocanbridged;
7587 else {
7588 if (conf->chan.echocanbridged)
7589 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7590 tmp->echocanbridged = 0;
7592 tmp->busydetect = conf->chan.busydetect;
7593 tmp->busycount = conf->chan.busycount;
7594 tmp->busy_tonelength = conf->chan.busy_tonelength;
7595 tmp->busy_quietlength = conf->chan.busy_quietlength;
7596 tmp->callprogress = conf->chan.callprogress;
7597 tmp->cancallforward = conf->chan.cancallforward;
7598 tmp->dtmfrelax = conf->chan.dtmfrelax;
7599 tmp->callwaiting = tmp->permcallwaiting;
7600 tmp->hidecallerid = tmp->permhidecallerid;
7601 tmp->channel = channel;
7602 tmp->stripmsd = conf->chan.stripmsd;
7603 tmp->use_callerid = conf->chan.use_callerid;
7604 tmp->cid_signalling = conf->chan.cid_signalling;
7605 tmp->cid_start = conf->chan.cid_start;
7606 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7607 tmp->restrictcid = conf->chan.restrictcid;
7608 tmp->use_callingpres = conf->chan.use_callingpres;
7609 tmp->priindication_oob = conf->chan.priindication_oob;
7610 tmp->priexclusive = conf->chan.priexclusive;
7611 if (tmp->usedistinctiveringdetection) {
7612 if (!tmp->use_callerid) {
7613 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7614 tmp->use_callerid = 1;
7618 if (tmp->cid_signalling == CID_SIG_SMDI) {
7619 if (!tmp->use_smdi) {
7620 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7621 tmp->use_smdi = 1;
7624 if (tmp->use_smdi) {
7625 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7626 if (!(tmp->smdi_iface)) {
7627 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7628 tmp->use_smdi = 0;
7632 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7633 tmp->amaflags = conf->chan.amaflags;
7634 if (!here) {
7635 tmp->confno = -1;
7636 tmp->propconfno = -1;
7638 tmp->canpark = conf->chan.canpark;
7639 tmp->transfer = conf->chan.transfer;
7640 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7641 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7642 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7643 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7644 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7645 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7646 tmp->cid_ton = 0;
7647 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7648 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7649 tmp->msgstate = -1;
7650 tmp->group = conf->chan.group;
7651 tmp->callgroup = conf->chan.callgroup;
7652 tmp->pickupgroup= conf->chan.pickupgroup;
7653 tmp->rxgain = conf->chan.rxgain;
7654 tmp->txgain = conf->chan.txgain;
7655 tmp->tonezone = conf->chan.tonezone;
7656 tmp->onhooktime = time(NULL);
7657 if (tmp->subs[SUB_REAL].dfd > -1) {
7658 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7659 if (tmp->dsp)
7660 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7661 update_conf(tmp);
7662 if (!here) {
7663 if (chan_sig != SIG_PRI)
7664 /* Hang it up to be sure it's good */
7665 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7667 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7668 #ifdef HAVE_PRI
7669 /* the dchannel is down so put the channel in alarm */
7670 if (tmp->pri && !pri_is_up(tmp->pri)) {
7671 tmp->inalarm = 1;
7673 #endif
7674 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
7675 tmp->inalarm = 1;
7676 handle_alarms(tmp, res);
7677 } else {
7678 /* yes, this looks strange... the unknown_alarm flag is only used to
7679 control whether an 'alarm cleared' message gets generated when we
7680 get an indication that the channel is no longer in alarm status.
7681 however, the channel *could* be in an alarm status that we aren't
7682 aware of (since get_alarms() only reports span alarms, not channel
7683 alarms). setting this flag will cause any potential 'alarm cleared'
7684 message to be suppressed, but if a real alarm occurs before that
7685 happens, this flag will get cleared by it and the situation will
7686 be normal.
7688 tmp->unknown_alarm = 1;
7692 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
7693 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
7694 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
7695 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
7698 if (tmp && !here) {
7699 /* nothing on the iflist */
7700 if (!*wlist) {
7701 *wlist = tmp;
7702 tmp->prev = NULL;
7703 tmp->next = NULL;
7704 *wend = tmp;
7705 } else {
7706 /* at least one member on the iflist */
7707 struct dahdi_pvt *working = *wlist;
7709 /* check if we maybe have to put it on the begining */
7710 if (working->channel > tmp->channel) {
7711 tmp->next = *wlist;
7712 tmp->prev = NULL;
7713 (*wlist)->prev = tmp;
7714 *wlist = tmp;
7715 } else {
7716 /* go through all the members and put the member in the right place */
7717 while (working) {
7718 /* in the middle */
7719 if (working->next) {
7720 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
7721 tmp->next = working->next;
7722 tmp->prev = working;
7723 working->next->prev = tmp;
7724 working->next = tmp;
7725 break;
7727 } else {
7728 /* the last */
7729 if (working->channel < tmp->channel) {
7730 working->next = tmp;
7731 tmp->next = NULL;
7732 tmp->prev = working;
7733 *wend = tmp;
7734 break;
7737 working = working->next;
7742 return tmp;
7745 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
7747 int res;
7748 struct dahdi_params par;
7750 /* First, check group matching */
7751 if (groupmatch) {
7752 if ((p->group & groupmatch) != groupmatch)
7753 return 0;
7754 *groupmatched = 1;
7756 /* Check to see if we have a channel match */
7757 if (channelmatch != -1) {
7758 if (p->channel != channelmatch)
7759 return 0;
7760 *channelmatched = 1;
7762 /* We're at least busy at this point */
7763 if (busy) {
7764 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
7765 *busy = 1;
7767 /* If do not disturb, definitely not */
7768 if (p->dnd)
7769 return 0;
7770 /* If guard time, definitely not */
7771 if (p->guardtime && (time(NULL) < p->guardtime))
7772 return 0;
7774 /* If no owner definitely available */
7775 if (!p->owner) {
7776 #ifdef HAVE_PRI
7777 /* Trust PRI */
7778 if (p->pri) {
7779 if (p->resetting || p->call)
7780 return 0;
7781 else
7782 return 1;
7784 #endif
7785 if (!(p->radio || (p->oprmode < 0)))
7787 if (!p->sig || (p->sig == SIG_FXSLS))
7788 return 1;
7789 /* Check hook state */
7790 if (p->subs[SUB_REAL].dfd > -1)
7791 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
7792 else {
7793 /* Assume not off hook on CVRS */
7794 res = 0;
7795 par.rxisoffhook = 0;
7797 if (res) {
7798 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
7799 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
7800 /* When "onhook" that means no battery on the line, and thus
7801 it is out of service..., if it's on a TDM card... If it's a channel
7802 bank, there is no telling... */
7803 if (par.rxbits > -1)
7804 return 1;
7805 if (par.rxisoffhook)
7806 return 1;
7807 else
7808 #ifdef DAHDI_CHECK_HOOKSTATE
7809 return 0;
7810 #else
7811 return 1;
7812 #endif
7813 } else if (par.rxisoffhook) {
7814 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
7815 /* Not available when the other end is off hook */
7816 return 0;
7819 return 1;
7822 /* If it's not an FXO, forget about call wait */
7823 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
7824 return 0;
7826 if (!p->callwaiting) {
7827 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7828 return 0;
7831 if (p->subs[SUB_CALLWAIT].dfd > -1) {
7832 /* If there is already a call waiting call, then we can't take a second one */
7833 return 0;
7836 if ((p->owner->_state != AST_STATE_UP) &&
7837 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
7838 /* If the current call is not up, then don't allow the call */
7839 return 0;
7841 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
7842 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7843 return 0;
7845 /* We're cool */
7846 return 1;
7849 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
7851 struct dahdi_pvt *p;
7852 struct dahdi_bufferinfo bi;
7853 int res;
7855 if ((p = ast_malloc(sizeof(*p)))) {
7856 memcpy(p, src, sizeof(struct dahdi_pvt));
7857 ast_mutex_init(&p->lock);
7858 #ifdef HAVE_ZAPTEL
7859 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
7860 #else
7861 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
7862 #endif
7863 /* Allocate a DAHDI structure */
7864 if (p->subs[SUB_REAL].dfd < 0) {
7865 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
7866 destroy_dahdi_pvt(&p);
7867 return NULL;
7869 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7870 if (!res) {
7871 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7872 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7873 bi.numbufs = numbufs;
7874 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7875 if (res < 0) {
7876 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
7878 } else
7879 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
7881 p->destroy = 1;
7882 p->next = iflist;
7883 p->prev = NULL;
7884 iflist = p;
7885 if (iflist->next)
7886 iflist->next->prev = p;
7887 return p;
7891 #ifdef HAVE_PRI
7892 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
7894 int x;
7895 if (backwards)
7896 x = pri->numchans;
7897 else
7898 x = 0;
7899 for (;;) {
7900 if (backwards && (x < 0))
7901 break;
7902 if (!backwards && (x >= pri->numchans))
7903 break;
7904 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7905 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7906 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7907 return x;
7909 if (backwards)
7910 x--;
7911 else
7912 x++;
7914 return -1;
7916 #endif
7918 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
7920 ast_group_t groupmatch = 0;
7921 int channelmatch = -1;
7922 int roundrobin = 0;
7923 int callwait = 0;
7924 int busy = 0;
7925 struct dahdi_pvt *p;
7926 struct ast_channel *tmp = NULL;
7927 char *dest=NULL;
7928 int x;
7929 char *s;
7930 char opt=0;
7931 int res=0, y=0;
7932 int backwards = 0;
7933 #ifdef HAVE_PRI
7934 int crv;
7935 int bearer = -1;
7936 int trunkgroup;
7937 struct dahdi_pri *pri=NULL;
7938 #endif
7939 struct dahdi_pvt *exit, *start, *end;
7940 ast_mutex_t *lock;
7941 int channelmatched = 0;
7942 int groupmatched = 0;
7944 /* Assume we're locking the iflock */
7945 lock = &iflock;
7946 start = iflist;
7947 end = ifend;
7948 if (data) {
7949 dest = ast_strdupa((char *)data);
7950 } else {
7951 ast_log(LOG_WARNING, "Channel requested with no data\n");
7952 return NULL;
7954 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
7955 /* Retrieve the group number */
7956 char *stringp=NULL;
7957 stringp=dest + 1;
7958 s = strsep(&stringp, "/");
7959 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7960 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
7961 return NULL;
7963 groupmatch = ((ast_group_t) 1 << x);
7964 if (toupper(dest[0]) == 'G') {
7965 if (dest[0] == 'G') {
7966 backwards = 1;
7967 p = ifend;
7968 } else
7969 p = iflist;
7970 } else {
7971 if (dest[0] == 'R') {
7972 backwards = 1;
7973 p = round_robin[x]?round_robin[x]->prev:ifend;
7974 if (!p)
7975 p = ifend;
7976 } else {
7977 p = round_robin[x]?round_robin[x]->next:iflist;
7978 if (!p)
7979 p = iflist;
7981 roundrobin = 1;
7983 } else {
7984 char *stringp=NULL;
7985 stringp=dest;
7986 s = strsep(&stringp, "/");
7987 p = iflist;
7988 if (!strcasecmp(s, "pseudo")) {
7989 /* Special case for pseudo */
7990 x = CHAN_PSEUDO;
7991 channelmatch = x;
7993 #ifdef HAVE_PRI
7994 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
7995 if ((trunkgroup < 1) || (crv < 1)) {
7996 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
7997 return NULL;
7999 res--;
8000 for (x = 0; x < NUM_SPANS; x++) {
8001 if (pris[x].trunkgroup == trunkgroup) {
8002 pri = pris + x;
8003 lock = &pri->lock;
8004 start = pri->crvs;
8005 end = pri->crvend;
8006 break;
8009 if (!pri) {
8010 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
8011 return NULL;
8013 channelmatch = crv;
8014 p = pris[x].crvs;
8016 #endif
8017 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
8018 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
8019 return NULL;
8020 } else {
8021 channelmatch = x;
8024 /* Search for an unowned channel */
8025 ast_mutex_lock(lock);
8026 exit = p;
8027 while (p && !tmp) {
8028 if (roundrobin)
8029 round_robin[x] = p;
8030 #if 0
8031 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
8032 #endif
8034 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
8035 if (option_debug)
8036 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
8037 if (p->inalarm)
8038 goto next;
8040 callwait = (p->owner != NULL);
8041 #ifdef HAVE_PRI
8042 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
8043 if (p->sig != SIG_FXSKS) {
8044 /* Gotta find an actual channel to use for this
8045 CRV if this isn't a callwait */
8046 bearer = pri_find_empty_chan(pri, 0);
8047 if (bearer < 0) {
8048 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
8049 p = NULL;
8050 break;
8052 pri_assign_bearer(p, pri, pri->pvts[bearer]);
8053 } else {
8054 if (alloc_sub(p, 0)) {
8055 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
8056 p = NULL;
8057 break;
8058 } else
8059 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
8060 p->pri = pri;
8063 #endif
8064 if (p->channel == CHAN_PSEUDO) {
8065 p = chandup(p);
8066 if (!p) {
8067 break;
8070 if (p->owner) {
8071 if (alloc_sub(p, SUB_CALLWAIT)) {
8072 p = NULL;
8073 break;
8076 p->outgoing = 1;
8077 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
8078 #ifdef HAVE_PRI
8079 if (p->bearer) {
8080 /* Log owner to bearer channel, too */
8081 p->bearer->owner = tmp;
8083 #endif
8084 /* Make special notes */
8085 if (res > 1) {
8086 if (opt == 'c') {
8087 /* Confirm answer */
8088 p->confirmanswer = 1;
8089 } else if (opt == 'r') {
8090 /* Distinctive ring */
8091 if (res < 3)
8092 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
8093 else
8094 p->distinctivering = y;
8095 } else if (opt == 'd') {
8096 /* If this is an ISDN call, make it digital */
8097 p->digital = 1;
8098 if (tmp)
8099 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
8100 } else {
8101 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
8104 /* Note if the call is a call waiting call */
8105 if (tmp && callwait)
8106 tmp->cdrflags |= AST_CDR_CALLWAIT;
8107 break;
8109 next:
8110 if (backwards) {
8111 p = p->prev;
8112 if (!p)
8113 p = end;
8114 } else {
8115 p = p->next;
8116 if (!p)
8117 p = start;
8119 /* stop when you roll to the one that we started from */
8120 if (p == exit)
8121 break;
8123 ast_mutex_unlock(lock);
8124 restart_monitor();
8125 if (callwait)
8126 *cause = AST_CAUSE_BUSY;
8127 else if (!tmp) {
8128 if (channelmatched) {
8129 if (busy)
8130 *cause = AST_CAUSE_BUSY;
8131 } else if (groupmatched) {
8132 *cause = AST_CAUSE_CONGESTION;
8136 return tmp;
8140 #ifdef HAVE_PRI
8141 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8143 struct dahdi_pvt *p;
8144 p = pri->crvs;
8145 while (p) {
8146 if (p->channel == crv)
8147 return p;
8148 p = p->next;
8150 return NULL;
8154 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8156 int x;
8157 int span = PRI_SPAN(channel);
8158 int spanfd;
8159 struct dahdi_params param;
8160 int principle = -1;
8161 int explicit = PRI_EXPLICIT(channel);
8162 channel = PRI_CHANNEL(channel);
8164 if (!explicit) {
8165 spanfd = pri_active_dchan_fd(pri);
8166 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8167 return -1;
8168 span = pris[param.spanno - 1].prilogicalspan;
8171 for (x = 0; x < pri->numchans; x++) {
8172 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8173 principle = x;
8174 break;
8178 return principle;
8181 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8183 int x;
8184 struct dahdi_pvt *crv;
8185 if (!c) {
8186 if (principle < 0)
8187 return -1;
8188 return principle;
8190 if ((principle > -1) &&
8191 (principle < pri->numchans) &&
8192 (pri->pvts[principle]) &&
8193 (pri->pvts[principle]->call == c))
8194 return principle;
8195 /* First, check for other bearers */
8196 for (x = 0; x < pri->numchans; x++) {
8197 if (!pri->pvts[x])
8198 continue;
8199 if (pri->pvts[x]->call == c) {
8200 /* Found our call */
8201 if (principle != x) {
8202 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8204 if (option_verbose > 2)
8205 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8206 old->channel, new->channel);
8207 if (new->owner) {
8208 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8209 old->channel, new->channel, new->channel);
8210 return -1;
8212 /* Fix it all up now */
8213 new->owner = old->owner;
8214 old->owner = NULL;
8215 if (new->owner) {
8216 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
8217 new->owner->tech_pvt = new;
8218 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8219 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8220 old->subs[SUB_REAL].owner = NULL;
8221 } else
8222 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);
8223 new->call = old->call;
8224 old->call = NULL;
8226 /* Copy any DSP that may be present */
8227 new->dsp = old->dsp;
8228 new->dsp_features = old->dsp_features;
8229 old->dsp = NULL;
8230 old->dsp_features = 0;
8232 return principle;
8235 /* Now check for a CRV with no bearer */
8236 crv = pri->crvs;
8237 while (crv) {
8238 if (crv->call == c) {
8239 /* This is our match... Perform some basic checks */
8240 if (crv->bearer)
8241 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8242 else if (pri->pvts[principle]->owner)
8243 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8244 else {
8245 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8246 wakeup the potential sleeper */
8247 dahdi_close(crv->subs[SUB_REAL].dfd);
8248 pri->pvts[principle]->call = crv->call;
8249 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8250 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8251 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8252 pri->trunkgroup, crv->channel);
8253 wakeup_sub(crv, SUB_REAL, pri);
8255 return principle;
8257 crv = crv->next;
8259 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8260 return -1;
8263 static void *do_idle_thread(void *vchan)
8265 struct ast_channel *chan = vchan;
8266 struct dahdi_pvt *pvt = chan->tech_pvt;
8267 struct ast_frame *f;
8268 char ex[80];
8269 /* Wait up to 30 seconds for an answer */
8270 int newms, ms = 30000;
8271 if (option_verbose > 2)
8272 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8273 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8274 if (ast_call(chan, ex, 0)) {
8275 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8276 ast_hangup(chan);
8277 return NULL;
8279 while ((newms = ast_waitfor(chan, ms)) > 0) {
8280 f = ast_read(chan);
8281 if (!f) {
8282 /* Got hangup */
8283 break;
8285 if (f->frametype == AST_FRAME_CONTROL) {
8286 switch (f->subclass) {
8287 case AST_CONTROL_ANSWER:
8288 /* Launch the PBX */
8289 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8290 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8291 chan->priority = 1;
8292 if (option_verbose > 3)
8293 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8294 ast_pbx_run(chan);
8295 /* It's already hungup, return immediately */
8296 return NULL;
8297 case AST_CONTROL_BUSY:
8298 if (option_verbose > 3)
8299 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8300 break;
8301 case AST_CONTROL_CONGESTION:
8302 if (option_verbose > 3)
8303 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8304 break;
8307 ast_frfree(f);
8308 ms = newms;
8310 /* Hangup the channel since nothing happend */
8311 ast_hangup(chan);
8312 return NULL;
8315 #ifndef PRI_RESTART
8316 #error "Upgrade your libpri"
8317 #endif
8318 static void dahdi_pri_message(struct pri *pri, char *s)
8320 int x, y;
8321 int dchan = -1, span = -1;
8322 int dchancount = 0;
8324 if (pri) {
8325 for (x = 0; x < NUM_SPANS; x++) {
8326 for (y = 0; y < NUM_DCHANS; y++) {
8327 if (pris[x].dchans[y])
8328 dchancount++;
8330 if (pris[x].dchans[y] == pri)
8331 dchan = y;
8333 if (dchan >= 0) {
8334 span = x;
8335 break;
8337 dchancount = 0;
8339 if ((dchan >= 0) && (span >= 0)) {
8340 if (dchancount > 1)
8341 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
8342 else
8343 ast_verbose("%s", s);
8344 } else
8345 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8346 } else
8347 ast_verbose("%s", s);
8349 ast_mutex_lock(&pridebugfdlock);
8351 if (pridebugfd >= 0)
8352 write(pridebugfd, s, strlen(s));
8354 ast_mutex_unlock(&pridebugfdlock);
8357 static void dahdi_pri_error(struct pri *pri, char *s)
8359 int x, y;
8360 int dchan = -1, span = -1;
8361 int dchancount = 0;
8363 if (pri) {
8364 for (x = 0; x < NUM_SPANS; x++) {
8365 for (y = 0; y < NUM_DCHANS; y++) {
8366 if (pris[x].dchans[y])
8367 dchancount++;
8369 if (pris[x].dchans[y] == pri)
8370 dchan = y;
8372 if (dchan >= 0) {
8373 span = x;
8374 break;
8376 dchancount = 0;
8378 if ((dchan >= 0) && (span >= 0)) {
8379 if (dchancount > 1)
8380 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8381 else
8382 ast_log(LOG_ERROR, "%s", s);
8383 } else
8384 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8385 } else
8386 ast_log(LOG_ERROR, "%s", s);
8388 ast_mutex_lock(&pridebugfdlock);
8390 if (pridebugfd >= 0)
8391 write(pridebugfd, s, strlen(s));
8393 ast_mutex_unlock(&pridebugfdlock);
8396 static int pri_check_restart(struct dahdi_pri *pri)
8398 do {
8399 pri->resetpos++;
8400 } while ((pri->resetpos < pri->numchans) &&
8401 (!pri->pvts[pri->resetpos] ||
8402 pri->pvts[pri->resetpos]->call ||
8403 pri->pvts[pri->resetpos]->resetting));
8404 if (pri->resetpos < pri->numchans) {
8405 /* Mark the channel as resetting and restart it */
8406 pri->pvts[pri->resetpos]->resetting = 1;
8407 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8408 } else {
8409 pri->resetting = 0;
8410 time(&pri->lastreset);
8412 return 0;
8415 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
8417 int x;
8418 int redo;
8419 ast_mutex_unlock(&pri->lock);
8420 ast_mutex_lock(&p->lock);
8421 do {
8422 redo = 0;
8423 for (x = 0; x < 3; x++) {
8424 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
8425 redo++;
8426 DEADLOCK_AVOIDANCE(&p->lock);
8428 if (p->subs[x].owner) {
8429 ast_queue_hangup(p->subs[x].owner);
8430 ast_mutex_unlock(&p->subs[x].owner->lock);
8433 } while (redo);
8434 ast_mutex_unlock(&p->lock);
8435 ast_mutex_lock(&pri->lock);
8436 return 0;
8439 static char * redirectingreason2str(int redirectingreason)
8441 switch (redirectingreason) {
8442 case 0:
8443 return "UNKNOWN";
8444 case 1:
8445 return "BUSY";
8446 case 2:
8447 return "NO_REPLY";
8448 case 0xF:
8449 return "UNCONDITIONAL";
8450 default:
8451 return "NOREDIRECT";
8455 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
8457 switch (plan) {
8458 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8459 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
8460 break;
8461 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8462 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
8463 break;
8464 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8465 snprintf(buf, size, "%s%s", pri->localprefix, number);
8466 break;
8467 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8468 snprintf(buf, size, "%s%s", pri->privateprefix, number);
8469 break;
8470 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8471 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
8472 break;
8473 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8474 snprintf(buf, size, "%s", number);
8475 break;
8479 static int dahdi_setlaw(int dfd, int law)
8481 int res;
8482 res = ioctl(dfd, DAHDI_SETLAW, &law);
8483 if (res)
8484 return res;
8485 return 0;
8488 static void *pri_dchannel(void *vpri)
8490 struct dahdi_pri *pri = vpri;
8491 pri_event *e;
8492 struct pollfd fds[NUM_DCHANS];
8493 int res;
8494 int chanpos = 0;
8495 int x;
8496 int haveidles;
8497 int activeidles;
8498 int nextidle = -1;
8499 struct ast_channel *c;
8500 struct timeval tv, lowest, *next;
8501 struct timeval lastidle = { 0, 0 };
8502 int doidling=0;
8503 char *cc;
8504 char idlen[80];
8505 struct ast_channel *idle;
8506 pthread_t p;
8507 time_t t;
8508 int i, which=-1;
8509 int numdchans;
8510 int cause=0;
8511 struct dahdi_pvt *crv;
8512 pthread_t threadid;
8513 pthread_attr_t attr;
8514 char ani2str[6];
8515 char plancallingnum[256];
8516 char plancallingani[256];
8517 char calledtonstr[10];
8519 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
8521 gettimeofday(&lastidle, NULL);
8522 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
8523 /* Need to do idle dialing, check to be sure though */
8524 cc = strchr(pri->idleext, '@');
8525 if (cc) {
8526 *cc = '\0';
8527 cc++;
8528 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
8529 #if 0
8530 /* Extensions may not be loaded yet */
8531 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
8532 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
8533 else
8534 #endif
8535 doidling = 1;
8536 } else
8537 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
8539 for (;;) {
8540 for (i = 0; i < NUM_DCHANS; i++) {
8541 if (!pri->dchannels[i])
8542 break;
8543 fds[i].fd = pri->fds[i];
8544 fds[i].events = POLLIN | POLLPRI;
8545 fds[i].revents = 0;
8547 numdchans = i;
8548 time(&t);
8549 ast_mutex_lock(&pri->lock);
8550 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
8551 if (pri->resetting && pri_is_up(pri)) {
8552 if (pri->resetpos < 0)
8553 pri_check_restart(pri);
8554 } else {
8555 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
8556 pri->resetting = 1;
8557 pri->resetpos = -1;
8561 /* Look for any idle channels if appropriate */
8562 if (doidling && pri_is_up(pri)) {
8563 nextidle = -1;
8564 haveidles = 0;
8565 activeidles = 0;
8566 for (x = pri->numchans; x >= 0; x--) {
8567 if (pri->pvts[x] && !pri->pvts[x]->owner &&
8568 !pri->pvts[x]->call) {
8569 if (haveidles < pri->minunused) {
8570 haveidles++;
8571 } else if (!pri->pvts[x]->resetting) {
8572 nextidle = x;
8573 break;
8575 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
8576 activeidles++;
8578 if (nextidle > -1) {
8579 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
8580 /* Don't create a new idle call more than once per second */
8581 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
8582 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
8583 if (idle) {
8584 pri->pvts[nextidle]->isidlecall = 1;
8585 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
8586 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
8587 dahdi_hangup(idle);
8589 } else
8590 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
8591 gettimeofday(&lastidle, NULL);
8593 } else if ((haveidles < pri->minunused) &&
8594 (activeidles > pri->minidle)) {
8595 /* Mark something for hangup if there is something
8596 that can be hungup */
8597 for (x = pri->numchans; x >= 0; x--) {
8598 /* find a candidate channel */
8599 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
8600 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8601 haveidles++;
8602 /* Stop if we have enough idle channels or
8603 can't spare any more active idle ones */
8604 if ((haveidles >= pri->minunused) ||
8605 (activeidles <= pri->minidle))
8606 break;
8611 /* Start with reasonable max */
8612 lowest = ast_tv(60, 0);
8613 for (i = 0; i < NUM_DCHANS; i++) {
8614 /* Find lowest available d-channel */
8615 if (!pri->dchannels[i])
8616 break;
8617 if ((next = pri_schedule_next(pri->dchans[i]))) {
8618 /* We need relative time here */
8619 tv = ast_tvsub(*next, ast_tvnow());
8620 if (tv.tv_sec < 0) {
8621 tv = ast_tv(0,0);
8623 if (doidling || pri->resetting) {
8624 if (tv.tv_sec > 1) {
8625 tv = ast_tv(1, 0);
8627 } else {
8628 if (tv.tv_sec > 60) {
8629 tv = ast_tv(60, 0);
8632 } else if (doidling || pri->resetting) {
8633 /* Make sure we stop at least once per second if we're
8634 monitoring idle channels */
8635 tv = ast_tv(1,0);
8636 } else {
8637 /* Don't poll for more than 60 seconds */
8638 tv = ast_tv(60, 0);
8640 if (!i || ast_tvcmp(tv, lowest) < 0) {
8641 lowest = tv;
8644 ast_mutex_unlock(&pri->lock);
8646 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
8647 pthread_testcancel();
8648 e = NULL;
8649 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
8650 pthread_testcancel();
8651 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
8653 ast_mutex_lock(&pri->lock);
8654 if (!res) {
8655 for (which = 0; which < NUM_DCHANS; which++) {
8656 if (!pri->dchans[which])
8657 break;
8658 /* Just a timeout, run the scheduler */
8659 e = pri_schedule_run(pri->dchans[which]);
8660 if (e)
8661 break;
8663 } else if (res > -1) {
8664 for (which = 0; which < NUM_DCHANS; which++) {
8665 if (!pri->dchans[which])
8666 break;
8667 if (fds[which].revents & POLLPRI) {
8668 /* Check for an event */
8669 x = 0;
8670 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
8671 if (x)
8672 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);
8673 /* Keep track of alarm state */
8674 if (x == DAHDI_EVENT_ALARM) {
8675 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8676 pri_find_dchan(pri);
8677 } else if (x == DAHDI_EVENT_NOALARM) {
8678 pri->dchanavail[which] |= DCHAN_NOTINALARM;
8679 pri_restart(pri->dchans[which]);
8682 if (option_debug)
8683 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
8684 } else if (fds[which].revents & POLLIN) {
8685 e = pri_check_event(pri->dchans[which]);
8687 if (e)
8688 break;
8690 } else if (errno != EINTR)
8691 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8693 if (e) {
8694 if (pri->debug)
8695 pri_dump_event(pri->dchans[which], e);
8697 if (e->e != PRI_EVENT_DCHAN_DOWN) {
8698 if (!(pri->dchanavail[which] & DCHAN_UP)) {
8699 if (option_verbose > 1)
8700 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8702 pri->dchanavail[which] |= DCHAN_UP;
8703 } else {
8704 if (pri->dchanavail[which] & DCHAN_UP) {
8705 if (option_verbose > 1)
8706 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8708 pri->dchanavail[which] &= ~DCHAN_UP;
8711 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
8712 /* Must be an NFAS group that has the secondary dchan active */
8713 pri->pri = pri->dchans[which];
8715 switch (e->e) {
8716 case PRI_EVENT_DCHAN_UP:
8717 if (!pri->pri) pri_find_dchan(pri);
8719 /* Note presense of D-channel */
8720 time(&pri->lastreset);
8722 /* Restart in 5 seconds */
8723 if (pri->resetinterval > -1) {
8724 pri->lastreset -= pri->resetinterval;
8725 pri->lastreset += 5;
8727 pri->resetting = 0;
8728 /* Take the channels from inalarm condition */
8729 for (i = 0; i < pri->numchans; i++)
8730 if (pri->pvts[i]) {
8731 pri->pvts[i]->inalarm = 0;
8733 break;
8734 case PRI_EVENT_DCHAN_DOWN:
8735 pri_find_dchan(pri);
8736 if (!pri_is_up(pri)) {
8737 pri->resetting = 0;
8738 /* Hangup active channels and put them in alarm mode */
8739 for (i = 0; i < pri->numchans; i++) {
8740 struct dahdi_pvt *p = pri->pvts[i];
8741 if (p) {
8742 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8743 /* T309 is not enabled : hangup calls when alarm occurs */
8744 if (p->call) {
8745 if (p->pri && p->pri->pri) {
8746 pri_hangup(p->pri->pri, p->call, -1);
8747 pri_destroycall(p->pri->pri, p->call);
8748 p->call = NULL;
8749 } else
8750 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8752 if (p->realcall) {
8753 pri_hangup_all(p->realcall, pri);
8754 } else if (p->owner)
8755 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8757 p->inalarm = 1;
8761 break;
8762 case PRI_EVENT_RESTART:
8763 if (e->restart.channel > -1) {
8764 chanpos = pri_find_principle(pri, e->restart.channel);
8765 if (chanpos < 0)
8766 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8767 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8768 else {
8769 if (option_verbose > 2)
8770 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
8771 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8772 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8773 if (pri->pvts[chanpos]->call) {
8774 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
8775 pri->pvts[chanpos]->call = NULL;
8777 /* Force soft hangup if appropriate */
8778 if (pri->pvts[chanpos]->realcall)
8779 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8780 else if (pri->pvts[chanpos]->owner)
8781 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8782 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8784 } else {
8785 if (option_verbose > 2)
8786 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
8787 for (x = 0; x < pri->numchans; x++)
8788 if (pri->pvts[x]) {
8789 ast_mutex_lock(&pri->pvts[x]->lock);
8790 if (pri->pvts[x]->call) {
8791 pri_destroycall(pri->pri, pri->pvts[x]->call);
8792 pri->pvts[x]->call = NULL;
8794 if (pri->pvts[chanpos]->realcall)
8795 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8796 else if (pri->pvts[x]->owner)
8797 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8798 ast_mutex_unlock(&pri->pvts[x]->lock);
8801 break;
8802 case PRI_EVENT_KEYPAD_DIGIT:
8803 chanpos = pri_find_principle(pri, e->digit.channel);
8804 if (chanpos < 0) {
8805 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8806 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
8807 } else {
8808 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
8809 if (chanpos > -1) {
8810 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8811 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8812 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
8813 /* how to do that */
8814 int digitlen = strlen(e->digit.digits);
8815 char digit;
8816 int i;
8817 for (i = 0; i < digitlen; i++) {
8818 digit = e->digit.digits[i];
8820 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8821 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8825 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8828 break;
8830 case PRI_EVENT_INFO_RECEIVED:
8831 chanpos = pri_find_principle(pri, e->ring.channel);
8832 if (chanpos < 0) {
8833 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
8834 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8835 } else {
8836 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8837 if (chanpos > -1) {
8838 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8839 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8840 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8841 /* how to do that */
8842 int digitlen = strlen(e->ring.callednum);
8843 char digit;
8844 int i;
8845 for (i = 0; i < digitlen; i++) {
8846 digit = e->ring.callednum[i];
8848 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8849 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8853 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8856 break;
8857 case PRI_EVENT_RING:
8858 crv = NULL;
8859 if (e->ring.channel == -1)
8860 chanpos = pri_find_empty_chan(pri, 1);
8861 else
8862 chanpos = pri_find_principle(pri, e->ring.channel);
8863 /* if no channel specified find one empty */
8864 if (chanpos < 0) {
8865 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8866 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8867 } else {
8868 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8869 if (pri->pvts[chanpos]->owner) {
8870 if (pri->pvts[chanpos]->call == e->ring.call) {
8871 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8872 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8873 break;
8874 } else {
8875 /* This is where we handle initial glare */
8876 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8877 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8878 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8879 chanpos = -1;
8882 if (chanpos > -1)
8883 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8885 if ((chanpos < 0) && (e->ring.flexible))
8886 chanpos = pri_find_empty_chan(pri, 1);
8887 if (chanpos > -1) {
8888 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8889 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8890 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8891 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8892 if (crv)
8893 ast_mutex_lock(&crv->lock);
8894 if (!crv || crv->owner) {
8895 pri->pvts[chanpos]->call = NULL;
8896 if (crv) {
8897 if (crv->owner)
8898 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8899 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);
8900 } else
8901 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);
8902 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8903 if (crv)
8904 ast_mutex_unlock(&crv->lock);
8905 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8906 break;
8909 pri->pvts[chanpos]->call = e->ring.call;
8910 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8911 if (pri->pvts[chanpos]->use_callerid) {
8912 ast_shrink_phone_number(plancallingnum);
8913 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
8914 #ifdef PRI_ANI
8915 if (!ast_strlen_zero(e->ring.callingani)) {
8916 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
8917 ast_shrink_phone_number(plancallingani);
8918 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
8919 } else {
8920 pri->pvts[chanpos]->cid_ani[0] = '\0';
8922 #endif
8923 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
8924 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8925 } else {
8926 pri->pvts[chanpos]->cid_num[0] = '\0';
8927 pri->pvts[chanpos]->cid_ani[0] = '\0';
8928 pri->pvts[chanpos]->cid_name[0] = '\0';
8929 pri->pvts[chanpos]->cid_ton = 0;
8931 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8932 e->ring.redirectingnum, e->ring.callingplanrdnis);
8933 /* If immediate=yes go to s|1 */
8934 if (pri->pvts[chanpos]->immediate) {
8935 if (option_verbose > 2)
8936 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8937 pri->pvts[chanpos]->exten[0] = 's';
8938 pri->pvts[chanpos]->exten[1] = '\0';
8940 /* Get called number */
8941 else if (!ast_strlen_zero(e->ring.callednum)) {
8942 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8943 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8944 } else if (pri->overlapdial)
8945 pri->pvts[chanpos]->exten[0] = '\0';
8946 else {
8947 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8948 pri->pvts[chanpos]->exten[0] = 's';
8949 pri->pvts[chanpos]->exten[1] = '\0';
8951 /* Set DNID on all incoming calls -- even immediate */
8952 if (!ast_strlen_zero(e->ring.callednum))
8953 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8954 /* No number yet, but received "sending complete"? */
8955 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8956 if (option_verbose > 2)
8957 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8958 pri->pvts[chanpos]->exten[0] = 's';
8959 pri->pvts[chanpos]->exten[1] = '\0';
8961 /* Make sure extension exists (or in overlap dial mode, can exist) */
8962 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8963 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8964 /* Setup law */
8965 int law;
8966 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
8967 /* Set to audio mode at this point */
8968 law = 1;
8969 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
8970 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
8972 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
8973 law = DAHDI_LAW_ALAW;
8974 else
8975 law = DAHDI_LAW_MULAW;
8976 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
8977 if (res < 0)
8978 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
8979 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
8980 if (res < 0)
8981 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
8982 if (e->ring.complete || !pri->overlapdial) {
8983 /* Just announce proceeding */
8984 pri->pvts[chanpos]->proceeding = 1;
8985 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
8986 } else {
8987 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
8988 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8989 else
8990 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
8992 /* Get the use_callingpres state */
8993 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
8995 /* Start PBX */
8996 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8997 /* Release the PRI lock while we create the channel */
8998 ast_mutex_unlock(&pri->lock);
8999 if (crv) {
9000 /* Set bearer and such */
9001 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
9002 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9003 pri->pvts[chanpos]->owner = &inuse;
9004 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
9005 } else {
9006 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9009 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9011 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
9012 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
9014 if (e->ring.ani2 >= 0) {
9015 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
9016 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9019 #ifdef SUPPORT_USERUSER
9020 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9021 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9023 #endif
9025 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9026 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9027 if (e->ring.redirectingreason >= 0)
9028 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9030 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9031 ast_mutex_lock(&pri->lock);
9033 pthread_attr_init(&attr);
9034 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
9035 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
9036 if (option_verbose > 2)
9037 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
9038 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
9039 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9040 } else {
9041 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9042 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9043 if (c)
9044 ast_hangup(c);
9045 else {
9046 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9047 pri->pvts[chanpos]->call = NULL;
9050 pthread_attr_destroy(&attr);
9051 } else {
9052 ast_mutex_unlock(&pri->lock);
9053 /* Release PRI lock while we create the channel */
9054 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
9055 if (c) {
9056 char calledtonstr[10];
9058 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9060 if (e->ring.ani2 >= 0) {
9061 snprintf(ani2str, 5, "%d", e->ring.ani2);
9062 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9065 #ifdef SUPPORT_USERUSER
9066 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9067 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9069 #endif
9071 if (e->ring.redirectingreason >= 0)
9072 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9074 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9075 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9077 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9078 ast_mutex_lock(&pri->lock);
9080 if (option_verbose > 2)
9081 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
9082 plancallingnum, pri->pvts[chanpos]->exten,
9083 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9084 dahdi_enable_ec(pri->pvts[chanpos]);
9085 } else {
9087 ast_mutex_lock(&pri->lock);
9089 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9090 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9091 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9092 pri->pvts[chanpos]->call = NULL;
9095 } else {
9096 if (option_verbose > 2)
9097 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9098 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
9099 pri->pvts[chanpos]->prioffset, pri->span);
9100 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
9101 pri->pvts[chanpos]->call = NULL;
9102 pri->pvts[chanpos]->exten[0] = '\0';
9104 if (crv)
9105 ast_mutex_unlock(&crv->lock);
9106 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9107 } else {
9108 if (e->ring.flexible)
9109 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
9110 else
9111 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
9113 break;
9114 case PRI_EVENT_RINGING:
9115 chanpos = pri_find_principle(pri, e->ringing.channel);
9116 if (chanpos < 0) {
9117 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9118 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9119 } else {
9120 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9121 if (chanpos < 0) {
9122 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9123 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9124 } else {
9125 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9126 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9127 dahdi_enable_ec(pri->pvts[chanpos]);
9128 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9129 pri->pvts[chanpos]->alerting = 1;
9130 } else
9131 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9132 #ifdef PRI_PROGRESS_MASK
9133 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9134 #else
9135 if (e->ringing.progress == 8) {
9136 #endif
9137 /* Now we can do call progress detection */
9138 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9139 /* RINGING detection isn't required because we got ALERTING signal */
9140 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9141 pri->pvts[chanpos]->dsp_features = 0;
9145 #ifdef SUPPORT_USERUSER
9146 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9147 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9148 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9149 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9150 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9152 #endif
9154 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9157 break;
9158 case PRI_EVENT_PROGRESS:
9159 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9160 chanpos = pri_find_principle(pri, e->proceeding.channel);
9161 if (chanpos > -1) {
9162 #ifdef PRI_PROGRESS_MASK
9163 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9164 #else
9165 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9166 #endif
9167 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9169 if (e->proceeding.cause > -1) {
9170 if (option_verbose > 2)
9171 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9173 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9174 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9175 if (pri->pvts[chanpos]->owner) {
9176 if (option_verbose > 2)
9177 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9179 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9180 f.subclass = AST_CONTROL_BUSY;
9185 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9186 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9187 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9188 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9189 #ifdef PRI_PROGRESS_MASK
9190 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9191 #else
9192 if (e->proceeding.progress == 8) {
9193 #endif
9194 /* Now we can do call progress detection */
9195 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9196 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9197 pri->pvts[chanpos]->dsp_features = 0;
9200 pri->pvts[chanpos]->progress = 1;
9201 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9204 break;
9205 case PRI_EVENT_PROCEEDING:
9206 chanpos = pri_find_principle(pri, e->proceeding.channel);
9207 if (chanpos > -1) {
9208 if (!pri->pvts[chanpos]->proceeding) {
9209 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9211 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9212 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9213 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9214 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9215 #ifdef PRI_PROGRESS_MASK
9216 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9217 #else
9218 if (e->proceeding.progress == 8) {
9219 #endif
9220 /* Now we can do call progress detection */
9221 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9222 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9223 pri->pvts[chanpos]->dsp_features = 0;
9225 /* Bring voice path up */
9226 f.subclass = AST_CONTROL_PROGRESS;
9227 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9229 pri->pvts[chanpos]->proceeding = 1;
9230 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9233 break;
9234 case PRI_EVENT_FACNAME:
9235 chanpos = pri_find_principle(pri, e->facname.channel);
9236 if (chanpos < 0) {
9237 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9238 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9239 } else {
9240 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
9241 if (chanpos < 0) {
9242 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
9243 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9244 } else {
9245 /* Re-use *69 field for PRI */
9246 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9247 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
9248 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
9249 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
9250 dahdi_enable_ec(pri->pvts[chanpos]);
9251 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9254 break;
9255 case PRI_EVENT_ANSWER:
9256 chanpos = pri_find_principle(pri, e->answer.channel);
9257 if (chanpos < 0) {
9258 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
9259 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9260 } else {
9261 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
9262 if (chanpos < 0) {
9263 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
9264 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9265 } else {
9266 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9267 /* Now we can do call progress detection */
9269 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9270 * By this time, we need DTMF detection and other features that were previously disabled
9271 * -- Matt F */
9272 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9273 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9274 pri->pvts[chanpos]->dsp_features = 0;
9276 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
9277 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
9278 x = DAHDI_START;
9279 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
9280 if (res < 0) {
9281 if (errno != EINPROGRESS) {
9282 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
9285 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9286 pri->pvts[chanpos]->dialing = 1;
9287 /* Send any "w" waited stuff */
9288 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
9289 if (res < 0) {
9290 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
9291 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9292 } else
9293 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9294 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9295 } else if (pri->pvts[chanpos]->confirmanswer) {
9296 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9297 } else {
9298 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9299 /* Enable echo cancellation if it's not on already */
9300 dahdi_enable_ec(pri->pvts[chanpos]);
9303 #ifdef SUPPORT_USERUSER
9304 if (!ast_strlen_zero(e->answer.useruserinfo)) {
9305 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9306 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9307 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
9308 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9310 #endif
9312 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9315 break;
9316 case PRI_EVENT_HANGUP:
9317 chanpos = pri_find_principle(pri, e->hangup.channel);
9318 if (chanpos < 0) {
9319 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
9320 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9321 } else {
9322 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9323 if (chanpos > -1) {
9324 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9325 if (!pri->pvts[chanpos]->alreadyhungup) {
9326 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9327 pri->pvts[chanpos]->alreadyhungup = 1;
9328 if (pri->pvts[chanpos]->realcall)
9329 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9330 else if (pri->pvts[chanpos]->owner) {
9331 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9332 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9333 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9334 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9335 else {
9336 switch (e->hangup.cause) {
9337 case PRI_CAUSE_USER_BUSY:
9338 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9339 break;
9340 case PRI_CAUSE_CALL_REJECTED:
9341 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9342 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9343 case PRI_CAUSE_SWITCH_CONGESTION:
9344 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9345 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9346 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9347 break;
9348 default:
9349 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9353 if (option_verbose > 2)
9354 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9355 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9356 } else {
9357 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9358 pri->pvts[chanpos]->call = NULL;
9360 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9361 if (option_verbose > 2)
9362 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9363 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9364 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9365 pri->pvts[chanpos]->resetting = 1;
9367 if (e->hangup.aoc_units > -1)
9368 if (option_verbose > 2)
9369 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9370 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9372 #ifdef SUPPORT_USERUSER
9373 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
9374 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9375 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9376 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9377 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9379 #endif
9381 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9382 } else {
9383 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9384 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9387 break;
9388 #ifndef PRI_EVENT_HANGUP_REQ
9389 #error please update libpri
9390 #endif
9391 case PRI_EVENT_HANGUP_REQ:
9392 chanpos = pri_find_principle(pri, e->hangup.channel);
9393 if (chanpos < 0) {
9394 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9395 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9396 } else {
9397 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9398 if (chanpos > -1) {
9399 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9400 if (pri->pvts[chanpos]->realcall)
9401 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9402 else if (pri->pvts[chanpos]->owner) {
9403 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9404 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9405 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9406 else {
9407 switch (e->hangup.cause) {
9408 case PRI_CAUSE_USER_BUSY:
9409 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9410 break;
9411 case PRI_CAUSE_CALL_REJECTED:
9412 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9413 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9414 case PRI_CAUSE_SWITCH_CONGESTION:
9415 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9416 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9417 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9418 break;
9419 default:
9420 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9423 if (option_verbose > 2)
9424 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);
9425 if (e->hangup.aoc_units > -1)
9426 if (option_verbose > 2)
9427 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9428 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9429 } else {
9430 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9431 pri->pvts[chanpos]->call = NULL;
9433 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9434 if (option_verbose > 2)
9435 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9436 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9437 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9438 pri->pvts[chanpos]->resetting = 1;
9441 #ifdef SUPPORT_USERUSER
9442 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9443 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9444 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9445 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9446 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9448 #endif
9450 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9451 } else {
9452 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);
9455 break;
9456 case PRI_EVENT_HANGUP_ACK:
9457 chanpos = pri_find_principle(pri, e->hangup.channel);
9458 if (chanpos < 0) {
9459 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9460 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9461 } else {
9462 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9463 if (chanpos > -1) {
9464 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9465 pri->pvts[chanpos]->call = NULL;
9466 pri->pvts[chanpos]->resetting = 0;
9467 if (pri->pvts[chanpos]->owner) {
9468 if (option_verbose > 2)
9469 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);
9472 #ifdef SUPPORT_USERUSER
9473 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9474 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9475 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9476 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9477 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9479 #endif
9481 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9484 break;
9485 case PRI_EVENT_CONFIG_ERR:
9486 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
9487 break;
9488 case PRI_EVENT_RESTART_ACK:
9489 chanpos = pri_find_principle(pri, e->restartack.channel);
9490 if (chanpos < 0) {
9491 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9492 channel number, so we have to figure it out... This must be why
9493 everybody resets exactly a channel at a time. */
9494 for (x = 0; x < pri->numchans; x++) {
9495 if (pri->pvts[x] && pri->pvts[x]->resetting) {
9496 chanpos = x;
9497 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9498 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
9499 pri->pvts[chanpos]->prioffset, pri->span);
9500 if (pri->pvts[chanpos]->realcall)
9501 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9502 else if (pri->pvts[chanpos]->owner) {
9503 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
9504 pri->pvts[chanpos]->prioffset, pri->span);
9505 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9507 pri->pvts[chanpos]->resetting = 0;
9508 if (option_verbose > 2)
9509 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9510 pri->pvts[chanpos]->prioffset, pri->span);
9511 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9512 if (pri->resetting)
9513 pri_check_restart(pri);
9514 break;
9517 if (chanpos < 0) {
9518 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
9519 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9521 } else {
9522 if (pri->pvts[chanpos]) {
9523 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9524 if (pri->pvts[chanpos]->realcall)
9525 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9526 else if (pri->pvts[chanpos]->owner) {
9527 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
9528 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9529 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9531 pri->pvts[chanpos]->resetting = 0;
9532 if (option_verbose > 2)
9533 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9534 pri->pvts[chanpos]->prioffset, pri->span);
9535 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9536 if (pri->resetting)
9537 pri_check_restart(pri);
9540 break;
9541 case PRI_EVENT_SETUP_ACK:
9542 chanpos = pri_find_principle(pri, e->setup_ack.channel);
9543 if (chanpos < 0) {
9544 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9545 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
9546 } else {
9547 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
9548 if (chanpos > -1) {
9549 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9550 pri->pvts[chanpos]->setup_ack = 1;
9551 /* Send any queued digits */
9552 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
9553 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
9554 pri_information(pri->pri, pri->pvts[chanpos]->call,
9555 pri->pvts[chanpos]->dialdest[x]);
9557 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9558 } else
9559 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
9561 break;
9562 case PRI_EVENT_NOTIFY:
9563 chanpos = pri_find_principle(pri, e->notify.channel);
9564 if (chanpos < 0) {
9565 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9566 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
9567 } else {
9568 struct ast_frame f = { AST_FRAME_CONTROL, };
9569 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9570 switch (e->notify.info) {
9571 case PRI_NOTIFY_REMOTE_HOLD:
9572 f.subclass = AST_CONTROL_HOLD;
9573 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9574 break;
9575 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9576 f.subclass = AST_CONTROL_UNHOLD;
9577 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9578 break;
9580 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9582 break;
9583 default:
9584 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9587 ast_mutex_unlock(&pri->lock);
9589 /* Never reached */
9590 return NULL;
9593 static int start_pri(struct dahdi_pri *pri)
9595 int res, x;
9596 struct dahdi_params p;
9597 struct dahdi_bufferinfo bi;
9598 struct dahdi_spaninfo si;
9599 int i;
9601 for (i = 0; i < NUM_DCHANS; i++) {
9602 if (!pri->dchannels[i])
9603 break;
9604 #ifdef HAVE_ZAPTEL
9605 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
9606 #else
9607 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
9608 #endif
9609 x = pri->dchannels[i];
9610 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
9611 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
9612 return -1;
9614 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
9615 if (res) {
9616 dahdi_close(pri->fds[i]);
9617 pri->fds[i] = -1;
9618 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
9619 return -1;
9621 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
9622 dahdi_close(pri->fds[i]);
9623 pri->fds[i] = -1;
9624 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/DAHDI.conf\n", x);
9625 return -1;
9627 memset(&si, 0, sizeof(si));
9628 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
9629 if (res) {
9630 dahdi_close(pri->fds[i]);
9631 pri->fds[i] = -1;
9632 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
9634 if (!si.alarms)
9635 pri->dchanavail[i] |= DCHAN_NOTINALARM;
9636 else
9637 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
9638 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
9639 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
9640 bi.numbufs = 32;
9641 bi.bufsize = 1024;
9642 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
9643 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
9644 dahdi_close(pri->fds[i]);
9645 pri->fds[i] = -1;
9646 return -1;
9648 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9649 /* Force overlap dial if we're doing GR-303! */
9650 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9651 pri->overlapdial = 1;
9652 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
9653 #ifdef HAVE_PRI_INBANDDISCONNECT
9654 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
9655 #endif
9656 /* Enslave to master if appropriate */
9657 if (i)
9658 pri_enslave(pri->dchans[0], pri->dchans[i]);
9659 if (!pri->dchans[i]) {
9660 dahdi_close(pri->fds[i]);
9661 pri->fds[i] = -1;
9662 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
9663 return -1;
9665 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
9666 pri_set_nsf(pri->dchans[i], pri->nsf);
9667 #ifdef PRI_GETSET_TIMERS
9668 for (x = 0; x < PRI_MAX_TIMERS; x++) {
9669 if (pritimers[x] != 0)
9670 pri_set_timer(pri->dchans[i], x, pritimers[x]);
9672 #endif
9674 /* Assume primary is the one we use */
9675 pri->pri = pri->dchans[0];
9676 pri->resetpos = -1;
9677 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
9678 for (i = 0; i < NUM_DCHANS; i++) {
9679 if (!pri->dchannels[i])
9680 break;
9681 dahdi_close(pri->fds[i]);
9682 pri->fds[i] = -1;
9684 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
9685 return -1;
9687 return 0;
9690 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
9692 int which, span;
9693 char *ret = NULL;
9695 if (pos != rpos)
9696 return ret;
9698 for (which = span = 0; span < NUM_SPANS; span++) {
9699 if (pris[span].pri && ++which > state) {
9700 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
9701 break;
9704 return ret;
9707 static char *complete_span_4(const char *line, const char *word, int pos, int state)
9709 return complete_span_helper(line,word,pos,state,3);
9712 static char *complete_span_5(const char *line, const char *word, int pos, int state)
9714 return complete_span_helper(line,word,pos,state,4);
9717 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9719 int myfd;
9721 if (!strncasecmp(argv[1], "set", 3)) {
9722 if (argc < 5)
9723 return RESULT_SHOWUSAGE;
9725 if (ast_strlen_zero(argv[4]))
9726 return RESULT_SHOWUSAGE;
9728 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
9729 if (myfd < 0) {
9730 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9731 return RESULT_SUCCESS;
9734 ast_mutex_lock(&pridebugfdlock);
9736 if (pridebugfd >= 0)
9737 close(pridebugfd);
9739 pridebugfd = myfd;
9740 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9742 ast_mutex_unlock(&pridebugfdlock);
9744 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9745 } else {
9746 /* Assume it is unset */
9747 ast_mutex_lock(&pridebugfdlock);
9748 close(pridebugfd);
9749 pridebugfd = -1;
9750 ast_cli(fd, "PRI debug output to file disabled\n");
9751 ast_mutex_unlock(&pridebugfdlock);
9754 return RESULT_SUCCESS;
9757 #ifdef HAVE_PRI_VERSION
9758 static int handle_pri_version(int fd, int agc, char *argv[]) {
9759 ast_cli(fd, "libpri version: %s\n", pri_get_version());
9760 return RESULT_SUCCESS;
9762 #endif
9764 static int handle_pri_debug(int fd, int argc, char *argv[])
9766 int span;
9767 int x;
9768 if (argc < 4) {
9769 return RESULT_SHOWUSAGE;
9771 span = atoi(argv[3]);
9772 if ((span < 1) || (span > NUM_SPANS)) {
9773 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
9774 return RESULT_SUCCESS;
9776 if (!pris[span-1].pri) {
9777 ast_cli(fd, "No PRI running on span %d\n", span);
9778 return RESULT_SUCCESS;
9780 for (x = 0; x < NUM_DCHANS; x++) {
9781 if (pris[span-1].dchans[x])
9782 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9783 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9784 PRI_DEBUG_Q921_STATE);
9786 ast_cli(fd, "Enabled debugging on span %d\n", span);
9787 return RESULT_SUCCESS;
9792 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9794 int span;
9795 int x;
9796 if (argc < 5)
9797 return RESULT_SHOWUSAGE;
9798 span = atoi(argv[4]);
9799 if ((span < 1) || (span > NUM_SPANS)) {
9800 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9801 return RESULT_SUCCESS;
9803 if (!pris[span-1].pri) {
9804 ast_cli(fd, "No PRI running on span %d\n", span);
9805 return RESULT_SUCCESS;
9807 for (x = 0; x < NUM_DCHANS; x++) {
9808 if (pris[span-1].dchans[x])
9809 pri_set_debug(pris[span-1].dchans[x], 0);
9811 ast_cli(fd, "Disabled debugging on span %d\n", span);
9812 return RESULT_SUCCESS;
9815 static int handle_pri_really_debug(int fd, int argc, char *argv[])
9817 int span;
9818 int x;
9819 if (argc < 5)
9820 return RESULT_SHOWUSAGE;
9821 span = atoi(argv[4]);
9822 if ((span < 1) || (span > NUM_SPANS)) {
9823 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9824 return RESULT_SUCCESS;
9826 if (!pris[span-1].pri) {
9827 ast_cli(fd, "No PRI running on span %d\n", span);
9828 return RESULT_SUCCESS;
9830 for (x = 0; x < NUM_DCHANS; x++) {
9831 if (pris[span-1].dchans[x])
9832 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9833 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9834 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
9836 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
9837 return RESULT_SUCCESS;
9840 static void build_status(char *s, size_t len, int status, int active)
9842 if (!s || len < 1) {
9843 return;
9845 s[0] = '\0';
9846 if (status & DCHAN_PROVISIONED)
9847 strncat(s, "Provisioned, ", len - strlen(s) - 1);
9848 if (!(status & DCHAN_NOTINALARM))
9849 strncat(s, "In Alarm, ", len - strlen(s) - 1);
9850 if (status & DCHAN_UP)
9851 strncat(s, "Up", len - strlen(s) - 1);
9852 else
9853 strncat(s, "Down", len - strlen(s) - 1);
9854 if (active)
9855 strncat(s, ", Active", len - strlen(s) - 1);
9856 else
9857 strncat(s, ", Standby", len - strlen(s) - 1);
9858 s[len - 1] = '\0';
9861 static int handle_pri_show_spans(int fd, int argc, char *argv[])
9863 int span;
9864 int x;
9865 char status[256];
9866 if (argc != 3)
9867 return RESULT_SHOWUSAGE;
9869 for (span = 0; span < NUM_SPANS; span++) {
9870 if (pris[span].pri) {
9871 for (x = 0; x < NUM_DCHANS; x++) {
9872 if (pris[span].dchannels[x]) {
9873 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
9874 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
9879 return RESULT_SUCCESS;
9882 static int handle_pri_show_span(int fd, int argc, char *argv[])
9884 int span;
9885 int x;
9886 char status[256];
9887 if (argc < 4)
9888 return RESULT_SHOWUSAGE;
9889 span = atoi(argv[3]);
9890 if ((span < 1) || (span > NUM_SPANS)) {
9891 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
9892 return RESULT_SUCCESS;
9894 if (!pris[span-1].pri) {
9895 ast_cli(fd, "No PRI running on span %d\n", span);
9896 return RESULT_SUCCESS;
9898 for (x = 0; x < NUM_DCHANS; x++) {
9899 if (pris[span-1].dchannels[x]) {
9900 #ifdef PRI_DUMP_INFO_STR
9901 char *info_str = NULL;
9902 #endif
9903 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
9904 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
9905 ast_cli(fd, "Status: %s\n", status);
9906 #ifdef PRI_DUMP_INFO_STR
9907 info_str = pri_dump_info_str(pris[span-1].pri);
9908 if (info_str) {
9909 ast_cli(fd, "%s", info_str);
9910 free(info_str);
9912 #else
9913 pri_dump_info(pris[span-1].pri);
9914 #endif
9915 ast_cli(fd, "\n");
9918 return RESULT_SUCCESS;
9921 static int handle_pri_show_debug(int fd, int argc, char *argv[])
9923 int x;
9924 int span;
9925 int count=0;
9926 int debug=0;
9928 for (span = 0; span < NUM_SPANS; span++) {
9929 if (pris[span].pri) {
9930 for (x = 0; x < NUM_DCHANS; x++) {
9931 debug = 0;
9932 if (pris[span].dchans[x]) {
9933 debug = pri_get_debug(pris[span].dchans[x]);
9934 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" );
9935 count++;
9941 ast_mutex_lock(&pridebugfdlock);
9942 if (pridebugfd >= 0)
9943 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9944 ast_mutex_unlock(&pridebugfdlock);
9946 if (!count)
9947 ast_cli(fd, "No debug set or no PRI running\n");
9948 return RESULT_SUCCESS;
9951 static const char pri_debug_help[] =
9952 "Usage: pri debug span <span>\n"
9953 " Enables debugging on a given PRI span\n";
9955 static const char pri_no_debug_help[] =
9956 "Usage: pri no debug span <span>\n"
9957 " Disables debugging on a given PRI span\n";
9959 static const char pri_really_debug_help[] =
9960 "Usage: pri intensive debug span <span>\n"
9961 " Enables debugging down to the Q.921 level\n";
9963 static const char pri_show_span_help[] =
9964 "Usage: pri show span <span>\n"
9965 " Displays PRI Information on a given PRI span\n";
9967 static const char pri_show_spans_help[] =
9968 "Usage: pri show spans\n"
9969 " Displays PRI Information\n";
9971 static struct ast_cli_entry dahdi_pri_cli[] = {
9972 { { "pri", "debug", "span", NULL },
9973 handle_pri_debug, "Enables PRI debugging on a span",
9974 pri_debug_help, complete_span_4 },
9976 { { "pri", "no", "debug", "span", NULL },
9977 handle_pri_no_debug, "Disables PRI debugging on a span",
9978 pri_no_debug_help, complete_span_5 },
9980 { { "pri", "intense", "debug", "span", NULL },
9981 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
9982 pri_really_debug_help, complete_span_5 },
9984 { { "pri", "show", "spans", NULL },
9985 handle_pri_show_spans, "Displays PRI Information",
9986 pri_show_spans_help },
9988 { { "pri", "show", "span", NULL },
9989 handle_pri_show_span, "Displays PRI Information",
9990 pri_show_span_help, complete_span_4 },
9992 { { "pri", "show", "debug", NULL },
9993 handle_pri_show_debug, "Displays current PRI debug settings" },
9995 { { "pri", "set", "debug", "file", NULL },
9996 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
9998 { { "pri", "unset", "debug", "file", NULL },
9999 handle_pri_set_debug_file, "Ends PRI debug output to file" },
10001 #ifdef HAVE_PRI_VERSION
10002 { { "pri", "show", "version", NULL },
10003 handle_pri_version, "Displays version of libpri" },
10004 #endif
10007 #endif /* HAVE_PRI */
10009 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10011 int channel;
10013 if (argc != 4)
10014 return RESULT_SHOWUSAGE;
10016 channel = atoi(argv[3]);
10018 return dahdi_destroy_channel_bynum(channel);
10021 static void dahdi_softhangup_all(void)
10023 struct dahdi_pvt *p;
10024 retry:
10025 ast_mutex_lock(&iflock);
10026 for (p = iflist; p; p = p->next) {
10027 ast_mutex_lock(&p->lock);
10028 if (p->owner && !p->restartpending) {
10029 if (ast_channel_trylock(p->owner)) {
10030 if (option_debug > 2)
10031 ast_verbose("Avoiding deadlock\n");
10032 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10033 ast_mutex_unlock(&p->lock);
10034 ast_mutex_unlock(&iflock);
10035 goto retry;
10037 if (option_debug > 2)
10038 ast_verbose("Softhanging up on %s\n", p->owner->name);
10039 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10040 p->restartpending = 1;
10041 num_restart_pending++;
10042 ast_channel_unlock(p->owner);
10044 ast_mutex_unlock(&p->lock);
10046 ast_mutex_unlock(&iflock);
10049 static int setup_dahdi(int reload);
10050 static int dahdi_restart(void)
10052 int i, j, cancel_code;
10053 struct dahdi_pvt *p;
10055 ast_mutex_lock(&restart_lock);
10057 if (option_verbose)
10058 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10059 dahdi_softhangup_all();
10060 if (option_verbose > 3)
10061 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10063 #if defined(HAVE_PRI)
10064 for (i = 0; i < NUM_SPANS; i++) {
10065 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10066 cancel_code = pthread_cancel(pris[i].master);
10067 pthread_kill(pris[i].master, SIGURG);
10068 if (option_debug > 3)
10069 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10070 pthread_join(pris[i].master, NULL);
10071 if (option_debug > 3)
10072 ast_verbose("Joined thread of span %d\n", i);
10075 #endif
10077 ast_mutex_lock(&monlock);
10078 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10079 cancel_code = pthread_cancel(monitor_thread);
10080 pthread_kill(monitor_thread, SIGURG);
10081 if (option_debug > 3)
10082 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10083 pthread_join(monitor_thread, NULL);
10084 if (option_debug > 3)
10085 ast_verbose("Joined monitor thread\n");
10087 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10089 ast_mutex_lock(&ss_thread_lock);
10090 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10091 int x = DAHDI_FLASH;
10092 if (option_debug > 2)
10093 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10095 for (p = iflist; p; p = p->next) {
10096 if (p->owner)
10097 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
10099 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10102 /* ensure any created channels before monitor threads were stopped are hungup */
10103 dahdi_softhangup_all();
10104 if (option_verbose > 3)
10105 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10106 destroy_all_channels();
10107 if (option_debug)
10108 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10110 ast_mutex_unlock(&monlock);
10112 #ifdef HAVE_PRI
10113 for (i = 0; i < NUM_SPANS; i++) {
10114 for (j = 0; j < NUM_DCHANS; j++)
10115 dahdi_close(pris[i].fds[j]);
10118 memset(pris, 0, sizeof(pris));
10119 for (i = 0; i < NUM_SPANS; i++) {
10120 ast_mutex_init(&pris[i].lock);
10121 pris[i].offset = -1;
10122 pris[i].master = AST_PTHREADT_NULL;
10123 for (j = 0; j < NUM_DCHANS; j++)
10124 pris[i].fds[j] = -1;
10126 pri_set_error(dahdi_pri_error);
10127 pri_set_message(dahdi_pri_message);
10128 #endif
10130 if (setup_dahdi(2) != 0) {
10131 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10132 ast_mutex_unlock(&ss_thread_lock);
10133 return 1;
10135 ast_mutex_unlock(&ss_thread_lock);
10136 ast_mutex_unlock(&restart_lock);
10137 return 0;
10140 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10142 if (argc != 2) {
10143 return RESULT_SHOWUSAGE;
10146 if (dahdi_restart() != 0)
10147 return RESULT_FAILURE;
10148 return RESULT_SUCCESS;
10151 static int dahdi_show_channels(int fd, int argc, char **argv)
10153 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10154 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10155 struct dahdi_pvt *tmp = NULL;
10156 char tmps[20] = "";
10157 ast_mutex_t *lock;
10158 struct dahdi_pvt *start;
10159 #ifdef HAVE_PRI
10160 int trunkgroup;
10161 struct dahdi_pri *pri = NULL;
10162 int x;
10163 #endif
10165 lock = &iflock;
10166 start = iflist;
10168 #ifdef HAVE_PRI
10169 if (argc == 4) {
10170 if ((trunkgroup = atoi(argv[3])) < 1)
10171 return RESULT_SHOWUSAGE;
10172 for (x = 0; x < NUM_SPANS; x++) {
10173 if (pris[x].trunkgroup == trunkgroup) {
10174 pri = pris + x;
10175 break;
10178 if (pri) {
10179 start = pri->crvs;
10180 lock = &pri->lock;
10181 } else {
10182 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10183 return RESULT_FAILURE;
10185 } else
10186 #endif
10187 if (argc != 3)
10188 return RESULT_SHOWUSAGE;
10190 ast_mutex_lock(lock);
10191 #ifdef HAVE_PRI
10192 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10193 #else
10194 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10195 #endif
10197 tmp = start;
10198 while (tmp) {
10199 if (tmp->channel > 0) {
10200 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10201 } else
10202 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10203 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10204 tmp = tmp->next;
10206 ast_mutex_unlock(lock);
10207 return RESULT_SUCCESS;
10208 #undef FORMAT
10209 #undef FORMAT2
10212 static int dahdi_show_channel(int fd, int argc, char **argv)
10214 int channel;
10215 struct dahdi_pvt *tmp = NULL;
10216 struct dahdi_confinfo ci;
10217 struct dahdi_params ps;
10218 int x;
10219 ast_mutex_t *lock;
10220 struct dahdi_pvt *start;
10221 #ifdef HAVE_PRI
10222 char *c;
10223 int trunkgroup;
10224 struct dahdi_pri *pri=NULL;
10225 #endif
10227 lock = &iflock;
10228 start = iflist;
10230 if (argc != 4)
10231 return RESULT_SHOWUSAGE;
10232 #ifdef HAVE_PRI
10233 if ((c = strchr(argv[3], ':'))) {
10234 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10235 return RESULT_SHOWUSAGE;
10236 if ((trunkgroup < 1) || (channel < 1))
10237 return RESULT_SHOWUSAGE;
10238 for (x = 0; x < NUM_SPANS; x++) {
10239 if (pris[x].trunkgroup == trunkgroup) {
10240 pri = pris + x;
10241 break;
10244 if (pri) {
10245 start = pri->crvs;
10246 lock = &pri->lock;
10247 } else {
10248 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10249 return RESULT_FAILURE;
10251 } else
10252 #endif
10253 channel = atoi(argv[3]);
10255 ast_mutex_lock(lock);
10256 tmp = start;
10257 while (tmp) {
10258 if (tmp->channel == channel) {
10259 #ifdef HAVE_PRI
10260 if (pri)
10261 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10262 else
10263 #endif
10264 ast_cli(fd, "Channel: %d\n", tmp->channel);
10265 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10266 ast_cli(fd, "Span: %d\n", tmp->span);
10267 ast_cli(fd, "Extension: %s\n", tmp->exten);
10268 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10269 ast_cli(fd, "Context: %s\n", tmp->context);
10270 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10271 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10272 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10273 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10274 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10275 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10276 ast_cli(fd, "Radio: %d\n", tmp->radio);
10277 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10278 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)" : "");
10279 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)" : "");
10280 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)" : "");
10281 ast_cli(fd, "Confno: %d\n", tmp->confno);
10282 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10283 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10284 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10285 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10286 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10287 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10288 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10289 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10290 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10291 if (tmp->master)
10292 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10293 for (x = 0; x < MAX_SLAVES; x++) {
10294 if (tmp->slaves[x])
10295 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10297 #ifdef HAVE_PRI
10298 if (tmp->pri) {
10299 ast_cli(fd, "PRI Flags: ");
10300 if (tmp->resetting)
10301 ast_cli(fd, "Resetting ");
10302 if (tmp->call)
10303 ast_cli(fd, "Call ");
10304 if (tmp->bearer)
10305 ast_cli(fd, "Bearer ");
10306 ast_cli(fd, "\n");
10307 if (tmp->logicalspan)
10308 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10309 else
10310 ast_cli(fd, "PRI Logical Span: Implicit\n");
10313 #endif
10314 memset(&ci, 0, sizeof(ci));
10315 ps.channo = tmp->channel;
10316 if (tmp->subs[SUB_REAL].dfd > -1) {
10317 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10318 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10320 #ifdef DAHDI_GETCONFMUTE
10321 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10322 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10324 #endif
10325 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10326 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10327 } else {
10328 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10331 ast_mutex_unlock(lock);
10332 return RESULT_SUCCESS;
10334 tmp = tmp->next;
10337 ast_cli(fd, "Unable to find given channel %d\n", channel);
10338 ast_mutex_unlock(lock);
10339 return RESULT_FAILURE;
10342 static char dahdi_show_cadences_usage[] =
10343 "Usage: dahdi show cadences\n"
10344 " Shows all cadences currently defined\n";
10346 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10348 int i, j;
10349 for (i = 0; i < num_cadence; i++) {
10350 char output[1024];
10351 char tmp[16], tmp2[64];
10352 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10353 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10355 for (j = 0; j < 16; j++) {
10356 if (cadences[i].ringcadence[j] == 0)
10357 break;
10358 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10359 if (cidrings[i] * 2 - 1 == j)
10360 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10361 else
10362 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10363 if (j != 0)
10364 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10365 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10367 ast_cli(fd,"%s\n",output);
10369 return 0;
10372 /* Based on irqmiss.c */
10373 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10374 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10375 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10377 int span;
10378 int res;
10379 char alarms[50];
10381 int ctl;
10382 struct dahdi_spaninfo s;
10384 #ifdef HAVE_ZAPTEL
10385 if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
10386 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10387 ast_cli(fd, "No Zaptel interface found.\n");
10388 return RESULT_FAILURE;
10390 #else
10391 if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
10392 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10393 ast_cli(fd, "No DAHDI interface found.\n");
10394 return RESULT_FAILURE;
10396 #endif
10397 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10399 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10400 s.spanno = span;
10401 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10402 if (res) {
10403 continue;
10405 alarms[0] = '\0';
10406 if (s.alarms > 0) {
10407 if (s.alarms & DAHDI_ALARM_BLUE)
10408 strcat(alarms, "BLU/");
10409 if (s.alarms & DAHDI_ALARM_YELLOW)
10410 strcat(alarms, "YEL/");
10411 if (s.alarms & DAHDI_ALARM_RED)
10412 strcat(alarms, "RED/");
10413 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10414 strcat(alarms, "LB/");
10415 if (s.alarms & DAHDI_ALARM_RECOVER)
10416 strcat(alarms, "REC/");
10417 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10418 strcat(alarms, "NOP/");
10419 if (!strlen(alarms))
10420 strcat(alarms, "UUU/");
10421 if (strlen(alarms)) {
10422 /* Strip trailing / */
10423 alarms[strlen(alarms) - 1] = '\0';
10425 } else {
10426 if (s.numchans)
10427 strcpy(alarms, "OK");
10428 else
10429 strcpy(alarms, "UNCONFIGURED");
10432 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10434 close(ctl);
10436 return RESULT_SUCCESS;
10437 #undef FORMAT
10438 #undef FORMAT2
10441 static char show_channels_usage[] =
10442 "Usage: dahdi show channels\n"
10443 " Shows a list of available channels\n";
10445 static char show_channel_usage[] =
10446 "Usage: dahdi show channel <chan num>\n"
10447 " Detailed information about a given channel\n";
10449 static char dahdi_show_status_usage[] =
10450 "Usage: dahdi show status\n"
10451 " Shows a list of DAHDI cards with status\n";
10453 static char destroy_channel_usage[] =
10454 "Usage: dahdi destroy channel <chan num>\n"
10455 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10457 static char dahdi_restart_usage[] =
10458 "Usage: dahdi restart\n"
10459 " Restarts the DAHDI channels: destroys them all and then\n"
10460 " re-reads them from chan_dahdi.conf.\n"
10461 " Note that this will STOP any running CALL on DAHDI channels.\n"
10464 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10465 { "zap", "show", "cadences", NULL },
10466 handle_dahdi_show_cadences, NULL,
10467 NULL };
10469 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10470 { "zap", "show", "channels", NULL },
10471 dahdi_show_channels, NULL,
10472 NULL };
10474 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10475 { "zap", "show", "channel", NULL },
10476 dahdi_show_channel, NULL,
10477 NULL };
10479 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10480 { "zap", "destroy", "channel", NULL },
10481 dahdi_destroy_channel, NULL,
10482 NULL };
10484 static struct ast_cli_entry cli_zap_restart_deprecated = {
10485 { "zap", "restart", NULL },
10486 dahdi_restart_cmd, NULL,
10487 NULL };
10489 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10490 { "zap", "show", "status", NULL },
10491 dahdi_show_status, NULL,
10492 NULL };
10494 static struct ast_cli_entry dahdi_cli[] = {
10495 { { "dahdi", "show", "cadences", NULL },
10496 handle_dahdi_show_cadences, "List cadences",
10497 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10499 { { "dahdi", "show", "channels", NULL},
10500 dahdi_show_channels, "Show active DAHDI channels",
10501 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10503 { { "dahdi", "show", "channel", NULL},
10504 dahdi_show_channel, "Show information on a channel",
10505 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10507 { { "dahdi", "destroy", "channel", NULL},
10508 dahdi_destroy_channel, "Destroy a channel",
10509 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10511 { { "dahdi", "restart", NULL},
10512 dahdi_restart_cmd, "Fully restart DAHDI channels",
10513 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10515 { { "dahdi", "show", "status", NULL},
10516 dahdi_show_status, "Show all DAHDI cards status",
10517 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10520 #define TRANSFER 0
10521 #define HANGUP 1
10523 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10525 if (p) {
10526 switch (mode) {
10527 case TRANSFER:
10528 p->fake_event = DAHDI_EVENT_WINKFLASH;
10529 break;
10530 case HANGUP:
10531 p->fake_event = DAHDI_EVENT_ONHOOK;
10532 break;
10533 default:
10534 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10537 return 0;
10539 static struct dahdi_pvt *find_channel(int channel)
10541 struct dahdi_pvt *p = iflist;
10542 while (p) {
10543 if (p->channel == channel) {
10544 break;
10546 p = p->next;
10548 return p;
10551 #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)
10552 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10554 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10556 struct dahdi_pvt *p = NULL;
10557 const char *channel = local_astman_header(m, "Channel", zap_mode);
10559 if (ast_strlen_zero(channel)) {
10560 astman_send_error(s, m, "No channel specified");
10561 return 0;
10563 if (!(p = find_channel(atoi(channel)))) {
10564 astman_send_error(s, m, "No such channel");
10565 return 0;
10567 p->dnd = dnd;
10568 local_astman_ack(s, m, "DND", zap_mode);
10570 return 0;
10573 static int zap_action_dndon(struct mansession *s, const struct message *m)
10575 return __action_dnd(s, m, 1, 1);
10578 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10580 return __action_dnd(s, m, 0, 1);
10583 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10585 return __action_dnd(s, m, 1, 0);
10588 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10590 return __action_dnd(s, m, 0, 0);
10593 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10595 struct dahdi_pvt *p = NULL;
10596 const char *channel = local_astman_header(m, "Channel", zap_mode);
10598 if (ast_strlen_zero(channel)) {
10599 astman_send_error(s, m, "No channel specified");
10600 return 0;
10602 if (!(p = find_channel(atoi(channel)))) {
10603 astman_send_error(s, m, "No such channel");
10604 return 0;
10606 dahdi_fake_event(p,TRANSFER);
10607 local_astman_ack(s, m, "Transfer", zap_mode);
10609 return 0;
10612 static int zap_action_transfer(struct mansession *s, const struct message *m)
10614 return __action_transfer(s, m, 1);
10617 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10619 return __action_transfer(s, m, 0);
10622 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
10624 struct dahdi_pvt *p = NULL;
10625 const char *channel = local_astman_header(m, "Channel", zap_mode);
10627 if (ast_strlen_zero(channel)) {
10628 astman_send_error(s, m, "No channel specified");
10629 return 0;
10631 if (!(p = find_channel(atoi(channel)))) {
10632 astman_send_error(s, m, "No such channel");
10633 return 0;
10635 dahdi_fake_event(p, HANGUP);
10636 local_astman_ack(s, m, "Hangup", zap_mode);
10637 return 0;
10640 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10642 return __action_transferhangup(s, m, 1);
10645 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10647 return __action_transferhangup(s, m, 0);
10650 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10652 struct dahdi_pvt *p = NULL;
10653 const char *channel = local_astman_header(m, "Channel", zap_mode);
10654 const char *number = astman_get_header(m, "Number");
10655 int i;
10657 if (ast_strlen_zero(channel)) {
10658 astman_send_error(s, m, "No channel specified");
10659 return 0;
10661 if (ast_strlen_zero(number)) {
10662 astman_send_error(s, m, "No number specified");
10663 return 0;
10665 if (!(p = find_channel(atoi(channel)))) {
10666 astman_send_error(s, m, "No such channel");
10667 return 0;
10669 if (!p->owner) {
10670 astman_send_error(s, m, "Channel does not have an owner");
10671 return 0;
10673 for (i = 0; i < strlen(number); i++) {
10674 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10676 dahdi_queue_frame(p, &f, NULL);
10678 local_astman_ack(s, m, "DialOffHook", zap_mode);
10680 return 0;
10683 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10685 return __action_dialoffhook(s, m, 1);
10688 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10690 return __action_dialoffhook(s, m, 0);
10693 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10695 struct dahdi_pvt *tmp = NULL;
10696 const char *id = astman_get_header(m, "ActionID");
10697 char idText[256] = "";
10699 local_astman_ack(s, m, " channel status will follow", zap_mode);
10700 if (!ast_strlen_zero(id))
10701 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10703 ast_mutex_lock(&iflock);
10705 tmp = iflist;
10706 while (tmp) {
10707 if (tmp->channel > 0) {
10708 int alarm = get_alarms(tmp);
10709 astman_append(s,
10710 "Event: %sShowChannels\r\n"
10711 "Channel: %d\r\n"
10712 "Signalling: %s\r\n"
10713 "Context: %s\r\n"
10714 "DND: %s\r\n"
10715 "Alarm: %s\r\n"
10716 "%s"
10717 "\r\n",
10718 dahdi_chan_name,
10719 tmp->channel, sig2str(tmp->sig), tmp->context,
10720 tmp->dnd ? "Enabled" : "Disabled",
10721 alarm2str(alarm), idText);
10724 tmp = tmp->next;
10727 ast_mutex_unlock(&iflock);
10729 astman_append(s,
10730 "Event: %sShowChannelsComplete\r\n"
10731 "%s"
10732 "\r\n",
10733 dahdi_chan_name,
10734 idText);
10735 return 0;
10738 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10740 return __action_showchannels(s, m, 1);
10743 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10745 return __action_showchannels(s, m, 0);
10748 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10750 if (dahdi_restart() != 0) {
10751 if (zap_mode) {
10752 astman_send_error(s, m, "Failed to restart Zap");
10753 } else {
10754 astman_send_error(s, m, "Failed to restart DAHDI");
10756 return 1;
10758 local_astman_ack(s, m, "Restart: Success", zap_mode);
10759 return 0;
10762 static int zap_action_restart(struct mansession *s, const struct message *m)
10764 return __action_restart(s, m, 1);
10767 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10769 return __action_restart(s, m, 0);
10772 #define local_astman_unregister(a) do { \
10773 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10774 ast_manager_unregister("DAHDI" a); \
10776 ast_manager_unregister("Zap" a); \
10777 } while (0)
10779 static int __unload_module(void)
10781 int x;
10782 struct dahdi_pvt *p, *pl;
10784 #ifdef HAVE_PRI
10785 int i, j;
10786 for (i = 0; i < NUM_SPANS; i++) {
10787 if (pris[i].master != AST_PTHREADT_NULL)
10788 pthread_cancel(pris[i].master);
10790 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10792 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10793 ast_unregister_application(dahdi_send_keypad_facility_app);
10795 ast_unregister_application(zap_send_keypad_facility_app);
10796 #endif
10797 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10798 local_astman_unregister("DialOffHook");
10799 local_astman_unregister("Hangup");
10800 local_astman_unregister("Transfer");
10801 local_astman_unregister("DNDoff");
10802 local_astman_unregister("DNDon");
10803 local_astman_unregister("ShowChannels");
10804 local_astman_unregister("Restart");
10805 ast_channel_unregister(chan_tech);
10806 ast_mutex_lock(&iflock);
10807 /* Hangup all interfaces if they have an owner */
10808 p = iflist;
10809 while (p) {
10810 if (p->owner)
10811 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10812 p = p->next;
10814 ast_mutex_unlock(&iflock);
10815 ast_mutex_lock(&monlock);
10816 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10817 pthread_cancel(monitor_thread);
10818 pthread_kill(monitor_thread, SIGURG);
10819 pthread_join(monitor_thread, NULL);
10821 monitor_thread = AST_PTHREADT_STOP;
10822 ast_mutex_unlock(&monlock);
10824 ast_mutex_lock(&iflock);
10825 /* Destroy all the interfaces and free their memory */
10826 p = iflist;
10827 while (p) {
10828 /* Free any callerid */
10829 if (p->cidspill)
10830 free(p->cidspill);
10831 /* Close the DAHDI thingy */
10832 if (p->subs[SUB_REAL].dfd > -1)
10833 dahdi_close(p->subs[SUB_REAL].dfd);
10834 pl = p;
10835 p = p->next;
10836 x = pl->channel;
10837 /* Free associated memory */
10838 if (pl)
10839 destroy_dahdi_pvt(&pl);
10840 ast_verbose(VERBOSE_PREFIX_3 "Unregistered channel %d\n", x);
10842 iflist = NULL;
10843 ifcount = 0;
10844 ast_mutex_unlock(&iflock);
10845 #ifdef HAVE_PRI
10846 for (i = 0; i < NUM_SPANS; i++) {
10847 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10848 pthread_join(pris[i].master, NULL);
10849 for (j = 0; j < NUM_DCHANS; j++) {
10850 dahdi_close(pris[i].fds[j]);
10853 #endif
10854 return 0;
10857 static int unload_module(void)
10859 #ifdef HAVE_PRI
10860 int y;
10861 for (y = 0; y < NUM_SPANS; y++)
10862 ast_mutex_destroy(&pris[y].lock);
10863 #endif
10864 return __unload_module();
10867 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10869 char *c, *chan;
10870 int x, start, finish;
10871 struct dahdi_pvt *tmp;
10872 #ifdef HAVE_PRI
10873 struct dahdi_pri *pri;
10874 int trunkgroup, y;
10875 #endif
10877 if ((reload == 0) && (conf->chan.sig < 0)) {
10878 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10879 return -1;
10882 c = ast_strdupa(value);
10884 #ifdef HAVE_PRI
10885 pri = NULL;
10886 if (iscrv) {
10887 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10888 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10889 return -1;
10891 if (trunkgroup < 1) {
10892 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10893 return -1;
10895 c += y;
10896 for (y = 0; y < NUM_SPANS; y++) {
10897 if (pris[y].trunkgroup == trunkgroup) {
10898 pri = pris + y;
10899 break;
10902 if (!pri) {
10903 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10904 return -1;
10907 #endif
10909 while ((chan = strsep(&c, ","))) {
10910 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10911 /* Range */
10912 } else if (sscanf(chan, "%d", &start)) {
10913 /* Just one */
10914 finish = start;
10915 } else if (!strcasecmp(chan, "pseudo")) {
10916 finish = start = CHAN_PSEUDO;
10917 if (found_pseudo)
10918 *found_pseudo = 1;
10919 } else {
10920 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10921 return -1;
10923 if (finish < start) {
10924 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10925 x = finish;
10926 finish = start;
10927 start = x;
10930 for (x = start; x <= finish; x++) {
10931 #ifdef HAVE_PRI
10932 tmp = mkintf(x, conf, pri, reload);
10933 #else
10934 tmp = mkintf(x, conf, NULL, reload);
10935 #endif
10937 if (tmp) {
10938 if (option_verbose > 2) {
10939 #ifdef HAVE_PRI
10940 if (pri)
10941 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10942 else
10943 #endif
10944 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10946 } else {
10947 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10948 (reload == 1) ? "reconfigure" : "register", value);
10949 return -1;
10954 return 0;
10957 /** The length of the parameters list of 'dahdichan'.
10958 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10959 #define MAX_CHANLIST_LEN 80
10960 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10962 struct dahdi_pvt *tmp;
10963 char *ringc; /* temporary string for parsing the dring number. */
10964 int y;
10965 int found_pseudo = 0;
10966 char dahdichan[MAX_CHANLIST_LEN] = {};
10968 for (; v; v = v->next) {
10969 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10970 continue;
10972 /* Create the interface list */
10973 if (!strcasecmp(v->name, "channel")
10974 #ifdef HAVE_PRI
10975 || !strcasecmp(v->name, "crv")
10976 #endif
10978 int iscrv;
10979 if (skipchannels)
10980 continue;
10981 iscrv = !strcasecmp(v->name, "crv");
10982 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
10983 return -1;
10984 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
10985 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
10986 if (v->name[0] == 'z' || v->name[0] == 'Z') {
10987 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
10989 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
10990 if (ast_true(v->value))
10991 confp->chan.usedistinctiveringdetection = 1;
10992 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
10993 if (ast_true(v->value))
10994 distinctiveringaftercid = 1;
10995 } else if (!strcasecmp(v->name, "dring1context")) {
10996 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
10997 } else if (!strcasecmp(v->name, "dring2context")) {
10998 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
10999 } else if (!strcasecmp(v->name, "dring3context")) {
11000 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11001 } else if (!strcasecmp(v->name, "dring1")) {
11002 ringc = v->value;
11003 sscanf(ringc, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11004 } else if (!strcasecmp(v->name, "dring2")) {
11005 ringc = v->value;
11006 sscanf(ringc, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11007 } else if (!strcasecmp(v->name, "dring3")) {
11008 ringc = v->value;
11009 sscanf(ringc, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11010 } else if (!strcasecmp(v->name, "usecallerid")) {
11011 confp->chan.use_callerid = ast_true(v->value);
11012 } else if (!strcasecmp(v->name, "cidsignalling")) {
11013 if (!strcasecmp(v->value, "bell"))
11014 confp->chan.cid_signalling = CID_SIG_BELL;
11015 else if (!strcasecmp(v->value, "v23"))
11016 confp->chan.cid_signalling = CID_SIG_V23;
11017 else if (!strcasecmp(v->value, "dtmf"))
11018 confp->chan.cid_signalling = CID_SIG_DTMF;
11019 else if (!strcasecmp(v->value, "smdi"))
11020 confp->chan.cid_signalling = CID_SIG_SMDI;
11021 else if (!strcasecmp(v->value, "v23_jp"))
11022 confp->chan.cid_signalling = CID_SIG_V23_JP;
11023 else if (ast_true(v->value))
11024 confp->chan.cid_signalling = CID_SIG_BELL;
11025 } else if (!strcasecmp(v->name, "cidstart")) {
11026 if (!strcasecmp(v->value, "ring"))
11027 confp->chan.cid_start = CID_START_RING;
11028 else if (!strcasecmp(v->value, "polarity"))
11029 confp->chan.cid_start = CID_START_POLARITY;
11030 else if (ast_true(v->value))
11031 confp->chan.cid_start = CID_START_RING;
11032 } else if (!strcasecmp(v->name, "threewaycalling")) {
11033 confp->chan.threewaycalling = ast_true(v->value);
11034 } else if (!strcasecmp(v->name, "cancallforward")) {
11035 confp->chan.cancallforward = ast_true(v->value);
11036 } else if (!strcasecmp(v->name, "relaxdtmf")) {
11037 if (ast_true(v->value))
11038 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11039 else
11040 confp->chan.dtmfrelax = 0;
11041 } else if (!strcasecmp(v->name, "mailbox")) {
11042 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11043 } else if (!strcasecmp(v->name, "hasvoicemail")) {
11044 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11045 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11047 } else if (!strcasecmp(v->name, "adsi")) {
11048 confp->chan.adsi = ast_true(v->value);
11049 } else if (!strcasecmp(v->name, "usesmdi")) {
11050 confp->chan.use_smdi = ast_true(v->value);
11051 } else if (!strcasecmp(v->name, "smdiport")) {
11052 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11053 } else if (!strcasecmp(v->name, "transfer")) {
11054 confp->chan.transfer = ast_true(v->value);
11055 } else if (!strcasecmp(v->name, "canpark")) {
11056 confp->chan.canpark = ast_true(v->value);
11057 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11058 confp->chan.echocanbridged = ast_true(v->value);
11059 } else if (!strcasecmp(v->name, "busydetect")) {
11060 confp->chan.busydetect = ast_true(v->value);
11061 } else if (!strcasecmp(v->name, "busycount")) {
11062 confp->chan.busycount = atoi(v->value);
11063 } else if (!strcasecmp(v->name, "busypattern")) {
11064 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
11065 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
11067 } else if (!strcasecmp(v->name, "callprogress")) {
11068 if (ast_true(v->value))
11069 confp->chan.callprogress |= 1;
11070 else
11071 confp->chan.callprogress &= ~1;
11072 } else if (!strcasecmp(v->name, "faxdetect")) {
11073 if (!strcasecmp(v->value, "incoming")) {
11074 confp->chan.callprogress |= 4;
11075 confp->chan.callprogress &= ~2;
11076 } else if (!strcasecmp(v->value, "outgoing")) {
11077 confp->chan.callprogress &= ~4;
11078 confp->chan.callprogress |= 2;
11079 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11080 confp->chan.callprogress |= 6;
11081 else
11082 confp->chan.callprogress &= ~6;
11083 } else if (!strcasecmp(v->name, "echocancel")) {
11084 if (!ast_strlen_zero(v->value)) {
11085 y = atoi(v->value);
11086 } else
11087 y = 0;
11088 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11089 confp->chan.echocancel = y;
11090 else {
11091 confp->chan.echocancel = ast_true(v->value);
11092 if (confp->chan.echocancel)
11093 confp->chan.echocancel=128;
11095 } else if (!strcasecmp(v->name, "echotraining")) {
11096 if (sscanf(v->value, "%d", &y) == 1) {
11097 if ((y < 10) || (y > 4000)) {
11098 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
11099 } else {
11100 confp->chan.echotraining = y;
11102 } else if (ast_true(v->value)) {
11103 confp->chan.echotraining = 400;
11104 } else
11105 confp->chan.echotraining = 0;
11106 } else if (!strcasecmp(v->name, "hidecallerid")) {
11107 confp->chan.hidecallerid = ast_true(v->value);
11108 } else if (!strcasecmp(v->name, "hidecalleridname")) {
11109 confp->chan.hidecalleridname = ast_true(v->value);
11110 } else if (!strcasecmp(v->name, "pulsedial")) {
11111 confp->chan.pulse = ast_true(v->value);
11112 } else if (!strcasecmp(v->name, "callreturn")) {
11113 confp->chan.callreturn = ast_true(v->value);
11114 } else if (!strcasecmp(v->name, "callwaiting")) {
11115 confp->chan.callwaiting = ast_true(v->value);
11116 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11117 confp->chan.callwaitingcallerid = ast_true(v->value);
11118 } else if (!strcasecmp(v->name, "context")) {
11119 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11120 } else if (!strcasecmp(v->name, "language")) {
11121 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11122 } else if (!strcasecmp(v->name, "progzone")) {
11123 ast_copy_string(progzone, v->value, sizeof(progzone));
11124 } else if (!strcasecmp(v->name, "mohinterpret")
11125 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11126 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11127 } else if (!strcasecmp(v->name, "mohsuggest")) {
11128 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11129 } else if (!strcasecmp(v->name, "stripmsd")) {
11130 confp->chan.stripmsd = atoi(v->value);
11131 } else if (!strcasecmp(v->name, "jitterbuffers")) {
11132 numbufs = atoi(v->value);
11133 } else if (!strcasecmp(v->name, "group")) {
11134 confp->chan.group = ast_get_group(v->value);
11135 } else if (!strcasecmp(v->name, "callgroup")) {
11136 confp->chan.callgroup = ast_get_group(v->value);
11137 } else if (!strcasecmp(v->name, "pickupgroup")) {
11138 confp->chan.pickupgroup = ast_get_group(v->value);
11139 } else if (!strcasecmp(v->name, "immediate")) {
11140 confp->chan.immediate = ast_true(v->value);
11141 } else if (!strcasecmp(v->name, "transfertobusy")) {
11142 confp->chan.transfertobusy = ast_true(v->value);
11143 } else if (!strcasecmp(v->name, "rxgain")) {
11144 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11145 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11147 } else if (!strcasecmp(v->name, "txgain")) {
11148 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11149 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11151 } else if (!strcasecmp(v->name, "tonezone")) {
11152 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11153 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11155 } else if (!strcasecmp(v->name, "callerid")) {
11156 if (!strcasecmp(v->value, "asreceived")) {
11157 confp->chan.cid_num[0] = '\0';
11158 confp->chan.cid_name[0] = '\0';
11159 } else {
11160 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11162 } else if (!strcasecmp(v->name, "fullname")) {
11163 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11164 } else if (!strcasecmp(v->name, "cid_number")) {
11165 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11166 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11167 confp->chan.dahditrcallerid = ast_true(v->value);
11168 if (strstr(v->name, "zap")) {
11169 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11171 } else if (!strcasecmp(v->name, "restrictcid")) {
11172 confp->chan.restrictcid = ast_true(v->value);
11173 } else if (!strcasecmp(v->name, "usecallingpres")) {
11174 confp->chan.use_callingpres = ast_true(v->value);
11175 } else if (!strcasecmp(v->name, "accountcode")) {
11176 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11177 } else if (!strcasecmp(v->name, "amaflags")) {
11178 y = ast_cdr_amaflags2int(v->value);
11179 if (y < 0)
11180 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11181 else
11182 confp->chan.amaflags = y;
11183 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11184 confp->chan.polarityonanswerdelay = atoi(v->value);
11185 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11186 confp->chan.answeronpolarityswitch = ast_true(v->value);
11187 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11188 confp->chan.hanguponpolarityswitch = ast_true(v->value);
11189 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11190 confp->chan.sendcalleridafter = atoi(v->value);
11191 } else if (reload != 1){
11192 if (!strcasecmp(v->name, "signalling")) {
11193 confp->chan.outsigmod = -1;
11194 if (!strcasecmp(v->value, "em")) {
11195 confp->chan.sig = SIG_EM;
11196 } else if (!strcasecmp(v->value, "em_e1")) {
11197 confp->chan.sig = SIG_EM_E1;
11198 } else if (!strcasecmp(v->value, "em_w")) {
11199 confp->chan.sig = SIG_EMWINK;
11200 confp->chan.radio = 0;
11201 } else if (!strcasecmp(v->value, "fxs_ls")) {
11202 confp->chan.sig = SIG_FXSLS;
11203 confp->chan.radio = 0;
11204 } else if (!strcasecmp(v->value, "fxs_gs")) {
11205 confp->chan.sig = SIG_FXSGS;
11206 confp->chan.radio = 0;
11207 } else if (!strcasecmp(v->value, "fxs_ks")) {
11208 confp->chan.sig = SIG_FXSKS;
11209 confp->chan.radio = 0;
11210 } else if (!strcasecmp(v->value, "fxo_ls")) {
11211 confp->chan.sig = SIG_FXOLS;
11212 confp->chan.radio = 0;
11213 } else if (!strcasecmp(v->value, "fxo_gs")) {
11214 confp->chan.sig = SIG_FXOGS;
11215 confp->chan.radio = 0;
11216 } else if (!strcasecmp(v->value, "fxo_ks")) {
11217 confp->chan.sig = SIG_FXOKS;
11218 confp->chan.radio = 0;
11219 } else if (!strcasecmp(v->value, "fxs_rx")) {
11220 confp->chan.sig = SIG_FXSKS;
11221 confp->chan.radio = 1;
11222 } else if (!strcasecmp(v->value, "fxo_rx")) {
11223 confp->chan.sig = SIG_FXOLS;
11224 confp->chan.radio = 1;
11225 } else if (!strcasecmp(v->value, "fxs_tx")) {
11226 confp->chan.sig = SIG_FXSLS;
11227 confp->chan.radio = 1;
11228 } else if (!strcasecmp(v->value, "fxo_tx")) {
11229 confp->chan.sig = SIG_FXOGS;
11230 confp->chan.radio = 1;
11231 } else if (!strcasecmp(v->value, "em_rx")) {
11232 confp->chan.sig = SIG_EM;
11233 confp->chan.radio = 1;
11234 } else if (!strcasecmp(v->value, "em_tx")) {
11235 confp->chan.sig = SIG_EM;
11236 confp->chan.radio = 1;
11237 } else if (!strcasecmp(v->value, "em_rxtx")) {
11238 confp->chan.sig = SIG_EM;
11239 confp->chan.radio = 2;
11240 } else if (!strcasecmp(v->value, "em_txrx")) {
11241 confp->chan.sig = SIG_EM;
11242 confp->chan.radio = 2;
11243 } else if (!strcasecmp(v->value, "sf")) {
11244 confp->chan.sig = SIG_SF;
11245 confp->chan.radio = 0;
11246 } else if (!strcasecmp(v->value, "sf_w")) {
11247 confp->chan.sig = SIG_SFWINK;
11248 confp->chan.radio = 0;
11249 } else if (!strcasecmp(v->value, "sf_featd")) {
11250 confp->chan.sig = SIG_FEATD;
11251 confp->chan.radio = 0;
11252 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11253 confp->chan.sig = SIG_FEATDMF;
11254 confp->chan.radio = 0;
11255 } else if (!strcasecmp(v->value, "sf_featb")) {
11256 confp->chan.sig = SIG_SF_FEATB;
11257 confp->chan.radio = 0;
11258 } else if (!strcasecmp(v->value, "sf")) {
11259 confp->chan.sig = SIG_SF;
11260 confp->chan.radio = 0;
11261 } else if (!strcasecmp(v->value, "sf_rx")) {
11262 confp->chan.sig = SIG_SF;
11263 confp->chan.radio = 1;
11264 } else if (!strcasecmp(v->value, "sf_tx")) {
11265 confp->chan.sig = SIG_SF;
11266 confp->chan.radio = 1;
11267 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11268 confp->chan.sig = SIG_SF;
11269 confp->chan.radio = 2;
11270 } else if (!strcasecmp(v->value, "sf_txrx")) {
11271 confp->chan.sig = SIG_SF;
11272 confp->chan.radio = 2;
11273 } else if (!strcasecmp(v->value, "featd")) {
11274 confp->chan.sig = SIG_FEATD;
11275 confp->chan.radio = 0;
11276 } else if (!strcasecmp(v->value, "featdmf")) {
11277 confp->chan.sig = SIG_FEATDMF;
11278 confp->chan.radio = 0;
11279 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11280 confp->chan.sig = SIG_FEATDMF_TA;
11281 confp->chan.radio = 0;
11282 } else if (!strcasecmp(v->value, "e911")) {
11283 confp->chan.sig = SIG_E911;
11284 confp->chan.radio = 0;
11285 } else if (!strcasecmp(v->value, "fgccama")) {
11286 confp->chan.sig = SIG_FGC_CAMA;
11287 confp->chan.radio = 0;
11288 } else if (!strcasecmp(v->value, "fgccamamf")) {
11289 confp->chan.sig = SIG_FGC_CAMAMF;
11290 confp->chan.radio = 0;
11291 } else if (!strcasecmp(v->value, "featb")) {
11292 confp->chan.sig = SIG_FEATB;
11293 confp->chan.radio = 0;
11294 #ifdef HAVE_PRI
11295 } else if (!strcasecmp(v->value, "pri_net")) {
11296 confp->chan.radio = 0;
11297 confp->chan.sig = SIG_PRI;
11298 confp->pri.nodetype = PRI_NETWORK;
11299 } else if (!strcasecmp(v->value, "pri_cpe")) {
11300 confp->chan.sig = SIG_PRI;
11301 confp->chan.radio = 0;
11302 confp->pri.nodetype = PRI_CPE;
11303 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11304 confp->chan.sig = SIG_GR303FXOKS;
11305 confp->chan.radio = 0;
11306 confp->pri.nodetype = PRI_NETWORK;
11307 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11308 confp->chan.sig = SIG_GR303FXSKS;
11309 confp->chan.radio = 0;
11310 confp->pri.nodetype = PRI_CPE;
11311 #endif
11312 } else {
11313 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11315 } else if (!strcasecmp(v->name, "outsignalling")) {
11316 if (!strcasecmp(v->value, "em")) {
11317 confp->chan.outsigmod = SIG_EM;
11318 } else if (!strcasecmp(v->value, "em_e1")) {
11319 confp->chan.outsigmod = SIG_EM_E1;
11320 } else if (!strcasecmp(v->value, "em_w")) {
11321 confp->chan.outsigmod = SIG_EMWINK;
11322 } else if (!strcasecmp(v->value, "sf")) {
11323 confp->chan.outsigmod = SIG_SF;
11324 } else if (!strcasecmp(v->value, "sf_w")) {
11325 confp->chan.outsigmod = SIG_SFWINK;
11326 } else if (!strcasecmp(v->value, "sf_featd")) {
11327 confp->chan.outsigmod = SIG_FEATD;
11328 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11329 confp->chan.outsigmod = SIG_FEATDMF;
11330 } else if (!strcasecmp(v->value, "sf_featb")) {
11331 confp->chan.outsigmod = SIG_SF_FEATB;
11332 } else if (!strcasecmp(v->value, "sf")) {
11333 confp->chan.outsigmod = SIG_SF;
11334 } else if (!strcasecmp(v->value, "featd")) {
11335 confp->chan.outsigmod = SIG_FEATD;
11336 } else if (!strcasecmp(v->value, "featdmf")) {
11337 confp->chan.outsigmod = SIG_FEATDMF;
11338 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11339 confp->chan.outsigmod = SIG_FEATDMF_TA;
11340 } else if (!strcasecmp(v->value, "e911")) {
11341 confp->chan.outsigmod = SIG_E911;
11342 } else if (!strcasecmp(v->value, "fgccama")) {
11343 confp->chan.outsigmod = SIG_FGC_CAMA;
11344 } else if (!strcasecmp(v->value, "fgccamamf")) {
11345 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11346 } else if (!strcasecmp(v->value, "featb")) {
11347 confp->chan.outsigmod = SIG_FEATB;
11348 } else {
11349 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11351 #ifdef HAVE_PRI
11352 } else if (!strcasecmp(v->name, "pridialplan")) {
11353 if (!strcasecmp(v->value, "national")) {
11354 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11355 } else if (!strcasecmp(v->value, "unknown")) {
11356 confp->pri.dialplan = PRI_UNKNOWN + 1;
11357 } else if (!strcasecmp(v->value, "private")) {
11358 confp->pri.dialplan = PRI_PRIVATE + 1;
11359 } else if (!strcasecmp(v->value, "international")) {
11360 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11361 } else if (!strcasecmp(v->value, "local")) {
11362 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11363 } else if (!strcasecmp(v->value, "dynamic")) {
11364 confp->pri.dialplan = -1;
11365 } else {
11366 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11368 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11369 if (!strcasecmp(v->value, "national")) {
11370 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11371 } else if (!strcasecmp(v->value, "unknown")) {
11372 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11373 } else if (!strcasecmp(v->value, "private")) {
11374 confp->pri.localdialplan = PRI_PRIVATE + 1;
11375 } else if (!strcasecmp(v->value, "international")) {
11376 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11377 } else if (!strcasecmp(v->value, "local")) {
11378 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11379 } else if (!strcasecmp(v->value, "dynamic")) {
11380 confp->pri.localdialplan = -1;
11381 } else {
11382 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11384 } else if (!strcasecmp(v->name, "switchtype")) {
11385 if (!strcasecmp(v->value, "national"))
11386 confp->pri.switchtype = PRI_SWITCH_NI2;
11387 else if (!strcasecmp(v->value, "ni1"))
11388 confp->pri.switchtype = PRI_SWITCH_NI1;
11389 else if (!strcasecmp(v->value, "dms100"))
11390 confp->pri.switchtype = PRI_SWITCH_DMS100;
11391 else if (!strcasecmp(v->value, "4ess"))
11392 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11393 else if (!strcasecmp(v->value, "5ess"))
11394 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11395 else if (!strcasecmp(v->value, "euroisdn"))
11396 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11397 else if (!strcasecmp(v->value, "qsig"))
11398 confp->pri.switchtype = PRI_SWITCH_QSIG;
11399 else {
11400 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11401 return -1;
11403 } else if (!strcasecmp(v->name, "nsf")) {
11404 if (!strcasecmp(v->value, "sdn"))
11405 confp->pri.nsf = PRI_NSF_SDN;
11406 else if (!strcasecmp(v->value, "megacom"))
11407 confp->pri.nsf = PRI_NSF_MEGACOM;
11408 else if (!strcasecmp(v->value, "tollfreemegacom"))
11409 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11410 else if (!strcasecmp(v->value, "accunet"))
11411 confp->pri.nsf = PRI_NSF_ACCUNET;
11412 else if (!strcasecmp(v->value, "none"))
11413 confp->pri.nsf = PRI_NSF_NONE;
11414 else {
11415 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11416 confp->pri.nsf = PRI_NSF_NONE;
11418 } else if (!strcasecmp(v->name, "priindication")) {
11419 if (!strcasecmp(v->value, "outofband"))
11420 confp->chan.priindication_oob = 1;
11421 else if (!strcasecmp(v->value, "inband"))
11422 confp->chan.priindication_oob = 0;
11423 else
11424 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11425 v->value, v->lineno);
11426 } else if (!strcasecmp(v->name, "priexclusive")) {
11427 confp->chan.priexclusive = ast_true(v->value);
11428 } else if (!strcasecmp(v->name, "internationalprefix")) {
11429 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11430 } else if (!strcasecmp(v->name, "nationalprefix")) {
11431 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11432 } else if (!strcasecmp(v->name, "localprefix")) {
11433 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11434 } else if (!strcasecmp(v->name, "privateprefix")) {
11435 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11436 } else if (!strcasecmp(v->name, "unknownprefix")) {
11437 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11438 } else if (!strcasecmp(v->name, "resetinterval")) {
11439 if (!strcasecmp(v->value, "never"))
11440 confp->pri.resetinterval = -1;
11441 else if (atoi(v->value) >= 60)
11442 confp->pri.resetinterval = atoi(v->value);
11443 else
11444 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11445 v->value, v->lineno);
11446 } else if (!strcasecmp(v->name, "minunused")) {
11447 confp->pri.minunused = atoi(v->value);
11448 } else if (!strcasecmp(v->name, "minidle")) {
11449 confp->pri.minidle = atoi(v->value);
11450 } else if (!strcasecmp(v->name, "idleext")) {
11451 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11452 } else if (!strcasecmp(v->name, "idledial")) {
11453 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11454 } else if (!strcasecmp(v->name, "overlapdial")) {
11455 confp->pri.overlapdial = ast_true(v->value);
11456 #ifdef HAVE_PRI_INBANDDISCONNECT
11457 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11458 confp->pri.inbanddisconnect = ast_true(v->value);
11459 #endif
11460 } else if (!strcasecmp(v->name, "pritimer")) {
11461 #ifdef PRI_GETSET_TIMERS
11462 char *timerc, *c;
11463 int timer, timeridx;
11464 c = v->value;
11465 timerc = strsep(&c, ",");
11466 if (timerc) {
11467 timer = atoi(c);
11468 if (!timer)
11469 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11470 else {
11471 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11472 pritimers[timeridx] = timer;
11473 else
11474 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11476 } else
11477 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11479 } else if (!strcasecmp(v->name, "facilityenable")) {
11480 confp->pri.facilityenable = ast_true(v->value);
11481 #endif /* PRI_GETSET_TIMERS */
11482 #endif /* HAVE_PRI */
11483 } else if (!strcasecmp(v->name, "cadence")) {
11484 /* setup to scan our argument */
11485 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11486 int i;
11487 struct dahdi_ring_cadence new_cadence;
11488 int cid_location = -1;
11489 int firstcadencepos = 0;
11490 char original_args[80];
11491 int cadence_is_ok = 1;
11493 ast_copy_string(original_args, v->value, sizeof(original_args));
11494 /* 16 cadences allowed (8 pairs) */
11495 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]);
11497 /* Cadence must be even (on/off) */
11498 if (element_count % 2 == 1) {
11499 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11500 cadence_is_ok = 0;
11503 /* Ring cadences cannot be negative */
11504 for (i = 0; i < element_count; i++) {
11505 if (c[i] == 0) {
11506 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11507 cadence_is_ok = 0;
11508 break;
11509 } else if (c[i] < 0) {
11510 if (i % 2 == 1) {
11511 /* Silence duration, negative possibly okay */
11512 if (cid_location == -1) {
11513 cid_location = i;
11514 c[i] *= -1;
11515 } else {
11516 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11517 cadence_is_ok = 0;
11518 break;
11520 } else {
11521 if (firstcadencepos == 0) {
11522 firstcadencepos = i; /* only recorded to avoid duplicate specification */
11523 /* duration will be passed negative to the DAHDI driver */
11524 } else {
11525 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11526 cadence_is_ok = 0;
11527 break;
11533 /* Substitute our scanned cadence */
11534 for (i = 0; i < 16; i++) {
11535 new_cadence.ringcadence[i] = c[i];
11538 if (cadence_is_ok) {
11539 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11540 if (element_count < 2) {
11541 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11542 } else {
11543 if (cid_location == -1) {
11544 /* user didn't say; default to first pause */
11545 cid_location = 1;
11546 } else {
11547 /* convert element_index to cidrings value */
11548 cid_location = (cid_location + 1) / 2;
11550 /* ---we like their cadence; try to install it--- */
11551 if (!user_has_defined_cadences++)
11552 /* this is the first user-defined cadence; clear the default user cadences */
11553 num_cadence = 0;
11554 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11555 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11556 else {
11557 cadences[num_cadence] = new_cadence;
11558 cidrings[num_cadence++] = cid_location;
11559 if (option_verbose > 2)
11560 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11564 } else if (!strcasecmp(v->name, "ringtimeout")) {
11565 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11566 } else if (!strcasecmp(v->name, "prewink")) {
11567 confp->timing.prewinktime = atoi(v->value);
11568 } else if (!strcasecmp(v->name, "preflash")) {
11569 confp->timing.preflashtime = atoi(v->value);
11570 } else if (!strcasecmp(v->name, "wink")) {
11571 confp->timing.winktime = atoi(v->value);
11572 } else if (!strcasecmp(v->name, "flash")) {
11573 confp->timing.flashtime = atoi(v->value);
11574 } else if (!strcasecmp(v->name, "start")) {
11575 confp->timing.starttime = atoi(v->value);
11576 } else if (!strcasecmp(v->name, "rxwink")) {
11577 confp->timing.rxwinktime = atoi(v->value);
11578 } else if (!strcasecmp(v->name, "rxflash")) {
11579 confp->timing.rxflashtime = atoi(v->value);
11580 } else if (!strcasecmp(v->name, "debounce")) {
11581 confp->timing.debouncetime = atoi(v->value);
11582 } else if (!strcasecmp(v->name, "toneduration")) {
11583 int toneduration;
11584 int ctlfd;
11585 int res;
11586 struct dahdi_dialparams dps;
11588 #ifdef HAVE_ZAPTEL
11589 ctlfd = open("/dev/zap/ctl", O_RDWR);
11590 #else
11591 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11592 #endif
11594 if (ctlfd == -1) {
11595 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11596 return -1;
11599 toneduration = atoi(v->value);
11600 if (toneduration > -1) {
11601 memset(&dps, 0, sizeof(dps));
11603 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11604 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11605 if (res < 0) {
11606 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11607 return -1;
11610 close(ctlfd);
11611 } else if (!strcasecmp(v->name, "defaultcic")) {
11612 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11613 } else if (!strcasecmp(v->name, "defaultozz")) {
11614 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11616 } else if (!skipchannels)
11617 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11619 if (dahdichan[0]) {
11620 /* The user has set 'dahdichan' */
11621 /*< \todo pass proper line number instead of 0 */
11622 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11623 return -1;
11626 /*< \todo why check for the pseudo in the per-channel section.
11627 * Any actual use for manual setup of the pseudo channel? */
11628 if (!found_pseudo && reload == 0) {
11629 /* Make sure pseudo isn't a member of any groups if
11630 we're automatically making it. */
11632 confp->chan.group = 0;
11633 confp->chan.callgroup = 0;
11634 confp->chan.pickupgroup = 0;
11636 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
11638 if (tmp) {
11639 if (option_verbose > 2)
11640 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11641 } else {
11642 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11645 return 0;
11648 static int setup_dahdi(int reload)
11650 struct ast_config *cfg;
11651 struct ast_variable *v;
11652 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11653 int res;
11655 #ifdef HAVE_PRI
11656 char *c;
11657 int spanno;
11658 int i, x;
11659 int logicalspan;
11660 int trunkgroup;
11661 int dchannels[NUM_DCHANS];
11662 #endif
11664 #ifdef HAVE_ZAPTEL
11665 int load_from_zapata_conf = 1;
11666 #else
11667 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11668 #endif
11670 if (load_from_zapata_conf) {
11671 if (!(cfg = ast_config_load("zapata.conf"))) {
11672 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11673 return 0;
11675 } else {
11676 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11677 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11678 return 0;
11682 /* It's a little silly to lock it, but we mind as well just to be sure */
11683 ast_mutex_lock(&iflock);
11684 #ifdef HAVE_PRI
11685 if (reload != 1) {
11686 /* Process trunkgroups first */
11687 v = ast_variable_browse(cfg, "trunkgroups");
11688 while (v) {
11689 if (!strcasecmp(v->name, "trunkgroup")) {
11690 trunkgroup = atoi(v->value);
11691 if (trunkgroup > 0) {
11692 if ((c = strchr(v->value, ','))) {
11693 i = 0;
11694 memset(dchannels, 0, sizeof(dchannels));
11695 while (c && (i < NUM_DCHANS)) {
11696 dchannels[i] = atoi(c + 1);
11697 if (dchannels[i] < 0) {
11698 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);
11699 } else
11700 i++;
11701 c = strchr(c + 1, ',');
11703 if (i) {
11704 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11705 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);
11706 } else if (option_verbose > 1)
11707 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");
11708 } else
11709 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11710 } else
11711 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11712 } else
11713 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11714 } else if (!strcasecmp(v->name, "spanmap")) {
11715 spanno = atoi(v->value);
11716 if (spanno > 0) {
11717 if ((c = strchr(v->value, ','))) {
11718 trunkgroup = atoi(c + 1);
11719 if (trunkgroup > 0) {
11720 if ((c = strchr(c + 1, ',')))
11721 logicalspan = atoi(c + 1);
11722 else
11723 logicalspan = 0;
11724 if (logicalspan >= 0) {
11725 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11726 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11727 } else if (option_verbose > 1)
11728 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11729 } else
11730 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);
11731 } else
11732 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11733 } else
11734 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11735 } else
11736 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11737 } else {
11738 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11740 v = v->next;
11743 #endif
11745 /* Copy the default jb config over global_jbconf */
11746 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11748 v = ast_variable_browse(cfg, "channels");
11749 res = process_dahdi(&conf, "", v, reload, 0);
11750 ast_mutex_unlock(&iflock);
11751 ast_config_destroy(cfg);
11752 if (res)
11753 return res;
11754 cfg = ast_config_load("users.conf");
11755 if (cfg) {
11756 char *cat;
11757 const char *chans;
11758 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11759 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11760 if (!strcasecmp(cat, "general"))
11761 continue;
11762 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11763 if (!ast_strlen_zero(chans)) {
11764 struct dahdi_chan_conf sect_conf;
11765 memcpy(&sect_conf, &conf, sizeof(sect_conf));
11767 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11770 ast_config_destroy(cfg);
11772 #ifdef HAVE_PRI
11773 if (reload != 1) {
11774 for (x = 0; x < NUM_SPANS; x++) {
11775 if (pris[x].pvts[0]) {
11776 if (start_pri(pris + x)) {
11777 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11778 return -1;
11779 } else if (option_verbose > 1)
11780 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11784 #endif
11785 /* And start the monitor for the first time */
11786 restart_monitor();
11787 return 0;
11790 #define local_astman_register(a, b, c, d) do { \
11791 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11792 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11794 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11795 } while (0)
11797 static int load_module(void)
11799 int res;
11801 #ifdef HAVE_PRI
11802 int y,i;
11803 memset(pris, 0, sizeof(pris));
11804 for (y = 0; y < NUM_SPANS; y++) {
11805 ast_mutex_init(&pris[y].lock);
11806 pris[y].offset = -1;
11807 pris[y].master = AST_PTHREADT_NULL;
11808 for (i = 0; i < NUM_DCHANS; i++)
11809 pris[y].fds[i] = -1;
11811 pri_set_error(dahdi_pri_error);
11812 pri_set_message(dahdi_pri_message);
11813 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11814 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11815 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11817 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11818 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11819 #endif
11820 if ((res = setup_dahdi(0))) {
11821 return AST_MODULE_LOAD_DECLINE;
11823 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11824 chan_tech = &dahdi_tech;
11825 } else {
11826 chan_tech = &zap_tech;
11828 if (ast_channel_register(chan_tech)) {
11829 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11830 __unload_module();
11831 return -1;
11833 #ifdef HAVE_PRI
11834 ast_string_field_init(&inuse, 16);
11835 ast_string_field_set(&inuse, name, "GR-303InUse");
11836 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11837 #endif
11838 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11840 memset(round_robin, 0, sizeof(round_robin));
11841 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11842 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11843 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11844 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11845 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11846 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11847 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11849 return res;
11852 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11854 #define END_SILENCE_LEN 400
11855 #define HEADER_MS 50
11856 #define TRAILER_MS 5
11857 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11858 #define ASCII_BYTES_PER_CHAR 80
11860 unsigned char *buf,*mybuf;
11861 struct dahdi_pvt *p = c->tech_pvt;
11862 struct pollfd fds[1];
11863 int size,res,fd,len,x;
11864 int bytes=0;
11865 /* Initial carrier (imaginary) */
11866 float cr = 1.0;
11867 float ci = 0.0;
11868 float scont = 0.0;
11869 int index;
11871 index = dahdi_get_index(c, p, 0);
11872 if (index < 0) {
11873 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11874 return -1;
11876 if (!text[0]) return(0); /* if nothing to send, dont */
11877 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
11878 if (p->mate)
11879 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11880 else
11881 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11882 if (!buf)
11883 return -1;
11884 mybuf = buf;
11885 if (p->mate) {
11886 int codec = AST_LAW(p);
11887 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
11888 PUT_CLID_MARKMS;
11890 /* Put actual message */
11891 for (x = 0; text[x]; x++) {
11892 PUT_CLID(text[x]);
11894 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
11895 PUT_CLID_MARKMS;
11897 len = bytes;
11898 buf = mybuf;
11899 } else {
11900 len = tdd_generate(p->tdd, buf, text);
11901 if (len < 1) {
11902 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11903 free(mybuf);
11904 return -1;
11907 memset(buf + len, 0x7f, END_SILENCE_LEN);
11908 len += END_SILENCE_LEN;
11909 fd = p->subs[index].dfd;
11910 while (len) {
11911 if (ast_check_hangup(c)) {
11912 free(mybuf);
11913 return -1;
11915 size = len;
11916 if (size > READ_SIZE)
11917 size = READ_SIZE;
11918 fds[0].fd = fd;
11919 fds[0].events = POLLOUT | POLLPRI;
11920 fds[0].revents = 0;
11921 res = poll(fds, 1, -1);
11922 if (!res) {
11923 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11924 continue;
11926 /* if got exception */
11927 if (fds[0].revents & POLLPRI) {
11928 ast_free(mybuf);
11929 return -1;
11931 if (!(fds[0].revents & POLLOUT)) {
11932 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11933 continue;
11935 res = write(fd, buf, size);
11936 if (res != size) {
11937 if (res == -1) {
11938 free(mybuf);
11939 return -1;
11941 if (option_debug)
11942 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11943 break;
11945 len -= size;
11946 buf += size;
11948 free(mybuf);
11949 return(0);
11953 static int reload(void)
11955 int res = 0;
11957 res = setup_dahdi(1);
11958 if (res) {
11959 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
11960 return -1;
11962 return 0;
11965 /* This is a workaround so that menuselect displays a proper description
11966 * AST_MODULE_INFO(, , "DAHDI Telephony"
11969 #ifdef DAHDI_PRI
11970 #define tdesc "DAHDI Telephony w/PRI"
11971 #else
11972 #define tdesc "DAHDI Telephony"
11973 #endif
11975 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
11976 .load = load_module,
11977 .unload = unload_module,
11978 .reload = reload,