Ignore some files generated from 1.6.x/trunk build
[asterisk-bristuff.git] / channels / chan_dahdi.c
blob60b6d2d9ff3a458aa924603f264524d86e8f2174
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;
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 buf_no; /*!< Number of buffers */
428 int buf_policy; /*!< Buffer policy */
429 int sig; /*!< Signalling style */
430 int radio; /*!< radio type */
431 int outsigmod; /*!< Outbound Signalling style (modifier) */
432 int oprmode; /*!< "Operator Services" mode */
433 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
434 float rxgain;
435 float txgain;
436 int tonezone; /*!< tone zone for this chan, or -1 for default */
437 struct dahdi_pvt *next; /*!< Next channel in list */
438 struct dahdi_pvt *prev; /*!< Prev channel in list */
440 /* flags */
441 unsigned int adsi:1;
442 unsigned int answeronpolarityswitch:1;
443 unsigned int busydetect:1;
444 unsigned int callreturn:1;
445 unsigned int callwaiting:1;
446 unsigned int callwaitingcallerid:1;
447 unsigned int cancallforward:1;
448 unsigned int canpark:1;
449 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
450 unsigned int destroy:1;
451 unsigned int didtdd:1; /*!< flag to say its done it once */
452 unsigned int dialednone:1;
453 unsigned int dialing:1;
454 unsigned int digital:1;
455 unsigned int dnd:1;
456 unsigned int echobreak:1;
457 unsigned int echocanbridged:1;
458 unsigned int echocanon:1;
459 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
460 unsigned int firstradio:1;
461 unsigned int hanguponpolarityswitch:1;
462 unsigned int hardwaredtmf:1;
463 unsigned int hidecallerid:1;
464 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
465 unsigned int ignoredtmf:1;
466 unsigned int immediate:1; /*!< Answer before getting digits? */
467 unsigned int inalarm:1;
468 unsigned int unknown_alarm:1;
469 unsigned int mate:1; /*!< flag to say its in MATE mode */
470 unsigned int outgoing:1;
471 unsigned int overlapdial:1;
472 unsigned int permcallwaiting:1;
473 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
474 unsigned int priindication_oob:1;
475 unsigned int priexclusive:1;
476 unsigned int pulse:1;
477 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
478 unsigned int restartpending:1; /*!< flag to ensure counted only once for restart */
479 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
480 unsigned int threewaycalling:1;
481 unsigned int transfer:1;
482 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
483 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
484 unsigned int usedistinctiveringdetection:1;
485 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
486 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
487 #if defined(HAVE_PRI)
488 unsigned int alerting:1;
489 unsigned int alreadyhungup:1;
490 unsigned int isidlecall:1;
491 unsigned int proceeding:1;
492 unsigned int progress:1;
493 unsigned int resetting:1;
494 unsigned int setup_ack:1;
495 #endif
496 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
497 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
499 struct dahdi_distRings drings;
501 char context[AST_MAX_CONTEXT];
502 char defcontext[AST_MAX_CONTEXT];
503 char exten[AST_MAX_EXTENSION];
504 char language[MAX_LANGUAGE];
505 char mohinterpret[MAX_MUSICCLASS];
506 char mohsuggest[MAX_MUSICCLASS];
507 #ifdef PRI_ANI
508 char cid_ani[AST_MAX_EXTENSION];
509 #endif
510 char cid_num[AST_MAX_EXTENSION];
511 int cid_ton; /*!< Type Of Number (TON) */
512 char cid_name[AST_MAX_EXTENSION];
513 char lastcid_num[AST_MAX_EXTENSION];
514 char lastcid_name[AST_MAX_EXTENSION];
515 char *origcid_num; /*!< malloced original callerid */
516 char *origcid_name; /*!< malloced original callerid */
517 char callwait_num[AST_MAX_EXTENSION];
518 char callwait_name[AST_MAX_EXTENSION];
519 char rdnis[AST_MAX_EXTENSION];
520 char dnid[AST_MAX_EXTENSION];
521 ast_group_t group;
522 int law;
523 int confno; /*!< Our conference */
524 int confusers; /*!< Who is using our conference */
525 int propconfno; /*!< Propagated conference number */
526 ast_group_t callgroup;
527 ast_group_t pickupgroup;
528 int channel; /*!< Channel Number or CRV */
529 int span; /*!< Span number */
530 time_t guardtime; /*!< Must wait this much time before using for new call */
531 int cid_signalling; /*!< CID signalling type bell202 or v23 */
532 int cid_start; /*!< CID start indicator, polarity or ring */
533 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
534 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
535 int cidcwexpire; /*!< When to expire our muting for CID/CW */
536 unsigned char *cidspill;
537 int cidpos;
538 int cidlen;
539 int ringt;
540 int ringt_base;
541 int stripmsd;
542 int callwaitcas;
543 int callwaitrings;
544 int echocancel;
545 int echotraining;
546 char echorest[20];
547 int busycount;
548 int busy_tonelength;
549 int busy_quietlength;
550 int callprogress;
551 struct timeval flashtime; /*!< Last flash-hook time */
552 struct ast_dsp *dsp;
553 int cref; /*!< Call reference number */
554 struct dahdi_dialoperation dop;
555 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
556 char finaldial[64];
557 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
558 int amaflags; /*!< AMA Flags */
559 struct tdd_state *tdd; /*!< TDD flag */
560 char call_forward[AST_MAX_EXTENSION];
561 char mailbox[AST_MAX_EXTENSION];
562 char dialdest[256];
563 int onhooktime;
564 int msgstate;
565 int distinctivering; /*!< Which distinctivering to use */
566 int cidrings; /*!< Which ring to deliver CID on */
567 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
568 int fake_event;
569 int polarityonanswerdelay;
570 struct timeval polaritydelaytv;
571 int sendcalleridafter;
572 #ifdef HAVE_PRI
573 struct dahdi_pri *pri;
574 struct dahdi_pvt *bearer;
575 struct dahdi_pvt *realcall;
576 q931_call *call;
577 int prioffset;
578 int logicalspan;
579 #endif
580 int polarity;
581 int dsp_features;
582 char begindigit;
583 } *iflist = NULL, *ifend = NULL;
585 /*! \brief Channel configuration from chan_dahdi.conf .
586 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
587 * Generally there is a field here for every possible configuration item.
589 * The state of fields is saved along the parsing and whenever a 'channel'
590 * statement is reached, the current dahdi_chan_conf is used to configure the
591 * channel (struct dahdi_pvt)
593 * @seealso dahdi_chan_init for the default values.
595 struct dahdi_chan_conf {
596 struct dahdi_pvt chan;
597 #ifdef HAVE_PRI
598 struct dahdi_pri pri;
599 #endif
600 struct dahdi_params timing;
602 char smdi_port[SMDI_MAX_FILENAME_LEN];
605 /** returns a new dahdi_chan_conf with default values (by-value) */
606 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
607 /* recall that if a field is not included here it is initialized
608 * to 0 or equivalent
610 struct dahdi_chan_conf conf = {
611 #ifdef HAVE_PRI
612 .pri = {
613 .nsf = PRI_NSF_NONE,
614 .switchtype = PRI_SWITCH_NI2,
615 .dialplan = PRI_NATIONAL_ISDN + 1,
616 .localdialplan = PRI_NATIONAL_ISDN + 1,
617 .nodetype = PRI_CPE,
619 .minunused = 2,
620 .idleext = "",
621 .idledial = "",
622 .internationalprefix = "",
623 .nationalprefix = "",
624 .localprefix = "",
625 .privateprefix = "",
626 .unknownprefix = "",
628 .resetinterval = 3600
630 #endif
631 .chan = {
632 .context = "default",
633 .cid_num = "",
634 .cid_name = "",
635 .mohinterpret = "default",
636 .mohsuggest = "",
637 .transfertobusy = 1,
639 .cid_signalling = CID_SIG_BELL,
640 .cid_start = CID_START_RING,
641 .dahditrcallerid = 0,
642 .use_callerid = 1,
643 .sig = -1,
644 .outsigmod = -1,
646 .tonezone = -1,
648 .echocancel = 1,
650 .busycount = 3,
652 .accountcode = "",
654 .mailbox = "",
657 .polarityonanswerdelay = 600,
659 .sendcalleridafter = DEFAULT_CIDRINGS,
661 .buf_policy = DAHDI_POLICY_IMMEDIATE,
662 .buf_no = numbufs
664 .timing = {
665 .prewinktime = -1,
666 .preflashtime = -1,
667 .winktime = -1,
668 .flashtime = -1,
669 .starttime = -1,
670 .rxwinktime = -1,
671 .rxflashtime = -1,
672 .debouncetime = -1
674 .smdi_port = "/dev/ttyS0",
677 return conf;
681 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
682 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
683 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
684 static int dahdi_sendtext(struct ast_channel *c, const char *text);
685 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
686 static int dahdi_hangup(struct ast_channel *ast);
687 static int dahdi_answer(struct ast_channel *ast);
688 static struct ast_frame *dahdi_read(struct ast_channel *ast);
689 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
690 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
691 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
692 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
693 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
694 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
696 static const struct ast_channel_tech dahdi_tech = {
697 .type = "DAHDI",
698 .description = tdesc,
699 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
700 .requester = dahdi_request,
701 .send_digit_begin = dahdi_digit_begin,
702 .send_digit_end = dahdi_digit_end,
703 .send_text = dahdi_sendtext,
704 .call = dahdi_call,
705 .hangup = dahdi_hangup,
706 .answer = dahdi_answer,
707 .read = dahdi_read,
708 .write = dahdi_write,
709 .bridge = dahdi_bridge,
710 .exception = dahdi_exception,
711 .indicate = dahdi_indicate,
712 .fixup = dahdi_fixup,
713 .setoption = dahdi_setoption,
714 .func_channel_read = dahdi_func_read,
717 static const struct ast_channel_tech zap_tech = {
718 .type = "Zap",
719 .description = tdesc,
720 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
721 .requester = dahdi_request,
722 .send_digit_begin = dahdi_digit_begin,
723 .send_digit_end = dahdi_digit_end,
724 .send_text = dahdi_sendtext,
725 .call = dahdi_call,
726 .hangup = dahdi_hangup,
727 .answer = dahdi_answer,
728 .read = dahdi_read,
729 .write = dahdi_write,
730 .bridge = dahdi_bridge,
731 .exception = dahdi_exception,
732 .indicate = dahdi_indicate,
733 .fixup = dahdi_fixup,
734 .setoption = dahdi_setoption,
735 .func_channel_read = dahdi_func_read,
738 static const struct ast_channel_tech *chan_tech;
740 #ifdef HAVE_PRI
741 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
742 #else
743 #define GET_CHANNEL(p) ((p)->channel)
744 #endif
746 struct dahdi_pvt *round_robin[32];
748 #ifdef HAVE_PRI
749 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
751 int res;
752 /* Grab the lock first */
753 do {
754 res = ast_mutex_trylock(&pri->lock);
755 if (res) {
756 DEADLOCK_AVOIDANCE(&pvt->lock);
758 } while (res);
759 /* Then break the poll */
760 if (pri->master != AST_PTHREADT_NULL)
761 pthread_kill(pri->master, SIGURG);
762 return 0;
764 #endif
766 #define NUM_CADENCE_MAX 25
767 static int num_cadence = 4;
768 static int user_has_defined_cadences = 0;
770 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
771 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
772 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
773 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
774 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
777 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
778 * is 1, the second pause is 2 and so on.
781 static int cidrings[NUM_CADENCE_MAX] = {
782 2, /*!< Right after first long ring */
783 4, /*!< Right after long part */
784 3, /*!< After third chirp */
785 2, /*!< Second spell */
788 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
789 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
791 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
792 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
794 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
796 int res;
797 if (p->subs[SUB_REAL].owner == ast)
798 res = 0;
799 else if (p->subs[SUB_CALLWAIT].owner == ast)
800 res = 1;
801 else if (p->subs[SUB_THREEWAY].owner == ast)
802 res = 2;
803 else {
804 res = -1;
805 if (!nullok)
806 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
808 return res;
811 #ifdef HAVE_PRI
812 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
813 #else
814 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
815 #endif
817 #ifdef HAVE_PRI
818 if (pri)
819 ast_mutex_unlock(&pri->lock);
820 #endif
821 for (;;) {
822 if (p->subs[a].owner) {
823 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
824 DEADLOCK_AVOIDANCE(&p->lock);
825 } else {
826 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
827 ast_mutex_unlock(&p->subs[a].owner->lock);
828 break;
830 } else
831 break;
833 #ifdef HAVE_PRI
834 if (pri)
835 ast_mutex_lock(&pri->lock);
836 #endif
839 #ifdef HAVE_PRI
840 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
841 #else
842 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
843 #endif
845 /* We must unlock the PRI to avoid the possibility of a deadlock */
846 #ifdef HAVE_PRI
847 if (pri)
848 ast_mutex_unlock(&pri->lock);
849 #endif
850 for (;;) {
851 if (p->owner) {
852 if (ast_mutex_trylock(&p->owner->lock)) {
853 DEADLOCK_AVOIDANCE(&p->lock);
854 } else {
855 ast_queue_frame(p->owner, f);
856 ast_mutex_unlock(&p->owner->lock);
857 break;
859 } else
860 break;
862 #ifdef HAVE_PRI
863 if (pri)
864 ast_mutex_lock(&pri->lock);
865 #endif
868 static int restore_gains(struct dahdi_pvt *p);
870 static void swap_subs(struct dahdi_pvt *p, int a, int b)
872 int tchan;
873 int tinthreeway;
874 struct ast_channel *towner;
876 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
878 tchan = p->subs[a].chan;
879 towner = p->subs[a].owner;
880 tinthreeway = p->subs[a].inthreeway;
882 p->subs[a].chan = p->subs[b].chan;
883 p->subs[a].owner = p->subs[b].owner;
884 p->subs[a].inthreeway = p->subs[b].inthreeway;
886 p->subs[b].chan = tchan;
887 p->subs[b].owner = towner;
888 p->subs[b].inthreeway = tinthreeway;
890 if (p->subs[a].owner)
891 p->subs[a].owner->fds[0] = p->subs[a].dfd;
892 if (p->subs[b].owner)
893 p->subs[b].owner->fds[0] = p->subs[b].dfd;
894 wakeup_sub(p, a, NULL);
895 wakeup_sub(p, b, NULL);
898 static int dahdi_open(char *fn)
900 int fd;
901 int isnum;
902 int chan = 0;
903 int bs;
904 int x;
905 isnum = 1;
906 for (x = 0; x < strlen(fn); x++) {
907 if (!isdigit(fn[x])) {
908 isnum = 0;
909 break;
912 if (isnum) {
913 chan = atoi(fn);
914 if (chan < 1) {
915 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
916 return -1;
918 #ifdef HAVE_ZAPTEL
919 fn = "/dev/zap/channel";
920 #else
921 fn = "/dev/dahdi/channel";
922 #endif
924 fd = open(fn, O_RDWR | O_NONBLOCK);
925 if (fd < 0) {
926 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
927 return -1;
929 if (chan) {
930 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
931 x = errno;
932 close(fd);
933 errno = x;
934 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
935 return -1;
938 bs = READ_SIZE;
939 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
940 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
941 x = errno;
942 close(fd);
943 errno = x;
944 return -1;
946 return fd;
949 static void dahdi_close(int fd)
951 if (fd > 0)
952 close(fd);
955 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
957 dahdi_close(chan_pvt->subs[sub_num].dfd);
958 chan_pvt->subs[sub_num].dfd = -1;
961 #ifdef HAVE_PRI
962 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
964 dahdi_close(pri->fds[fd_num]);
965 pri->fds[fd_num] = -1;
967 #endif
969 static int dahdi_setlinear(int dfd, int linear)
971 int res;
972 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
973 if (res)
974 return res;
975 return 0;
979 static int alloc_sub(struct dahdi_pvt *p, int x)
981 struct dahdi_bufferinfo bi;
982 int res;
983 if (p->subs[x].dfd < 0) {
984 #ifdef HAVE_ZAPTEL
985 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
986 #else
987 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
988 #endif
989 if (p->subs[x].dfd > -1) {
990 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
991 if (!res) {
992 bi.txbufpolicy = p->buf_policy;
993 bi.rxbufpolicy = p->buf_policy;
994 bi.numbufs = p->buf_no;
995 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
996 if (res < 0) {
997 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
999 } else
1000 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
1001 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
1002 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
1003 dahdi_close_sub(p, x);
1004 return -1;
1006 if (option_debug)
1007 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
1008 return 0;
1009 } else
1010 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
1011 return -1;
1013 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
1014 return -1;
1017 static int unalloc_sub(struct dahdi_pvt *p, int x)
1019 if (!x) {
1020 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
1021 return -1;
1023 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
1024 dahdi_close_sub(p, x);
1025 p->subs[x].linear = 0;
1026 p->subs[x].chan = 0;
1027 p->subs[x].owner = NULL;
1028 p->subs[x].inthreeway = 0;
1029 p->polarity = POLARITY_IDLE;
1030 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
1031 return 0;
1034 static int digit_to_dtmfindex(char digit)
1036 if (isdigit(digit))
1037 return DAHDI_TONE_DTMF_BASE + (digit - '0');
1038 else if (digit >= 'A' && digit <= 'D')
1039 return DAHDI_TONE_DTMF_A + (digit - 'A');
1040 else if (digit >= 'a' && digit <= 'd')
1041 return DAHDI_TONE_DTMF_A + (digit - 'a');
1042 else if (digit == '*')
1043 return DAHDI_TONE_DTMF_s;
1044 else if (digit == '#')
1045 return DAHDI_TONE_DTMF_p;
1046 else
1047 return -1;
1050 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1052 struct dahdi_pvt *pvt;
1053 int index;
1054 int dtmf = -1;
1056 pvt = chan->tech_pvt;
1058 ast_mutex_lock(&pvt->lock);
1060 index = dahdi_get_index(chan, pvt, 0);
1062 if ((index != SUB_REAL) || !pvt->owner)
1063 goto out;
1065 #ifdef HAVE_PRI
1066 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1067 if (pvt->setup_ack) {
1068 if (!pri_grab(pvt, pvt->pri)) {
1069 pri_information(pvt->pri->pri, pvt->call, digit);
1070 pri_rel(pvt->pri);
1071 } else
1072 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1073 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1074 int res;
1075 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1076 res = strlen(pvt->dialdest);
1077 pvt->dialdest[res++] = digit;
1078 pvt->dialdest[res] = '\0';
1080 goto out;
1082 #endif
1083 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1084 goto out;
1086 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1087 int res;
1088 struct dahdi_dialoperation zo = {
1089 .op = DAHDI_DIAL_OP_APPEND,
1090 .dialstr[0] = 'T',
1091 .dialstr[1] = digit,
1092 .dialstr[2] = 0,
1094 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1095 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1096 else
1097 pvt->dialing = 1;
1098 } else {
1099 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1100 pvt->dialing = 1;
1101 pvt->begindigit = digit;
1104 out:
1105 ast_mutex_unlock(&pvt->lock);
1107 return 0;
1110 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1112 struct dahdi_pvt *pvt;
1113 int res = 0;
1114 int index;
1115 int x;
1117 pvt = chan->tech_pvt;
1119 ast_mutex_lock(&pvt->lock);
1121 index = dahdi_get_index(chan, pvt, 0);
1123 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1124 goto out;
1126 #ifdef HAVE_PRI
1127 /* This means that the digit was already sent via PRI signalling */
1128 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1129 goto out;
1130 #endif
1132 if (pvt->begindigit) {
1133 x = -1;
1134 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1135 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1136 pvt->dialing = 0;
1137 pvt->begindigit = 0;
1140 out:
1141 ast_mutex_unlock(&pvt->lock);
1143 return res;
1146 static char *events[] = {
1147 "No event",
1148 "On hook",
1149 "Ring/Answered",
1150 "Wink/Flash",
1151 "Alarm",
1152 "No more alarm",
1153 "HDLC Abort",
1154 "HDLC Overrun",
1155 "HDLC Bad FCS",
1156 "Dial Complete",
1157 "Ringer On",
1158 "Ringer Off",
1159 "Hook Transition Complete",
1160 "Bits Changed",
1161 "Pulse Start",
1162 "Timer Expired",
1163 "Timer Ping",
1164 "Polarity Reversal",
1165 "Ring Begin",
1168 static struct {
1169 int alarm;
1170 char *name;
1171 } alarms[] = {
1172 { DAHDI_ALARM_RED, "Red Alarm" },
1173 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1174 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1175 { DAHDI_ALARM_RECOVER, "Recovering" },
1176 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1177 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1178 { DAHDI_ALARM_NONE, "None" },
1181 static char *alarm2str(int alarm)
1183 int x;
1184 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1185 if (alarms[x].alarm & alarm)
1186 return alarms[x].name;
1188 return alarm ? "Unknown Alarm" : "No Alarm";
1191 static char *event2str(int event)
1193 static char buf[256];
1194 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1195 return events[event];
1196 sprintf(buf, "Event %d", event); /* safe */
1197 return buf;
1200 #ifdef HAVE_PRI
1201 static char *dialplan2str(int dialplan)
1203 if (dialplan == -1) {
1204 return("Dynamically set dialplan in ISDN");
1206 return (pri_plan2str(dialplan));
1208 #endif
1210 static char *dahdi_sig2str(int sig)
1212 static char buf[256];
1213 switch (sig) {
1214 case SIG_EM:
1215 return "E & M Immediate";
1216 case SIG_EMWINK:
1217 return "E & M Wink";
1218 case SIG_EM_E1:
1219 return "E & M E1";
1220 case SIG_FEATD:
1221 return "Feature Group D (DTMF)";
1222 case SIG_FEATDMF:
1223 return "Feature Group D (MF)";
1224 case SIG_FEATDMF_TA:
1225 return "Feature Groud D (MF) Tandem Access";
1226 case SIG_FEATB:
1227 return "Feature Group B (MF)";
1228 case SIG_E911:
1229 return "E911 (MF)";
1230 case SIG_FGC_CAMA:
1231 return "FGC/CAMA (Dialpulse)";
1232 case SIG_FGC_CAMAMF:
1233 return "FGC/CAMA (MF)";
1234 case SIG_FXSLS:
1235 return "FXS Loopstart";
1236 case SIG_FXSGS:
1237 return "FXS Groundstart";
1238 case SIG_FXSKS:
1239 return "FXS Kewlstart";
1240 case SIG_FXOLS:
1241 return "FXO Loopstart";
1242 case SIG_FXOGS:
1243 return "FXO Groundstart";
1244 case SIG_FXOKS:
1245 return "FXO Kewlstart";
1246 case SIG_PRI:
1247 return "ISDN PRI";
1248 case SIG_SF:
1249 return "SF (Tone) Immediate";
1250 case SIG_SFWINK:
1251 return "SF (Tone) Wink";
1252 case SIG_SF_FEATD:
1253 return "SF (Tone) with Feature Group D (DTMF)";
1254 case SIG_SF_FEATDMF:
1255 return "SF (Tone) with Feature Group D (MF)";
1256 case SIG_SF_FEATB:
1257 return "SF (Tone) with Feature Group B (MF)";
1258 case SIG_GR303FXOKS:
1259 return "GR-303 with FXOKS";
1260 case SIG_GR303FXSKS:
1261 return "GR-303 with FXSKS";
1262 case 0:
1263 return "Pseudo";
1264 default:
1265 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1266 return buf;
1270 #define sig2str dahdi_sig2str
1272 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1274 /* If the conference already exists, and we're already in it
1275 don't bother doing anything */
1276 struct dahdi_confinfo zi;
1278 memset(&zi, 0, sizeof(zi));
1279 zi.chan = 0;
1281 if (slavechannel > 0) {
1282 /* If we have only one slave, do a digital mon */
1283 zi.confmode = DAHDI_CONF_DIGITALMON;
1284 zi.confno = slavechannel;
1285 } else {
1286 if (!index) {
1287 /* Real-side and pseudo-side both participate in conference */
1288 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1289 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1290 } else
1291 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1292 zi.confno = p->confno;
1294 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1295 return 0;
1296 if (c->dfd < 0)
1297 return 0;
1298 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1299 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1300 return -1;
1302 if (slavechannel < 1) {
1303 p->confno = zi.confno;
1305 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1306 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1307 return 0;
1310 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1312 /* If they're listening to our channel, they're ours */
1313 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1314 return 1;
1315 /* If they're a talker on our (allocated) conference, they're ours */
1316 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1317 return 1;
1318 return 0;
1321 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1323 struct dahdi_confinfo zi;
1324 if (/* Can't delete if there's no dfd */
1325 (c->dfd < 0) ||
1326 /* Don't delete from the conference if it's not our conference */
1327 !isourconf(p, c)
1328 /* Don't delete if we don't think it's conferenced at all (implied) */
1329 ) return 0;
1330 memset(&zi, 0, sizeof(zi));
1331 zi.chan = 0;
1332 zi.confno = 0;
1333 zi.confmode = 0;
1334 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1335 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1336 return -1;
1338 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1339 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1340 return 0;
1343 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1345 int x;
1346 int useslavenative;
1347 struct dahdi_pvt *slave = NULL;
1348 /* Start out optimistic */
1349 useslavenative = 1;
1350 /* Update conference state in a stateless fashion */
1351 for (x = 0; x < 3; x++) {
1352 /* Any three-way calling makes slave native mode *definitely* out
1353 of the question */
1354 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1355 useslavenative = 0;
1357 /* If we don't have any 3-way calls, check to see if we have
1358 precisely one slave */
1359 if (useslavenative) {
1360 for (x = 0; x < MAX_SLAVES; x++) {
1361 if (p->slaves[x]) {
1362 if (slave) {
1363 /* Whoops already have a slave! No
1364 slave native and stop right away */
1365 slave = NULL;
1366 useslavenative = 0;
1367 break;
1368 } else {
1369 /* We have one slave so far */
1370 slave = p->slaves[x];
1375 /* If no slave, slave native definitely out */
1376 if (!slave)
1377 useslavenative = 0;
1378 else if (slave->law != p->law) {
1379 useslavenative = 0;
1380 slave = NULL;
1382 if (out)
1383 *out = slave;
1384 return useslavenative;
1387 static int reset_conf(struct dahdi_pvt *p)
1389 struct dahdi_confinfo zi;
1390 memset(&zi, 0, sizeof(zi));
1391 p->confno = -1;
1392 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1393 if (p->subs[SUB_REAL].dfd > -1) {
1394 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1395 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1397 return 0;
1400 static int update_conf(struct dahdi_pvt *p)
1402 int needconf = 0;
1403 int x;
1404 int useslavenative;
1405 struct dahdi_pvt *slave = NULL;
1407 useslavenative = isslavenative(p, &slave);
1408 /* Start with the obvious, general stuff */
1409 for (x = 0; x < 3; x++) {
1410 /* Look for three way calls */
1411 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1412 conf_add(p, &p->subs[x], x, 0);
1413 needconf++;
1414 } else {
1415 conf_del(p, &p->subs[x], x);
1418 /* If we have a slave, add him to our conference now. or DAX
1419 if this is slave native */
1420 for (x = 0; x < MAX_SLAVES; x++) {
1421 if (p->slaves[x]) {
1422 if (useslavenative)
1423 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1424 else {
1425 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1426 needconf++;
1430 /* If we're supposed to be in there, do so now */
1431 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1432 if (useslavenative)
1433 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1434 else {
1435 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1436 needconf++;
1439 /* If we have a master, add ourselves to his conference */
1440 if (p->master) {
1441 if (isslavenative(p->master, NULL)) {
1442 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1443 } else {
1444 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1447 if (!needconf) {
1448 /* Nobody is left (or should be left) in our conference.
1449 Kill it. */
1450 p->confno = -1;
1452 if (option_debug)
1453 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1454 return 0;
1457 static void dahdi_enable_ec(struct dahdi_pvt *p)
1459 int x;
1460 int res;
1461 if (!p)
1462 return;
1463 if (p->echocanon) {
1464 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1465 return;
1467 if (p->digital) {
1468 ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
1469 return;
1471 if (p->echocancel) {
1472 if (p->sig == SIG_PRI) {
1473 x = 1;
1474 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1475 if (res)
1476 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1478 x = p->echocancel;
1479 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1480 if (res)
1481 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1482 else {
1483 p->echocanon = 1;
1484 if (option_debug)
1485 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1487 } else if (option_debug)
1488 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1491 static void dahdi_train_ec(struct dahdi_pvt *p)
1493 int x;
1494 int res;
1495 if (p && p->echocancel && p->echotraining) {
1496 x = p->echotraining;
1497 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1498 if (res)
1499 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1500 else {
1501 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1503 } else
1504 ast_log(LOG_DEBUG, "No echo training requested\n");
1507 static void dahdi_disable_ec(struct dahdi_pvt *p)
1509 int x;
1510 int res;
1511 if (p->echocancel) {
1512 x = 0;
1513 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1514 if (res)
1515 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1516 else if (option_debug)
1517 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1519 p->echocanon = 0;
1522 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
1524 int j;
1525 int k;
1526 float linear_gain = pow(10.0, gain / 20.0);
1528 switch (law) {
1529 case DAHDI_LAW_ALAW:
1530 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1531 if (gain) {
1532 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1533 if (k > 32767) k = 32767;
1534 if (k < -32767) k = -32767;
1535 g->txgain[j] = AST_LIN2A(k);
1536 } else {
1537 g->txgain[j] = j;
1540 break;
1541 case DAHDI_LAW_MULAW:
1542 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1543 if (gain) {
1544 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1545 if (k > 32767) k = 32767;
1546 if (k < -32767) k = -32767;
1547 g->txgain[j] = AST_LIN2MU(k);
1548 } else {
1549 g->txgain[j] = j;
1552 break;
1556 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
1558 int j;
1559 int k;
1560 float linear_gain = pow(10.0, gain / 20.0);
1562 switch (law) {
1563 case DAHDI_LAW_ALAW:
1564 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1565 if (gain) {
1566 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1567 if (k > 32767) k = 32767;
1568 if (k < -32767) k = -32767;
1569 g->rxgain[j] = AST_LIN2A(k);
1570 } else {
1571 g->rxgain[j] = j;
1574 break;
1575 case DAHDI_LAW_MULAW:
1576 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1577 if (gain) {
1578 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1579 if (k > 32767) k = 32767;
1580 if (k < -32767) k = -32767;
1581 g->rxgain[j] = AST_LIN2MU(k);
1582 } else {
1583 g->rxgain[j] = j;
1586 break;
1590 static int set_actual_txgain(int fd, int chan, float gain, int law)
1592 struct dahdi_gains g;
1593 int res;
1595 memset(&g, 0, sizeof(g));
1596 g.chan = chan;
1597 res = ioctl(fd, DAHDI_GETGAINS, &g);
1598 if (res) {
1599 if (option_debug)
1600 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1601 return res;
1604 fill_txgain(&g, gain, law);
1606 return ioctl(fd, DAHDI_SETGAINS, &g);
1609 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1611 struct dahdi_gains g;
1612 int res;
1614 memset(&g, 0, sizeof(g));
1615 g.chan = chan;
1616 res = ioctl(fd, DAHDI_GETGAINS, &g);
1617 if (res) {
1618 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1619 return res;
1622 fill_rxgain(&g, gain, law);
1624 return ioctl(fd, DAHDI_SETGAINS, &g);
1627 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1629 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1632 static int bump_gains(struct dahdi_pvt *p)
1634 int res;
1636 /* Bump receive gain by 5.0db */
1637 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1638 if (res) {
1639 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1640 return -1;
1643 return 0;
1646 static int restore_gains(struct dahdi_pvt *p)
1648 int res;
1650 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1651 if (res) {
1652 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1653 return -1;
1656 return 0;
1659 static inline int dahdi_set_hook(int fd, int hs)
1661 int x, res;
1663 x = hs;
1664 res = ioctl(fd, DAHDI_HOOK, &x);
1666 if (res < 0) {
1667 if (errno == EINPROGRESS)
1668 return 0;
1669 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
1670 /* will expectedly fail if phone is off hook during operation, such as during a restart */
1673 return res;
1676 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1678 int x, y, res;
1679 x = muted;
1680 if (p->sig == SIG_PRI) {
1681 y = 1;
1682 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1683 if (res)
1684 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1686 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1687 if (res < 0)
1688 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1689 return res;
1692 static int save_conference(struct dahdi_pvt *p)
1694 struct dahdi_confinfo c;
1695 int res;
1696 if (p->saveconf.confmode) {
1697 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1698 return -1;
1700 p->saveconf.chan = 0;
1701 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1702 if (res) {
1703 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1704 p->saveconf.confmode = 0;
1705 return -1;
1707 c.chan = 0;
1708 c.confno = 0;
1709 c.confmode = DAHDI_CONF_NORMAL;
1710 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1711 if (res) {
1712 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1713 return -1;
1715 if (option_debug)
1716 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1717 return 0;
1720 static int restore_conference(struct dahdi_pvt *p)
1722 int res;
1723 if (p->saveconf.confmode) {
1724 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1725 p->saveconf.confmode = 0;
1726 if (res) {
1727 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1728 return -1;
1731 if (option_debug)
1732 ast_log(LOG_DEBUG, "Restored conferencing\n");
1733 return 0;
1736 static int send_callerid(struct dahdi_pvt *p);
1738 static int send_cwcidspill(struct dahdi_pvt *p)
1740 p->callwaitcas = 0;
1741 p->cidcwexpire = 0;
1742 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1743 return -1;
1744 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1745 /* Make sure we account for the end */
1746 p->cidlen += READ_SIZE * 4;
1747 p->cidpos = 0;
1748 send_callerid(p);
1749 if (option_verbose > 2)
1750 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1751 return 0;
1754 static int has_voicemail(struct dahdi_pvt *p)
1757 return ast_app_has_voicemail(p->mailbox, NULL);
1760 static int send_callerid(struct dahdi_pvt *p)
1762 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1763 int res;
1764 /* Take out of linear mode if necessary */
1765 if (p->subs[SUB_REAL].linear) {
1766 p->subs[SUB_REAL].linear = 0;
1767 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1769 while (p->cidpos < p->cidlen) {
1770 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1771 if (res < 0) {
1772 if (errno == EAGAIN)
1773 return 0;
1774 else {
1775 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1776 return -1;
1779 if (!res)
1780 return 0;
1781 p->cidpos += res;
1783 free(p->cidspill);
1784 p->cidspill = NULL;
1785 if (p->callwaitcas) {
1786 /* Wait for CID/CW to expire */
1787 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1788 } else
1789 restore_conference(p);
1790 return 0;
1793 static int dahdi_callwait(struct ast_channel *ast)
1795 struct dahdi_pvt *p = ast->tech_pvt;
1796 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1797 if (p->cidspill) {
1798 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1799 free(p->cidspill);
1801 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1802 return -1;
1803 save_conference(p);
1804 /* Silence */
1805 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1806 if (!p->callwaitrings && p->callwaitingcallerid) {
1807 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1808 p->callwaitcas = 1;
1809 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1810 } else {
1811 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1812 p->callwaitcas = 0;
1813 p->cidlen = 2400 + READ_SIZE * 4;
1815 p->cidpos = 0;
1816 send_callerid(p);
1818 return 0;
1821 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1823 struct dahdi_pvt *p = ast->tech_pvt;
1824 int x, res, index,mysig;
1825 char *c, *n, *l;
1826 #ifdef HAVE_PRI
1827 char *s = NULL;
1828 #endif
1829 char dest[256]; /* must be same length as p->dialdest */
1830 ast_mutex_lock(&p->lock);
1831 ast_copy_string(dest, rdest, sizeof(dest));
1832 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1833 if ((ast->_state == AST_STATE_BUSY)) {
1834 p->subs[SUB_REAL].needbusy = 1;
1835 ast_mutex_unlock(&p->lock);
1836 return 0;
1838 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1839 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1840 ast_mutex_unlock(&p->lock);
1841 return -1;
1843 p->dialednone = 0;
1844 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1846 /* Special pseudo -- automatically up */
1847 ast_setstate(ast, AST_STATE_UP);
1848 ast_mutex_unlock(&p->lock);
1849 return 0;
1851 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1852 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1853 if (res)
1854 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1855 p->outgoing = 1;
1857 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1859 mysig = p->sig;
1860 if (p->outsigmod > -1)
1861 mysig = p->outsigmod;
1863 switch (mysig) {
1864 case SIG_FXOLS:
1865 case SIG_FXOGS:
1866 case SIG_FXOKS:
1867 if (p->owner == ast) {
1868 /* Normal ring, on hook */
1870 /* Don't send audio while on hook, until the call is answered */
1871 p->dialing = 1;
1872 if (p->use_callerid) {
1873 /* Generate the Caller-ID spill if desired */
1874 if (p->cidspill) {
1875 ast_log(LOG_WARNING, "cidspill already exists??\n");
1876 free(p->cidspill);
1878 p->callwaitcas = 0;
1879 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1880 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1881 p->cidpos = 0;
1882 send_callerid(p);
1885 /* Choose proper cadence */
1886 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1887 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1888 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1889 p->cidrings = cidrings[p->distinctivering - 1];
1890 } else {
1891 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1892 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1893 p->cidrings = p->sendcalleridafter;
1896 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1897 c = strchr(dest, '/');
1898 if (c)
1899 c++;
1900 if (c && (strlen(c) < p->stripmsd)) {
1901 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1902 c = NULL;
1904 if (c) {
1905 p->dop.op = DAHDI_DIAL_OP_REPLACE;
1906 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
1907 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
1908 } else {
1909 p->dop.dialstr[0] = '\0';
1911 x = DAHDI_RING;
1912 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
1913 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
1914 ast_mutex_unlock(&p->lock);
1915 return -1;
1917 p->dialing = 1;
1918 } else {
1919 /* Call waiting call */
1920 p->callwaitrings = 0;
1921 if (ast->cid.cid_num)
1922 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
1923 else
1924 p->callwait_num[0] = '\0';
1925 if (ast->cid.cid_name)
1926 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
1927 else
1928 p->callwait_name[0] = '\0';
1929 /* Call waiting tone instead */
1930 if (dahdi_callwait(ast)) {
1931 ast_mutex_unlock(&p->lock);
1932 return -1;
1934 /* Make ring-back */
1935 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
1936 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
1939 n = ast->cid.cid_name;
1940 l = ast->cid.cid_num;
1941 if (l)
1942 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
1943 else
1944 p->lastcid_num[0] = '\0';
1945 if (n)
1946 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
1947 else
1948 p->lastcid_name[0] = '\0';
1949 ast_setstate(ast, AST_STATE_RINGING);
1950 index = dahdi_get_index(ast, p, 0);
1951 if (index > -1) {
1952 p->subs[index].needringing = 1;
1954 break;
1955 case SIG_FXSLS:
1956 case SIG_FXSGS:
1957 case SIG_FXSKS:
1958 case SIG_EMWINK:
1959 case SIG_EM:
1960 case SIG_EM_E1:
1961 case SIG_FEATD:
1962 case SIG_FEATDMF:
1963 case SIG_E911:
1964 case SIG_FGC_CAMA:
1965 case SIG_FGC_CAMAMF:
1966 case SIG_FEATB:
1967 case SIG_SFWINK:
1968 case SIG_SF:
1969 case SIG_SF_FEATD:
1970 case SIG_SF_FEATDMF:
1971 case SIG_FEATDMF_TA:
1972 case SIG_SF_FEATB:
1973 c = strchr(dest, '/');
1974 if (c)
1975 c++;
1976 else
1977 c = "";
1978 if (strlen(c) < p->stripmsd) {
1979 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1980 ast_mutex_unlock(&p->lock);
1981 return -1;
1983 #ifdef HAVE_PRI
1984 /* Start the trunk, if not GR-303 */
1985 if (!p->pri) {
1986 #endif
1987 x = DAHDI_START;
1988 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
1989 if (res < 0) {
1990 if (errno != EINPROGRESS) {
1991 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
1992 ast_mutex_unlock(&p->lock);
1993 return -1;
1996 #ifdef HAVE_PRI
1998 #endif
1999 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
2000 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2002 c += p->stripmsd;
2004 switch (mysig) {
2005 case SIG_FEATD:
2006 l = ast->cid.cid_num;
2007 if (l)
2008 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
2009 else
2010 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
2011 break;
2012 case SIG_FEATDMF:
2013 l = ast->cid.cid_num;
2014 if (l)
2015 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
2016 else
2017 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
2018 break;
2019 case SIG_FEATDMF_TA:
2021 const char *cic, *ozz;
2023 /* If you have to go through a Tandem Access point you need to use this */
2024 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
2025 if (!ozz)
2026 ozz = defaultozz;
2027 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
2028 if (!cic)
2029 cic = defaultcic;
2030 if (!ozz || !cic) {
2031 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2032 ast_mutex_unlock(&p->lock);
2033 return -1;
2035 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
2036 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
2037 p->whichwink = 0;
2039 break;
2040 case SIG_E911:
2041 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2042 break;
2043 case SIG_FGC_CAMA:
2044 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2045 break;
2046 case SIG_FGC_CAMAMF:
2047 case SIG_FEATB:
2048 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2049 break;
2050 default:
2051 if (p->pulse)
2052 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2053 else
2054 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2055 break;
2058 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2059 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2060 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2061 p->echorest[sizeof(p->echorest) - 1] = '\0';
2062 p->echobreak = 1;
2063 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2064 } else
2065 p->echobreak = 0;
2066 if (!res) {
2067 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2068 int saveerr = errno;
2070 x = DAHDI_ONHOOK;
2071 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2072 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2073 ast_mutex_unlock(&p->lock);
2074 return -1;
2076 } else
2077 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2078 p->dialing = 1;
2079 if (ast_strlen_zero(c))
2080 p->dialednone = 1;
2081 ast_setstate(ast, AST_STATE_DIALING);
2082 break;
2083 case 0:
2084 /* Special pseudo -- automatically up*/
2085 ast_setstate(ast, AST_STATE_UP);
2086 break;
2087 case SIG_PRI:
2088 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2089 p->dialdest[0] = '\0';
2090 break;
2091 default:
2092 ast_log(LOG_DEBUG, "not yet implemented\n");
2093 ast_mutex_unlock(&p->lock);
2094 return -1;
2096 #ifdef HAVE_PRI
2097 if (p->pri) {
2098 struct pri_sr *sr;
2099 #ifdef SUPPORT_USERUSER
2100 const char *useruser;
2101 #endif
2102 int pridialplan;
2103 int dp_strip;
2104 int prilocaldialplan;
2105 int ldp_strip;
2106 int exclusive;
2107 const char *rr_str;
2108 int redirect_reason;
2110 c = strchr(dest, '/');
2111 if (c)
2112 c++;
2113 else
2114 c = dest;
2116 l = NULL;
2117 n = NULL;
2119 if (!p->hidecallerid) {
2120 l = ast->cid.cid_num;
2121 if (!p->hidecalleridname) {
2122 n = ast->cid.cid_name;
2127 if (strlen(c) < p->stripmsd) {
2128 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2129 ast_mutex_unlock(&p->lock);
2130 return -1;
2132 if (mysig != SIG_FXSKS) {
2133 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2134 s = strchr(c + p->stripmsd, 'w');
2135 if (s) {
2136 if (strlen(s) > 1)
2137 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2138 else
2139 p->dop.dialstr[0] = '\0';
2140 *s = '\0';
2141 } else {
2142 p->dop.dialstr[0] = '\0';
2145 if (pri_grab(p, p->pri)) {
2146 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2147 ast_mutex_unlock(&p->lock);
2148 return -1;
2150 if (!(p->call = pri_new_call(p->pri->pri))) {
2151 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2152 pri_rel(p->pri);
2153 ast_mutex_unlock(&p->lock);
2154 return -1;
2156 if (!(sr = pri_sr_new())) {
2157 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2158 pri_destroycall(p->pri->pri, p->call);
2159 p->call = NULL;
2160 pri_rel(p->pri);
2161 ast_mutex_unlock(&p->lock);
2162 return -1;
2164 if (p->bearer || (mysig == SIG_FXSKS)) {
2165 if (p->bearer) {
2166 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);
2167 p->bearer->call = p->call;
2168 } else
2169 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2170 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2172 p->digital = IS_DIGITAL(ast->transfercapability);
2173 /* Add support for exclusive override */
2174 if (p->priexclusive)
2175 exclusive = 1;
2176 else {
2177 /* otherwise, traditional behavior */
2178 if (p->pri->nodetype == PRI_NETWORK)
2179 exclusive = 0;
2180 else
2181 exclusive = 1;
2184 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2185 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2186 (p->digital ? -1 :
2187 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
2188 if (p->pri->facilityenable)
2189 pri_facility_enable(p->pri->pri);
2191 if (option_verbose > 2)
2192 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2193 dp_strip = 0;
2194 pridialplan = p->pri->dialplan - 1;
2195 if (pridialplan == -2) { /* compute dynamically */
2196 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2197 dp_strip = strlen(p->pri->internationalprefix);
2198 pridialplan = PRI_INTERNATIONAL_ISDN;
2199 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2200 dp_strip = strlen(p->pri->nationalprefix);
2201 pridialplan = PRI_NATIONAL_ISDN;
2202 } else {
2203 pridialplan = PRI_LOCAL_ISDN;
2206 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2208 ldp_strip = 0;
2209 prilocaldialplan = p->pri->localdialplan - 1;
2210 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2211 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2212 ldp_strip = strlen(p->pri->internationalprefix);
2213 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2214 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2215 ldp_strip = strlen(p->pri->nationalprefix);
2216 prilocaldialplan = PRI_NATIONAL_ISDN;
2217 } else {
2218 prilocaldialplan = PRI_LOCAL_ISDN;
2221 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2222 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2223 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2224 if (!strcasecmp(rr_str, "UNKNOWN"))
2225 redirect_reason = 0;
2226 else if (!strcasecmp(rr_str, "BUSY"))
2227 redirect_reason = 1;
2228 else if (!strcasecmp(rr_str, "NO_REPLY"))
2229 redirect_reason = 2;
2230 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2231 redirect_reason = 15;
2232 else
2233 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2234 } else
2235 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2236 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2238 #ifdef SUPPORT_USERUSER
2239 /* User-user info */
2240 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2242 if (useruser)
2243 pri_sr_set_useruser(sr, useruser);
2244 #endif
2246 if (pri_setup(p->pri->pri, p->call, sr)) {
2247 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2248 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2249 pri_rel(p->pri);
2250 ast_mutex_unlock(&p->lock);
2251 pri_sr_free(sr);
2252 return -1;
2254 pri_sr_free(sr);
2255 ast_setstate(ast, AST_STATE_DIALING);
2256 pri_rel(p->pri);
2258 #endif
2259 ast_mutex_unlock(&p->lock);
2260 return 0;
2263 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2265 struct dahdi_pvt *p = *pvt;
2266 /* Remove channel from the list */
2267 if (p->prev)
2268 p->prev->next = p->next;
2269 if (p->next)
2270 p->next->prev = p->prev;
2271 if (p->use_smdi)
2272 ast_smdi_interface_unref(p->smdi_iface);
2273 ast_mutex_destroy(&p->lock);
2274 dahdi_close_sub(p, SUB_REAL);
2275 if (p->owner)
2276 p->owner->tech_pvt = NULL;
2277 free(p);
2278 *pvt = NULL;
2281 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2283 int owned = 0;
2284 int i = 0;
2286 if (!now) {
2287 if (cur->owner) {
2288 owned = 1;
2291 for (i = 0; i < 3; i++) {
2292 if (cur->subs[i].owner) {
2293 owned = 1;
2296 if (!owned) {
2297 if (prev) {
2298 prev->next = cur->next;
2299 if (prev->next)
2300 prev->next->prev = prev;
2301 else
2302 ifend = prev;
2303 } else {
2304 iflist = cur->next;
2305 if (iflist)
2306 iflist->prev = NULL;
2307 else
2308 ifend = NULL;
2310 destroy_dahdi_pvt(&cur);
2312 } else {
2313 if (prev) {
2314 prev->next = cur->next;
2315 if (prev->next)
2316 prev->next->prev = prev;
2317 else
2318 ifend = prev;
2319 } else {
2320 iflist = cur->next;
2321 if (iflist)
2322 iflist->prev = NULL;
2323 else
2324 ifend = NULL;
2326 destroy_dahdi_pvt(&cur);
2328 return 0;
2331 static void destroy_all_channels(void)
2333 int x;
2334 struct dahdi_pvt *p, *pl;
2336 while (num_restart_pending) {
2337 usleep(1);
2340 ast_mutex_lock(&iflock);
2341 /* Destroy all the interfaces and free their memory */
2342 p = iflist;
2343 while (p) {
2344 /* Free any callerid */
2345 if (p->cidspill)
2346 ast_free(p->cidspill);
2347 pl = p;
2348 p = p->next;
2349 x = pl->channel;
2350 /* Free associated memory */
2351 if (pl)
2352 destroy_dahdi_pvt(&pl);
2353 if (option_verbose > 2)
2354 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
2356 iflist = NULL;
2357 ifcount = 0;
2358 ast_mutex_unlock(&iflock);
2361 #ifdef HAVE_PRI
2362 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2363 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
2365 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2366 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2368 static char *dahdi_send_keypad_facility_descrip =
2369 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2370 " IE over the current channel.\n";
2371 static char *zap_send_keypad_facility_descrip =
2372 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2373 " IE over the current channel.\n";
2375 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
2377 /* Data will be our digit string */
2378 struct dahdi_pvt *p;
2379 char *digits = (char *) data;
2381 if (ast_strlen_zero(digits)) {
2382 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2383 return -1;
2386 p = (struct dahdi_pvt *)chan->tech_pvt;
2388 if (!p) {
2389 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2390 return -1;
2393 ast_mutex_lock(&p->lock);
2395 if (!p->pri || !p->call) {
2396 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2397 ast_mutex_unlock(&p->lock);
2398 return -1;
2401 if (!pri_grab(p, p->pri)) {
2402 pri_keypad_facility(p->pri->pri, p->call, digits);
2403 pri_rel(p->pri);
2404 } else {
2405 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2406 ast_mutex_unlock(&p->lock);
2407 return -1;
2410 ast_mutex_unlock(&p->lock);
2412 return 0;
2415 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2417 return send_keypad_facility_exec(chan, data);
2420 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2422 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);
2423 return send_keypad_facility_exec(chan, data);
2426 static int pri_is_up(struct dahdi_pri *pri)
2428 int x;
2429 for (x = 0; x < NUM_DCHANS; x++) {
2430 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2431 return 1;
2433 return 0;
2436 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2438 bearer->owner = &inuse;
2439 bearer->realcall = crv;
2440 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2441 if (crv->subs[SUB_REAL].owner)
2442 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2443 crv->bearer = bearer;
2444 crv->call = bearer->call;
2445 crv->pri = pri;
2446 return 0;
2449 static char *pri_order(int level)
2451 switch (level) {
2452 case 0:
2453 return "Primary";
2454 case 1:
2455 return "Secondary";
2456 case 2:
2457 return "Tertiary";
2458 case 3:
2459 return "Quaternary";
2460 default:
2461 return "<Unknown>";
2465 /* Returns fd of the active dchan */
2466 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2468 int x = -1;
2470 for (x = 0; x < NUM_DCHANS; x++) {
2471 if ((pri->dchans[x] == pri->pri))
2472 break;
2475 return pri->fds[x];
2478 static int pri_find_dchan(struct dahdi_pri *pri)
2480 int oldslot = -1;
2481 struct pri *old;
2482 int newslot = -1;
2483 int x;
2484 old = pri->pri;
2485 for (x = 0; x < NUM_DCHANS; x++) {
2486 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2487 newslot = x;
2488 if (pri->dchans[x] == old) {
2489 oldslot = x;
2492 if (newslot < 0) {
2493 newslot = 0;
2494 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2495 pri->dchannels[newslot]);
2497 if (old && (oldslot != newslot))
2498 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2499 pri->dchannels[oldslot], pri->dchannels[newslot]);
2500 pri->pri = pri->dchans[newslot];
2501 return 0;
2503 #endif
2505 static int dahdi_hangup(struct ast_channel *ast)
2507 int res;
2508 int index,x, law;
2509 /*static int restore_gains(struct dahdi_pvt *p);*/
2510 struct dahdi_pvt *p = ast->tech_pvt;
2511 struct dahdi_pvt *tmp = NULL;
2512 struct dahdi_pvt *prev = NULL;
2513 struct dahdi_params par;
2515 if (option_debug)
2516 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2517 if (!ast->tech_pvt) {
2518 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2519 return 0;
2522 ast_mutex_lock(&p->lock);
2524 index = dahdi_get_index(ast, p, 1);
2526 if (p->sig == SIG_PRI) {
2527 x = 1;
2528 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2531 x = 0;
2532 dahdi_confmute(p, 0);
2533 restore_gains(p);
2534 if (p->origcid_num) {
2535 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2536 free(p->origcid_num);
2537 p->origcid_num = NULL;
2539 if (p->origcid_name) {
2540 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2541 free(p->origcid_name);
2542 p->origcid_name = NULL;
2544 if (p->dsp)
2545 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2546 if (p->exten)
2547 p->exten[0] = '\0';
2549 if (option_debug)
2550 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2551 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2552 p->ignoredtmf = 0;
2554 if (index > -1) {
2555 /* Real channel, do some fixup */
2556 p->subs[index].owner = NULL;
2557 p->subs[index].needanswer = 0;
2558 p->subs[index].needflash = 0;
2559 p->subs[index].needringing = 0;
2560 p->subs[index].needbusy = 0;
2561 p->subs[index].needcongestion = 0;
2562 p->subs[index].linear = 0;
2563 p->subs[index].needcallerid = 0;
2564 p->polarity = POLARITY_IDLE;
2565 dahdi_setlinear(p->subs[index].dfd, 0);
2566 if (index == SUB_REAL) {
2567 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2568 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2569 if (p->subs[SUB_CALLWAIT].inthreeway) {
2570 /* We had flipped over to answer a callwait and now it's gone */
2571 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2572 /* Move to the call-wait, but un-own us until they flip back. */
2573 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2574 unalloc_sub(p, SUB_CALLWAIT);
2575 p->owner = NULL;
2576 } else {
2577 /* The three way hung up, but we still have a call wait */
2578 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2579 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2580 unalloc_sub(p, SUB_THREEWAY);
2581 if (p->subs[SUB_REAL].inthreeway) {
2582 /* This was part of a three way call. Immediately make way for
2583 another call */
2584 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2585 p->owner = p->subs[SUB_REAL].owner;
2586 } else {
2587 /* This call hasn't been completed yet... Set owner to NULL */
2588 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2589 p->owner = NULL;
2591 p->subs[SUB_REAL].inthreeway = 0;
2593 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2594 /* Move to the call-wait and switch back to them. */
2595 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2596 unalloc_sub(p, SUB_CALLWAIT);
2597 p->owner = p->subs[SUB_REAL].owner;
2598 if (p->owner->_state != AST_STATE_UP)
2599 p->subs[SUB_REAL].needanswer = 1;
2600 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2601 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2602 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2603 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2604 unalloc_sub(p, SUB_THREEWAY);
2605 if (p->subs[SUB_REAL].inthreeway) {
2606 /* This was part of a three way call. Immediately make way for
2607 another call */
2608 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2609 p->owner = p->subs[SUB_REAL].owner;
2610 } else {
2611 /* This call hasn't been completed yet... Set owner to NULL */
2612 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2613 p->owner = NULL;
2615 p->subs[SUB_REAL].inthreeway = 0;
2617 } else if (index == SUB_CALLWAIT) {
2618 /* Ditch the holding callwait call, and immediately make it availabe */
2619 if (p->subs[SUB_CALLWAIT].inthreeway) {
2620 /* This is actually part of a three way, placed on hold. Place the third part
2621 on music on hold now */
2622 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2623 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2624 S_OR(p->mohsuggest, NULL),
2625 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2627 p->subs[SUB_THREEWAY].inthreeway = 0;
2628 /* Make it the call wait now */
2629 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2630 unalloc_sub(p, SUB_THREEWAY);
2631 } else
2632 unalloc_sub(p, SUB_CALLWAIT);
2633 } else if (index == SUB_THREEWAY) {
2634 if (p->subs[SUB_CALLWAIT].inthreeway) {
2635 /* The other party of the three way call is currently in a call-wait state.
2636 Start music on hold for them, and take the main guy out of the third call */
2637 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2638 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2639 S_OR(p->mohsuggest, NULL),
2640 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2642 p->subs[SUB_CALLWAIT].inthreeway = 0;
2644 p->subs[SUB_REAL].inthreeway = 0;
2645 /* If this was part of a three way call index, let us make
2646 another three way call */
2647 unalloc_sub(p, SUB_THREEWAY);
2648 } else {
2649 /* This wasn't any sort of call, but how are we an index? */
2650 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2654 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2655 p->owner = NULL;
2656 p->ringt = 0;
2657 p->distinctivering = 0;
2658 p->confirmanswer = 0;
2659 p->cidrings = 1;
2660 p->outgoing = 0;
2661 p->digital = 0;
2662 p->faxhandled = 0;
2663 p->pulsedial = 0;
2664 p->onhooktime = time(NULL);
2665 #ifdef HAVE_PRI
2666 p->proceeding = 0;
2667 p->progress = 0;
2668 p->alerting = 0;
2669 p->setup_ack = 0;
2670 #endif
2671 if (p->dsp) {
2672 ast_dsp_free(p->dsp);
2673 p->dsp = NULL;
2676 law = DAHDI_LAW_DEFAULT;
2677 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2678 if (res < 0)
2679 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2680 /* Perform low level hangup if no owner left */
2681 #ifdef HAVE_PRI
2682 if (p->pri) {
2683 #ifdef SUPPORT_USERUSER
2684 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2685 #endif
2687 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2688 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2689 if (!pri_grab(p, p->pri)) {
2690 if (p->alreadyhungup) {
2691 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2693 #ifdef SUPPORT_USERUSER
2694 pri_call_set_useruser(p->call, useruser);
2695 #endif
2697 pri_hangup(p->pri->pri, p->call, -1);
2698 p->call = NULL;
2699 if (p->bearer)
2700 p->bearer->call = NULL;
2701 } else {
2702 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2703 int icause = ast->hangupcause ? ast->hangupcause : -1;
2704 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2706 #ifdef SUPPORT_USERUSER
2707 pri_call_set_useruser(p->call, useruser);
2708 #endif
2710 p->alreadyhungup = 1;
2711 if (p->bearer)
2712 p->bearer->alreadyhungup = 1;
2713 if (cause) {
2714 if (atoi(cause))
2715 icause = atoi(cause);
2717 pri_hangup(p->pri->pri, p->call, icause);
2719 if (res < 0)
2720 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2721 pri_rel(p->pri);
2722 } else {
2723 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2724 res = -1;
2726 } else {
2727 if (p->bearer)
2728 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2729 p->call = NULL;
2730 res = 0;
2733 #endif
2734 if (p->sig && (p->sig != SIG_PRI))
2735 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2736 if (res < 0) {
2737 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2739 switch (p->sig) {
2740 case SIG_FXOGS:
2741 case SIG_FXOLS:
2742 case SIG_FXOKS:
2743 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2744 if (!res) {
2745 #if 0
2746 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2747 #endif
2748 /* If they're off hook, try playing congestion */
2749 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2750 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2751 else
2752 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2754 break;
2755 case SIG_FXSGS:
2756 case SIG_FXSLS:
2757 case SIG_FXSKS:
2758 /* Make sure we're not made available for at least two seconds assuming
2759 we were actually used for an inbound or outbound call. */
2760 if (ast->_state != AST_STATE_RESERVED) {
2761 time(&p->guardtime);
2762 p->guardtime += 2;
2764 break;
2765 default:
2766 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2768 if (p->cidspill)
2769 free(p->cidspill);
2770 if (p->sig)
2771 dahdi_disable_ec(p);
2772 x = 0;
2773 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2774 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2775 p->didtdd = 0;
2776 p->cidspill = NULL;
2777 p->callwaitcas = 0;
2778 p->callwaiting = p->permcallwaiting;
2779 p->hidecallerid = p->permhidecallerid;
2780 p->dialing = 0;
2781 p->rdnis[0] = '\0';
2782 update_conf(p);
2783 reset_conf(p);
2784 /* Restore data mode */
2785 if (p->sig == SIG_PRI) {
2786 x = 0;
2787 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2789 #ifdef HAVE_PRI
2790 if (p->bearer) {
2791 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2792 /* Free up the bearer channel as well, and
2793 don't use its file descriptor anymore */
2794 update_conf(p->bearer);
2795 reset_conf(p->bearer);
2796 p->bearer->owner = NULL;
2797 p->bearer->realcall = NULL;
2798 p->bearer = NULL;
2799 p->subs[SUB_REAL].dfd = -1;
2800 p->pri = NULL;
2802 #endif
2803 if (num_restart_pending == 0)
2804 restart_monitor();
2807 p->callwaitingrepeat = 0;
2808 p->cidcwexpire = 0;
2809 p->oprmode = 0;
2810 ast->tech_pvt = NULL;
2811 ast_mutex_unlock(&p->lock);
2812 ast_module_unref(ast_module_info->self);
2813 if (option_verbose > 2)
2814 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2816 ast_mutex_lock(&iflock);
2818 if (p->restartpending) {
2819 num_restart_pending--;
2822 tmp = iflist;
2823 prev = NULL;
2824 if (p->destroy) {
2825 while (tmp) {
2826 if (tmp == p) {
2827 destroy_channel(prev, tmp, 0);
2828 break;
2829 } else {
2830 prev = tmp;
2831 tmp = tmp->next;
2835 ast_mutex_unlock(&iflock);
2836 return 0;
2839 static int dahdi_answer(struct ast_channel *ast)
2841 struct dahdi_pvt *p = ast->tech_pvt;
2842 int res = 0;
2843 int index;
2844 int oldstate = ast->_state;
2845 ast_setstate(ast, AST_STATE_UP);
2846 ast_mutex_lock(&p->lock);
2847 index = dahdi_get_index(ast, p, 0);
2848 if (index < 0)
2849 index = SUB_REAL;
2850 /* nothing to do if a radio channel */
2851 if ((p->radio || (p->oprmode < 0))) {
2852 ast_mutex_unlock(&p->lock);
2853 return 0;
2855 switch (p->sig) {
2856 case SIG_FXSLS:
2857 case SIG_FXSGS:
2858 case SIG_FXSKS:
2859 p->ringt = 0;
2860 /* Fall through */
2861 case SIG_EM:
2862 case SIG_EM_E1:
2863 case SIG_EMWINK:
2864 case SIG_FEATD:
2865 case SIG_FEATDMF:
2866 case SIG_FEATDMF_TA:
2867 case SIG_E911:
2868 case SIG_FGC_CAMA:
2869 case SIG_FGC_CAMAMF:
2870 case SIG_FEATB:
2871 case SIG_SF:
2872 case SIG_SFWINK:
2873 case SIG_SF_FEATD:
2874 case SIG_SF_FEATDMF:
2875 case SIG_SF_FEATB:
2876 case SIG_FXOLS:
2877 case SIG_FXOGS:
2878 case SIG_FXOKS:
2879 /* Pick up the line */
2880 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
2881 if (p->hanguponpolarityswitch) {
2882 gettimeofday(&p->polaritydelaytv, NULL);
2884 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
2885 tone_zone_play_tone(p->subs[index].dfd, -1);
2886 p->dialing = 0;
2887 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
2888 if (oldstate == AST_STATE_RINGING) {
2889 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
2890 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
2891 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2892 p->owner = p->subs[SUB_REAL].owner;
2895 if (p->sig & __DAHDI_SIG_FXS) {
2896 dahdi_enable_ec(p);
2897 dahdi_train_ec(p);
2899 break;
2900 #ifdef HAVE_PRI
2901 case SIG_PRI:
2902 /* Send a pri acknowledge */
2903 if (!pri_grab(p, p->pri)) {
2904 p->proceeding = 1;
2905 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
2906 pri_rel(p->pri);
2907 } else {
2908 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2909 res = -1;
2911 break;
2912 #endif
2913 case 0:
2914 ast_mutex_unlock(&p->lock);
2915 return 0;
2916 default:
2917 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
2918 res = -1;
2920 ast_mutex_unlock(&p->lock);
2921 return res;
2924 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
2926 char *cp;
2927 signed char *scp;
2928 int x;
2929 int index;
2930 struct dahdi_pvt *p = chan->tech_pvt, *pp;
2931 struct oprmode *oprmode;
2934 /* all supported options require data */
2935 if (!data || (datalen < 1)) {
2936 errno = EINVAL;
2937 return -1;
2940 switch (option) {
2941 case AST_OPTION_TXGAIN:
2942 scp = (signed char *) data;
2943 index = dahdi_get_index(chan, p, 0);
2944 if (index < 0) {
2945 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
2946 return -1;
2948 if (option_debug)
2949 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
2950 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
2951 case AST_OPTION_RXGAIN:
2952 scp = (signed char *) data;
2953 index = dahdi_get_index(chan, p, 0);
2954 if (index < 0) {
2955 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
2956 return -1;
2958 if (option_debug)
2959 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
2960 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
2961 case AST_OPTION_TONE_VERIFY:
2962 if (!p->dsp)
2963 break;
2964 cp = (char *) data;
2965 switch (*cp) {
2966 case 1:
2967 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
2968 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
2969 break;
2970 case 2:
2971 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
2972 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
2973 break;
2974 default:
2975 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
2976 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
2977 break;
2979 break;
2980 case AST_OPTION_TDD:
2981 /* turn on or off TDD */
2982 cp = (char *) data;
2983 p->mate = 0;
2984 if (!*cp) { /* turn it off */
2985 if (option_debug)
2986 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
2987 if (p->tdd)
2988 tdd_free(p->tdd);
2989 p->tdd = 0;
2990 break;
2992 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
2993 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
2994 dahdi_disable_ec(p);
2995 /* otherwise, turn it on */
2996 if (!p->didtdd) { /* if havent done it yet */
2997 unsigned char mybuf[41000], *buf;
2998 int size, res, fd, len;
2999 struct pollfd fds[1];
3001 buf = mybuf;
3002 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
3003 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
3004 len = 40000;
3005 index = dahdi_get_index(chan, p, 0);
3006 if (index < 0) {
3007 ast_log(LOG_WARNING, "No index in TDD?\n");
3008 return -1;
3010 fd = p->subs[index].dfd;
3011 while (len) {
3012 if (ast_check_hangup(chan))
3013 return -1;
3014 size = len;
3015 if (size > READ_SIZE)
3016 size = READ_SIZE;
3017 fds[0].fd = fd;
3018 fds[0].events = POLLPRI | POLLOUT;
3019 fds[0].revents = 0;
3020 res = poll(fds, 1, -1);
3021 if (!res) {
3022 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
3023 continue;
3025 /* if got exception */
3026 if (fds[0].revents & POLLPRI)
3027 return -1;
3028 if (!(fds[0].revents & POLLOUT)) {
3029 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
3030 continue;
3032 res = write(fd, buf, size);
3033 if (res != size) {
3034 if (res == -1) return -1;
3035 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
3036 break;
3038 len -= size;
3039 buf += size;
3041 p->didtdd = 1; /* set to have done it now */
3043 if (*cp == 2) { /* Mate mode */
3044 if (p->tdd)
3045 tdd_free(p->tdd);
3046 p->tdd = 0;
3047 p->mate = 1;
3048 break;
3050 if (!p->tdd) { /* if we dont have one yet */
3051 p->tdd = tdd_new(); /* allocate one */
3053 break;
3054 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
3055 if (!p->dsp)
3056 break;
3057 cp = (char *) data;
3058 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3059 *cp ? "ON" : "OFF", (int) *cp, chan->name);
3060 p->dtmfrelax = 0;
3061 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
3062 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
3063 break;
3064 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
3065 cp = (char *) data;
3066 if (!*cp) {
3067 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
3068 x = 0;
3069 dahdi_disable_ec(p);
3070 } else {
3071 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
3072 x = 1;
3074 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
3075 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
3076 break;
3077 case AST_OPTION_OPRMODE: /* Operator services mode */
3078 oprmode = (struct oprmode *) data;
3079 pp = oprmode->peer->tech_pvt;
3080 p->oprmode = pp->oprmode = 0;
3081 /* setup peers */
3082 p->oprpeer = pp;
3083 pp->oprpeer = p;
3084 /* setup modes, if any */
3085 if (oprmode->mode)
3087 pp->oprmode = oprmode->mode;
3088 p->oprmode = -oprmode->mode;
3090 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
3091 oprmode->mode, chan->name,oprmode->peer->name);;
3092 break;
3093 case AST_OPTION_ECHOCAN:
3094 cp = (char *) data;
3095 if (*cp) {
3096 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3097 dahdi_enable_ec(p);
3098 } else {
3099 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3100 dahdi_disable_ec(p);
3102 break;
3104 errno = 0;
3106 return 0;
3109 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3111 struct dahdi_pvt *p = chan->tech_pvt;
3113 if (!strcasecmp(data, "rxgain")) {
3114 ast_mutex_lock(&p->lock);
3115 snprintf(buf, len, "%f", p->rxgain);
3116 ast_mutex_unlock(&p->lock);
3117 } else if (!strcasecmp(data, "txgain")) {
3118 ast_mutex_lock(&p->lock);
3119 snprintf(buf, len, "%f", p->txgain);
3120 ast_mutex_unlock(&p->lock);
3121 } else {
3122 ast_copy_string(buf, "", len);
3124 return 0;
3128 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3130 /* Unlink a specific slave or all slaves/masters from a given master */
3131 int x;
3132 int hasslaves;
3133 if (!master)
3134 return;
3135 if (needlock) {
3136 ast_mutex_lock(&master->lock);
3137 if (slave) {
3138 while (ast_mutex_trylock(&slave->lock)) {
3139 DEADLOCK_AVOIDANCE(&master->lock);
3143 hasslaves = 0;
3144 for (x = 0; x < MAX_SLAVES; x++) {
3145 if (master->slaves[x]) {
3146 if (!slave || (master->slaves[x] == slave)) {
3147 /* Take slave out of the conference */
3148 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3149 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3150 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3151 master->slaves[x]->master = NULL;
3152 master->slaves[x] = NULL;
3153 } else
3154 hasslaves = 1;
3156 if (!hasslaves)
3157 master->inconference = 0;
3159 if (!slave) {
3160 if (master->master) {
3161 /* Take master out of the conference */
3162 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3163 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3164 hasslaves = 0;
3165 for (x = 0; x < MAX_SLAVES; x++) {
3166 if (master->master->slaves[x] == master)
3167 master->master->slaves[x] = NULL;
3168 else if (master->master->slaves[x])
3169 hasslaves = 1;
3171 if (!hasslaves)
3172 master->master->inconference = 0;
3174 master->master = NULL;
3176 update_conf(master);
3177 if (needlock) {
3178 if (slave)
3179 ast_mutex_unlock(&slave->lock);
3180 ast_mutex_unlock(&master->lock);
3184 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3185 int x;
3186 if (!slave || !master) {
3187 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3188 return;
3190 for (x = 0; x < MAX_SLAVES; x++) {
3191 if (!master->slaves[x]) {
3192 master->slaves[x] = slave;
3193 break;
3196 if (x >= MAX_SLAVES) {
3197 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3198 master->slaves[MAX_SLAVES - 1] = slave;
3200 if (slave->master)
3201 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3202 slave->master = master;
3204 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3207 static void disable_dtmf_detect(struct dahdi_pvt *p)
3209 #ifdef DAHDI_TONEDETECT
3210 int val;
3211 #endif
3213 p->ignoredtmf = 1;
3215 #ifdef DAHDI_TONEDETECT
3216 val = 0;
3217 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3218 #endif
3219 if (!p->hardwaredtmf && p->dsp) {
3220 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3221 ast_dsp_set_features(p->dsp, p->dsp_features);
3225 static void enable_dtmf_detect(struct dahdi_pvt *p)
3227 #ifdef DAHDI_TONEDETECT
3228 int val;
3229 #endif
3231 if (p->channel == CHAN_PSEUDO)
3232 return;
3234 p->ignoredtmf = 0;
3236 #ifdef DAHDI_TONEDETECT
3237 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3238 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3239 #endif
3240 if (!p->hardwaredtmf && p->dsp) {
3241 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3242 ast_dsp_set_features(p->dsp, p->dsp_features);
3246 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)
3248 struct ast_channel *who;
3249 struct dahdi_pvt *p0, *p1, *op0, *op1;
3250 struct dahdi_pvt *master = NULL, *slave = NULL;
3251 struct ast_frame *f;
3252 int inconf = 0;
3253 int nothingok = 1;
3254 int ofd0, ofd1;
3255 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3256 int os0 = -1, os1 = -1;
3257 int priority = 0;
3258 struct ast_channel *oc0, *oc1;
3259 enum ast_bridge_result res;
3261 #ifdef PRI_2BCT
3262 int triedtopribridge = 0;
3263 q931_call *q931c0 = NULL, *q931c1 = NULL;
3264 #endif
3266 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3267 There is code below to handle it properly until DTMF is actually seen,
3268 but due to currently unresolved issues it's ignored...
3271 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3272 return AST_BRIDGE_FAILED_NOWARN;
3274 ast_mutex_lock(&c0->lock);
3275 while (ast_mutex_trylock(&c1->lock)) {
3276 DEADLOCK_AVOIDANCE(&c0->lock);
3279 p0 = c0->tech_pvt;
3280 p1 = c1->tech_pvt;
3281 /* cant do pseudo-channels here */
3282 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3283 ast_mutex_unlock(&c0->lock);
3284 ast_mutex_unlock(&c1->lock);
3285 return AST_BRIDGE_FAILED_NOWARN;
3288 oi0 = dahdi_get_index(c0, p0, 0);
3289 oi1 = dahdi_get_index(c1, p1, 0);
3290 if ((oi0 < 0) || (oi1 < 0)) {
3291 ast_mutex_unlock(&c0->lock);
3292 ast_mutex_unlock(&c1->lock);
3293 return AST_BRIDGE_FAILED;
3296 op0 = p0 = c0->tech_pvt;
3297 op1 = p1 = c1->tech_pvt;
3298 ofd0 = c0->fds[0];
3299 ofd1 = c1->fds[0];
3300 oc0 = p0->owner;
3301 oc1 = p1->owner;
3303 if (ast_mutex_trylock(&p0->lock)) {
3304 /* Don't block, due to potential for deadlock */
3305 ast_mutex_unlock(&c0->lock);
3306 ast_mutex_unlock(&c1->lock);
3307 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3308 return AST_BRIDGE_RETRY;
3310 if (ast_mutex_trylock(&p1->lock)) {
3311 /* Don't block, due to potential for deadlock */
3312 ast_mutex_unlock(&p0->lock);
3313 ast_mutex_unlock(&c0->lock);
3314 ast_mutex_unlock(&c1->lock);
3315 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3316 return AST_BRIDGE_RETRY;
3319 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3320 if (p0->owner && p1->owner) {
3321 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3322 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3323 master = p0;
3324 slave = p1;
3325 inconf = 1;
3326 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3327 master = p1;
3328 slave = p0;
3329 inconf = 1;
3330 } else {
3331 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3332 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3333 p0->channel,
3334 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3335 p0->subs[SUB_REAL].inthreeway, p0->channel,
3336 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3337 p1->subs[SUB_REAL].inthreeway);
3339 nothingok = 0;
3341 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3342 if (p1->subs[SUB_THREEWAY].inthreeway) {
3343 master = p1;
3344 slave = p0;
3345 nothingok = 0;
3347 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3348 if (p0->subs[SUB_THREEWAY].inthreeway) {
3349 master = p0;
3350 slave = p1;
3351 nothingok = 0;
3353 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3354 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3355 don't put us in anything */
3356 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3357 master = p1;
3358 slave = p0;
3359 nothingok = 0;
3361 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3362 /* Same as previous */
3363 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3364 master = p0;
3365 slave = p1;
3366 nothingok = 0;
3369 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3370 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3371 if (master && slave) {
3372 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3373 in an active threeway call with a channel that is ringing, we should
3374 indicate ringing. */
3375 if ((oi1 == SUB_THREEWAY) &&
3376 p1->subs[SUB_THREEWAY].inthreeway &&
3377 p1->subs[SUB_REAL].owner &&
3378 p1->subs[SUB_REAL].inthreeway &&
3379 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3380 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3381 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3382 os1 = p1->subs[SUB_REAL].owner->_state;
3383 } else {
3384 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3385 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3387 if ((oi0 == SUB_THREEWAY) &&
3388 p0->subs[SUB_THREEWAY].inthreeway &&
3389 p0->subs[SUB_REAL].owner &&
3390 p0->subs[SUB_REAL].inthreeway &&
3391 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3392 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3393 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3394 os0 = p0->subs[SUB_REAL].owner->_state;
3395 } else {
3396 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3397 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3399 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3400 if (!p0->echocanbridged || !p1->echocanbridged) {
3401 /* Disable echo cancellation if appropriate */
3402 dahdi_disable_ec(p0);
3403 dahdi_disable_ec(p1);
3406 dahdi_link(slave, master);
3407 master->inconference = inconf;
3408 } else if (!nothingok)
3409 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3411 update_conf(p0);
3412 update_conf(p1);
3413 t0 = p0->subs[SUB_REAL].inthreeway;
3414 t1 = p1->subs[SUB_REAL].inthreeway;
3416 ast_mutex_unlock(&p0->lock);
3417 ast_mutex_unlock(&p1->lock);
3419 ast_mutex_unlock(&c0->lock);
3420 ast_mutex_unlock(&c1->lock);
3422 /* Native bridge failed */
3423 if ((!master || !slave) && !nothingok) {
3424 dahdi_enable_ec(p0);
3425 dahdi_enable_ec(p1);
3426 return AST_BRIDGE_FAILED;
3429 if (option_verbose > 2)
3430 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3432 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3433 disable_dtmf_detect(op0);
3435 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3436 disable_dtmf_detect(op1);
3438 for (;;) {
3439 struct ast_channel *c0_priority[2] = {c0, c1};
3440 struct ast_channel *c1_priority[2] = {c1, c0};
3442 /* Here's our main loop... Start by locking things, looking for private parts,
3443 and then balking if anything is wrong */
3444 ast_mutex_lock(&c0->lock);
3445 while (ast_mutex_trylock(&c1->lock)) {
3446 DEADLOCK_AVOIDANCE(&c0->lock);
3449 p0 = c0->tech_pvt;
3450 p1 = c1->tech_pvt;
3452 if (op0 == p0)
3453 i0 = dahdi_get_index(c0, p0, 1);
3454 if (op1 == p1)
3455 i1 = dahdi_get_index(c1, p1, 1);
3456 ast_mutex_unlock(&c0->lock);
3457 ast_mutex_unlock(&c1->lock);
3459 if (!timeoutms ||
3460 (op0 != p0) ||
3461 (op1 != p1) ||
3462 (ofd0 != c0->fds[0]) ||
3463 (ofd1 != c1->fds[0]) ||
3464 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3465 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3466 (oc0 != p0->owner) ||
3467 (oc1 != p1->owner) ||
3468 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3469 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3470 (oi0 != i0) ||
3471 (oi1 != i1)) {
3472 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3473 op0->channel, oi0, op1->channel, oi1);
3474 res = AST_BRIDGE_RETRY;
3475 goto return_from_bridge;
3478 #ifdef PRI_2BCT
3479 q931c0 = p0->call;
3480 q931c1 = p1->call;
3481 if (p0->transfer && p1->transfer
3482 && q931c0 && q931c1
3483 && !triedtopribridge) {
3484 pri_channel_bridge(q931c0, q931c1);
3485 triedtopribridge = 1;
3487 #endif
3489 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3490 if (!who) {
3491 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3492 continue;
3494 f = ast_read(who);
3495 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3496 *fo = f;
3497 *rc = who;
3498 res = AST_BRIDGE_COMPLETE;
3499 goto return_from_bridge;
3501 if (f->frametype == AST_FRAME_DTMF) {
3502 if ((who == c0) && p0->pulsedial) {
3503 ast_write(c1, f);
3504 } else if ((who == c1) && p1->pulsedial) {
3505 ast_write(c0, f);
3506 } else {
3507 *fo = f;
3508 *rc = who;
3509 res = AST_BRIDGE_COMPLETE;
3510 goto return_from_bridge;
3513 ast_frfree(f);
3515 /* Swap who gets priority */
3516 priority = !priority;
3519 return_from_bridge:
3520 if (op0 == p0)
3521 dahdi_enable_ec(p0);
3523 if (op1 == p1)
3524 dahdi_enable_ec(p1);
3526 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3527 enable_dtmf_detect(op0);
3529 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3530 enable_dtmf_detect(op1);
3532 dahdi_unlink(slave, master, 1);
3534 return res;
3537 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3539 struct dahdi_pvt *p = newchan->tech_pvt;
3540 int x;
3541 ast_mutex_lock(&p->lock);
3542 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3543 if (p->owner == oldchan) {
3544 p->owner = newchan;
3546 for (x = 0; x < 3; x++)
3547 if (p->subs[x].owner == oldchan) {
3548 if (!x)
3549 dahdi_unlink(NULL, p, 0);
3550 p->subs[x].owner = newchan;
3552 if (newchan->_state == AST_STATE_RINGING)
3553 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3554 update_conf(p);
3555 ast_mutex_unlock(&p->lock);
3556 return 0;
3559 static int dahdi_ring_phone(struct dahdi_pvt *p)
3561 int x;
3562 int res;
3563 /* Make sure our transmit state is on hook */
3564 x = 0;
3565 x = DAHDI_ONHOOK;
3566 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3567 do {
3568 x = DAHDI_RING;
3569 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3570 if (res) {
3571 switch (errno) {
3572 case EBUSY:
3573 case EINTR:
3574 /* Wait just in case */
3575 usleep(10000);
3576 continue;
3577 case EINPROGRESS:
3578 res = 0;
3579 break;
3580 default:
3581 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3582 res = 0;
3585 } while (res);
3586 return res;
3589 static void *ss_thread(void *data);
3591 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3593 static int attempt_transfer(struct dahdi_pvt *p)
3595 /* In order to transfer, we need at least one of the channels to
3596 actually be in a call bridge. We can't conference two applications
3597 together (but then, why would we want to?) */
3598 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3599 /* The three-way person we're about to transfer to could still be in MOH, so
3600 stop if now if appropriate */
3601 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3602 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3603 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3604 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3606 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3607 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3609 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3610 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3611 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3612 return -1;
3614 /* Orphan the channel after releasing the lock */
3615 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3616 unalloc_sub(p, SUB_THREEWAY);
3617 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3618 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3619 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3620 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3622 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3623 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3625 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3626 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3627 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3628 return -1;
3630 /* Three-way is now the REAL */
3631 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3632 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3633 unalloc_sub(p, SUB_THREEWAY);
3634 /* Tell the caller not to hangup */
3635 return 1;
3636 } else {
3637 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3638 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3639 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3640 return -1;
3642 return 0;
3645 static int check_for_conference(struct dahdi_pvt *p)
3647 struct dahdi_confinfo ci;
3648 /* Fine if we already have a master, etc */
3649 if (p->master || (p->confno > -1))
3650 return 0;
3651 memset(&ci, 0, sizeof(ci));
3652 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3653 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3654 return 0;
3656 /* If we have no master and don't have a confno, then
3657 if we're in a conference, it's probably a MeetMe room or
3658 some such, so don't let us 3-way out! */
3659 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3660 if (option_verbose > 2)
3661 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3662 return 1;
3664 return 0;
3667 static int get_alarms(struct dahdi_pvt *p)
3669 int res;
3670 struct dahdi_spaninfo zi;
3671 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3673 * The conditional compilation is needed only in asterisk-1.4 for
3674 * backward compatibility with old zaptel drivers that don't have
3675 * a DAHDI_PARAMS.chan_alarms field.
3677 struct dahdi_params params;
3678 #endif
3680 memset(&zi, 0, sizeof(zi));
3681 zi.spanno = p->span;
3683 /* First check for span alarms */
3684 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
3685 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3686 return 0;
3688 if (zi.alarms != DAHDI_ALARM_NONE)
3689 return zi.alarms;
3690 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3691 /* No alarms on the span. Check for channel alarms. */
3692 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
3693 return params.chan_alarms;
3694 /* ioctl failed */
3695 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
3696 #endif
3697 return DAHDI_ALARM_NONE;
3700 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3702 struct dahdi_pvt *p = ast->tech_pvt;
3703 struct ast_frame *f = *dest;
3705 if (option_debug)
3706 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3708 if (p->confirmanswer) {
3709 if (option_debug)
3710 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3711 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3712 of a DTMF digit */
3713 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3714 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3715 *dest = &p->subs[index].f;
3716 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3717 p->confirmanswer = 0;
3718 } else if (p->callwaitcas) {
3719 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3720 if (option_debug)
3721 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3722 if (p->cidspill)
3723 free(p->cidspill);
3724 send_cwcidspill(p);
3726 if ((f->subclass != 'm') && (f->subclass != 'u'))
3727 p->callwaitcas = 0;
3728 p->subs[index].f.frametype = AST_FRAME_NULL;
3729 p->subs[index].f.subclass = 0;
3730 *dest = &p->subs[index].f;
3731 } else if (f->subclass == 'f') {
3732 /* Fax tone -- Handle and return NULL */
3733 if ((p->callprogress & 0x6) && !p->faxhandled) {
3734 p->faxhandled++;
3735 if (strcmp(ast->exten, "fax")) {
3736 const char *target_context = S_OR(ast->macrocontext, ast->context);
3738 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3739 if (option_verbose > 2)
3740 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3741 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3742 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3743 if (ast_async_goto(ast, target_context, "fax", 1))
3744 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3745 } else
3746 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3747 } else if (option_debug)
3748 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3749 } else if (option_debug)
3750 ast_log(LOG_DEBUG, "Fax already handled\n");
3751 dahdi_confmute(p, 0);
3752 p->subs[index].f.frametype = AST_FRAME_NULL;
3753 p->subs[index].f.subclass = 0;
3754 *dest = &p->subs[index].f;
3755 } else if (f->subclass == 'm') {
3756 /* Confmute request */
3757 dahdi_confmute(p, 1);
3758 p->subs[index].f.frametype = AST_FRAME_NULL;
3759 p->subs[index].f.subclass = 0;
3760 *dest = &p->subs[index].f;
3761 } else if (f->subclass == 'u') {
3762 /* Unmute */
3763 dahdi_confmute(p, 0);
3764 p->subs[index].f.frametype = AST_FRAME_NULL;
3765 p->subs[index].f.subclass = 0;
3766 *dest = &p->subs[index].f;
3767 } else
3768 dahdi_confmute(p, 0);
3771 static void handle_alarms(struct dahdi_pvt *p, int alarms)
3773 const char *alarm_str = alarm2str(alarms);
3775 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3776 * doesn't know what to do with it. Don't confuse users with log messages. */
3777 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3778 p->unknown_alarm = 1;
3779 return;
3780 } else {
3781 p->unknown_alarm = 0;
3784 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3785 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3786 "Alarm: %s\r\n"
3787 "Channel: %d\r\n",
3788 alarm_str, p->channel);
3791 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
3793 int res, x;
3794 int index, mysig;
3795 char *c;
3796 struct dahdi_pvt *p = ast->tech_pvt;
3797 pthread_t threadid;
3798 pthread_attr_t attr;
3799 struct ast_channel *chan;
3800 struct ast_frame *f;
3802 index = dahdi_get_index(ast, p, 0);
3803 mysig = p->sig;
3804 if (p->outsigmod > -1)
3805 mysig = p->outsigmod;
3806 p->subs[index].f.frametype = AST_FRAME_NULL;
3807 p->subs[index].f.subclass = 0;
3808 p->subs[index].f.datalen = 0;
3809 p->subs[index].f.samples = 0;
3810 p->subs[index].f.mallocd = 0;
3811 p->subs[index].f.offset = 0;
3812 p->subs[index].f.src = "dahdi_handle_event";
3813 p->subs[index].f.data = NULL;
3814 f = &p->subs[index].f;
3816 if (index < 0)
3817 return &p->subs[index].f;
3818 if (p->fake_event) {
3819 res = p->fake_event;
3820 p->fake_event = 0;
3821 } else
3822 res = dahdi_get_event(p->subs[index].dfd);
3824 if (option_debug)
3825 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
3827 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
3828 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
3830 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
3831 #ifdef HAVE_PRI
3832 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
3833 /* absorb event */
3834 } else {
3835 #endif
3836 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
3837 p->subs[index].f.subclass = res & 0xff;
3838 #ifdef HAVE_PRI
3840 #endif
3841 dahdi_handle_dtmfup(ast, index, &f);
3842 return f;
3845 if (res & DAHDI_EVENT_DTMFDOWN) {
3846 if (option_debug)
3847 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
3848 /* Mute conference */
3849 dahdi_confmute(p, 1);
3850 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
3851 p->subs[index].f.subclass = res & 0xff;
3852 return &p->subs[index].f;
3855 switch (res) {
3856 #ifdef DAHDI_EVENT_EC_DISABLED
3857 case DAHDI_EVENT_EC_DISABLED:
3858 if (option_verbose > 2)
3859 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
3860 p->echocanon = 0;
3861 break;
3862 #endif
3863 case DAHDI_EVENT_BITSCHANGED:
3864 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
3865 case DAHDI_EVENT_PULSE_START:
3866 /* Stop tone if there's a pulse start and the PBX isn't started */
3867 if (!ast->pbx)
3868 tone_zone_play_tone(p->subs[index].dfd, -1);
3869 break;
3870 case DAHDI_EVENT_DIALCOMPLETE:
3871 if (p->inalarm) break;
3872 if ((p->radio || (p->oprmode < 0))) break;
3873 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
3874 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
3875 return NULL;
3877 if (!x) { /* if not still dialing in driver */
3878 dahdi_enable_ec(p);
3879 if (p->echobreak) {
3880 dahdi_train_ec(p);
3881 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
3882 p->dop.op = DAHDI_DIAL_OP_REPLACE;
3883 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
3884 p->echobreak = 0;
3885 } else {
3886 p->dialing = 0;
3887 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
3888 /* if thru with dialing after offhook */
3889 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
3890 ast_setstate(ast, AST_STATE_UP);
3891 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3892 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3893 break;
3894 } else { /* if to state wait for offhook to dial rest */
3895 /* we now wait for off hook */
3896 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
3899 if (ast->_state == AST_STATE_DIALING) {
3900 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
3901 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
3902 } 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)))) {
3903 ast_setstate(ast, AST_STATE_RINGING);
3904 } else if (!p->answeronpolarityswitch) {
3905 ast_setstate(ast, AST_STATE_UP);
3906 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3907 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3908 /* If aops=0 and hops=1, this is necessary */
3909 p->polarity = POLARITY_REV;
3910 } else {
3911 /* Start clean, so we can catch the change to REV polarity when party answers */
3912 p->polarity = POLARITY_IDLE;
3917 break;
3918 case DAHDI_EVENT_ALARM:
3919 #ifdef HAVE_PRI
3920 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
3921 /* T309 is not enabled : hangup calls when alarm occurs */
3922 if (p->call) {
3923 if (p->pri && p->pri->pri) {
3924 if (!pri_grab(p, p->pri)) {
3925 pri_hangup(p->pri->pri, p->call, -1);
3926 pri_destroycall(p->pri->pri, p->call);
3927 p->call = NULL;
3928 pri_rel(p->pri);
3929 } else
3930 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
3931 } else
3932 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
3934 if (p->owner)
3935 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
3937 if (p->bearer)
3938 p->bearer->inalarm = 1;
3939 else
3940 #endif
3941 p->inalarm = 1;
3942 res = get_alarms(p);
3943 handle_alarms(p, res);
3944 #ifdef HAVE_LIBPRI
3945 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
3946 /* fall through intentionally */
3947 } else {
3948 break;
3950 #endif
3951 case DAHDI_EVENT_ONHOOK:
3952 if (p->radio) {
3953 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3954 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
3955 break;
3957 if (p->oprmode < 0)
3959 if (p->oprmode != -1) break;
3960 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
3962 /* Make sure it starts ringing */
3963 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
3964 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
3965 save_conference(p->oprpeer);
3966 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3968 break;
3970 switch (p->sig) {
3971 case SIG_FXOLS:
3972 case SIG_FXOGS:
3973 case SIG_FXOKS:
3974 p->onhooktime = time(NULL);
3975 p->msgstate = -1;
3976 /* Check for some special conditions regarding call waiting */
3977 if (index == SUB_REAL) {
3978 /* The normal line was hung up */
3979 if (p->subs[SUB_CALLWAIT].owner) {
3980 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
3981 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
3982 if (option_verbose > 2)
3983 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
3984 unalloc_sub(p, SUB_CALLWAIT);
3985 #if 0
3986 p->subs[index].needanswer = 0;
3987 p->subs[index].needringing = 0;
3988 #endif
3989 p->callwaitingrepeat = 0;
3990 p->cidcwexpire = 0;
3991 p->owner = NULL;
3992 /* Don't start streaming audio yet if the incoming call isn't up yet */
3993 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
3994 p->dialing = 1;
3995 dahdi_ring_phone(p);
3996 } else if (p->subs[SUB_THREEWAY].owner) {
3997 unsigned int mssinceflash;
3998 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
3999 the private structure -- not especially easy or clean */
4000 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
4001 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4002 ast_mutex_unlock(&p->lock);
4003 DEADLOCK_AVOIDANCE(&ast->lock);
4004 /* We can grab ast and p in that order, without worry. We should make sure
4005 nothing seriously bad has happened though like some sort of bizarre double
4006 masquerade! */
4007 ast_mutex_lock(&p->lock);
4008 if (p->owner != ast) {
4009 ast_log(LOG_WARNING, "This isn't good...\n");
4010 return NULL;
4013 if (!p->subs[SUB_THREEWAY].owner) {
4014 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
4015 return NULL;
4017 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
4018 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
4019 if (mssinceflash < MIN_MS_SINCE_FLASH) {
4020 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4021 hanging up. Hangup both channels now */
4022 if (p->subs[SUB_THREEWAY].owner)
4023 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
4024 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4025 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
4026 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4027 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
4028 if (p->transfer) {
4029 /* In any case this isn't a threeway call anymore */
4030 p->subs[SUB_REAL].inthreeway = 0;
4031 p->subs[SUB_THREEWAY].inthreeway = 0;
4032 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4033 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
4034 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4035 /* Swap subs and dis-own channel */
4036 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4037 p->owner = NULL;
4038 /* Ring the phone */
4039 dahdi_ring_phone(p);
4040 } else {
4041 if ((res = attempt_transfer(p)) < 0) {
4042 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4043 if (p->subs[SUB_THREEWAY].owner)
4044 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4045 } else if (res) {
4046 /* Don't actually hang up at this point */
4047 if (p->subs[SUB_THREEWAY].owner)
4048 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4049 break;
4052 } else {
4053 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4054 if (p->subs[SUB_THREEWAY].owner)
4055 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4057 } else {
4058 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4059 /* Swap subs and dis-own channel */
4060 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4061 p->owner = NULL;
4062 /* Ring the phone */
4063 dahdi_ring_phone(p);
4066 } else {
4067 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
4069 /* Fall through */
4070 default:
4071 dahdi_disable_ec(p);
4072 return NULL;
4074 break;
4075 case DAHDI_EVENT_RINGOFFHOOK:
4076 if (p->inalarm) break;
4077 if (p->oprmode < 0)
4079 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4081 /* Make sure it stops ringing */
4082 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4083 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
4084 restore_conference(p->oprpeer);
4086 break;
4088 if (p->radio)
4090 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4091 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4092 break;
4094 /* for E911, its supposed to wait for offhook then dial
4095 the second half of the dial string */
4096 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
4097 c = strchr(p->dialdest, '/');
4098 if (c)
4099 c++;
4100 else
4101 c = p->dialdest;
4102 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
4103 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
4104 if (strlen(p->dop.dialstr) > 4) {
4105 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
4106 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
4107 p->echorest[sizeof(p->echorest) - 1] = '\0';
4108 p->echobreak = 1;
4109 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
4110 } else
4111 p->echobreak = 0;
4112 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
4113 int saveerr = errno;
4115 x = DAHDI_ONHOOK;
4116 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4117 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4118 return NULL;
4120 p->dialing = 1;
4121 return &p->subs[index].f;
4123 switch (p->sig) {
4124 case SIG_FXOLS:
4125 case SIG_FXOGS:
4126 case SIG_FXOKS:
4127 switch (ast->_state) {
4128 case AST_STATE_RINGING:
4129 dahdi_enable_ec(p);
4130 dahdi_train_ec(p);
4131 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4132 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4133 /* Make sure it stops ringing */
4134 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4135 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4136 if (p->cidspill) {
4137 /* Cancel any running CallerID spill */
4138 free(p->cidspill);
4139 p->cidspill = NULL;
4141 p->dialing = 0;
4142 p->callwaitcas = 0;
4143 if (p->confirmanswer) {
4144 /* Ignore answer if "confirm answer" is enabled */
4145 p->subs[index].f.frametype = AST_FRAME_NULL;
4146 p->subs[index].f.subclass = 0;
4147 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4148 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4149 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4150 if (res < 0) {
4151 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4152 p->dop.dialstr[0] = '\0';
4153 return NULL;
4154 } else {
4155 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4156 p->subs[index].f.frametype = AST_FRAME_NULL;
4157 p->subs[index].f.subclass = 0;
4158 p->dialing = 1;
4160 p->dop.dialstr[0] = '\0';
4161 ast_setstate(ast, AST_STATE_DIALING);
4162 } else
4163 ast_setstate(ast, AST_STATE_UP);
4164 return &p->subs[index].f;
4165 case AST_STATE_DOWN:
4166 ast_setstate(ast, AST_STATE_RING);
4167 ast->rings = 1;
4168 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4169 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4170 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4171 return &p->subs[index].f;
4172 case AST_STATE_UP:
4173 /* Make sure it stops ringing */
4174 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4175 /* Okay -- probably call waiting*/
4176 if (ast_bridged_channel(p->owner))
4177 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4178 p->subs[index].needunhold = 1;
4179 break;
4180 case AST_STATE_RESERVED:
4181 /* Start up dialtone */
4182 if (has_voicemail(p))
4183 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4184 else
4185 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4186 break;
4187 default:
4188 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4190 break;
4191 case SIG_FXSLS:
4192 case SIG_FXSGS:
4193 case SIG_FXSKS:
4194 if (ast->_state == AST_STATE_RING) {
4195 p->ringt = p->ringt_base;
4198 /* Fall through */
4199 case SIG_EM:
4200 case SIG_EM_E1:
4201 case SIG_EMWINK:
4202 case SIG_FEATD:
4203 case SIG_FEATDMF:
4204 case SIG_FEATDMF_TA:
4205 case SIG_E911:
4206 case SIG_FGC_CAMA:
4207 case SIG_FGC_CAMAMF:
4208 case SIG_FEATB:
4209 case SIG_SF:
4210 case SIG_SFWINK:
4211 case SIG_SF_FEATD:
4212 case SIG_SF_FEATDMF:
4213 case SIG_SF_FEATB:
4214 if (ast->_state == AST_STATE_PRERING)
4215 ast_setstate(ast, AST_STATE_RING);
4216 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4217 if (option_debug)
4218 ast_log(LOG_DEBUG, "Ring detected\n");
4219 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4220 p->subs[index].f.subclass = AST_CONTROL_RING;
4221 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4222 if (option_debug)
4223 ast_log(LOG_DEBUG, "Line answered\n");
4224 if (p->confirmanswer) {
4225 p->subs[index].f.frametype = AST_FRAME_NULL;
4226 p->subs[index].f.subclass = 0;
4227 } else {
4228 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4229 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4230 ast_setstate(ast, AST_STATE_UP);
4232 } else if (ast->_state != AST_STATE_RING)
4233 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4234 break;
4235 default:
4236 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4238 break;
4239 #ifdef DAHDI_EVENT_RINGBEGIN
4240 case DAHDI_EVENT_RINGBEGIN:
4241 switch (p->sig) {
4242 case SIG_FXSLS:
4243 case SIG_FXSGS:
4244 case SIG_FXSKS:
4245 if (ast->_state == AST_STATE_RING) {
4246 p->ringt = p->ringt_base;
4248 break;
4250 break;
4251 #endif
4252 case DAHDI_EVENT_RINGEROFF:
4253 if (p->inalarm) break;
4254 if ((p->radio || (p->oprmode < 0))) break;
4255 ast->rings++;
4256 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4257 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4258 free(p->cidspill);
4259 p->cidspill = NULL;
4260 p->callwaitcas = 0;
4262 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4263 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4264 break;
4265 case DAHDI_EVENT_RINGERON:
4266 break;
4267 case DAHDI_EVENT_NOALARM:
4268 p->inalarm = 0;
4269 #ifdef HAVE_PRI
4270 /* Extremely unlikely but just in case */
4271 if (p->bearer)
4272 p->bearer->inalarm = 0;
4273 #endif
4274 if (!p->unknown_alarm) {
4275 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4276 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4277 "Channel: %d\r\n", p->channel);
4278 } else {
4279 p->unknown_alarm = 0;
4281 break;
4282 case DAHDI_EVENT_WINKFLASH:
4283 if (p->inalarm) break;
4284 if (p->radio) break;
4285 if (p->oprmode < 0) break;
4286 if (p->oprmode > 1)
4288 struct dahdi_params par;
4290 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4292 if (!par.rxisoffhook)
4294 /* Make sure it stops ringing */
4295 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4296 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4297 save_conference(p);
4298 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4301 break;
4303 /* Remember last time we got a flash-hook */
4304 gettimeofday(&p->flashtime, NULL);
4305 switch (mysig) {
4306 case SIG_FXOLS:
4307 case SIG_FXOGS:
4308 case SIG_FXOKS:
4309 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4310 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4311 p->callwaitcas = 0;
4313 if (index != SUB_REAL) {
4314 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4315 goto winkflashdone;
4318 if (p->subs[SUB_CALLWAIT].owner) {
4319 /* Swap to call-wait */
4320 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4321 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4322 p->owner = p->subs[SUB_REAL].owner;
4323 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4324 if (p->owner->_state == AST_STATE_RINGING) {
4325 ast_setstate(p->owner, AST_STATE_UP);
4326 p->subs[SUB_REAL].needanswer = 1;
4328 p->callwaitingrepeat = 0;
4329 p->cidcwexpire = 0;
4330 /* Start music on hold if appropriate */
4331 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4332 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4333 S_OR(p->mohsuggest, NULL),
4334 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4336 p->subs[SUB_CALLWAIT].needhold = 1;
4337 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4338 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4339 S_OR(p->mohsuggest, NULL),
4340 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4342 p->subs[SUB_REAL].needunhold = 1;
4343 } else if (!p->subs[SUB_THREEWAY].owner) {
4344 char cid_num[256];
4345 char cid_name[256];
4347 if (!p->threewaycalling) {
4348 /* Just send a flash if no 3-way calling */
4349 p->subs[SUB_REAL].needflash = 1;
4350 goto winkflashdone;
4351 } else if (!check_for_conference(p)) {
4352 if (p->dahditrcallerid && p->owner) {
4353 if (p->owner->cid.cid_num)
4354 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4355 if (p->owner->cid.cid_name)
4356 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4358 /* XXX This section needs much more error checking!!! XXX */
4359 /* Start a 3-way call if feasible */
4360 if (!((ast->pbx) ||
4361 (ast->_state == AST_STATE_UP) ||
4362 (ast->_state == AST_STATE_RING))) {
4363 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4364 goto winkflashdone;
4366 if (alloc_sub(p, SUB_THREEWAY)) {
4367 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4368 goto winkflashdone;
4370 /* Make new channel */
4371 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4372 if (p->dahditrcallerid) {
4373 if (!p->origcid_num)
4374 p->origcid_num = ast_strdup(p->cid_num);
4375 if (!p->origcid_name)
4376 p->origcid_name = ast_strdup(p->cid_name);
4377 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4378 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4380 /* Swap things around between the three-way and real call */
4381 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4382 /* Disable echo canceller for better dialing */
4383 dahdi_disable_ec(p);
4384 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4385 if (res)
4386 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4387 p->owner = chan;
4388 pthread_attr_init(&attr);
4389 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4390 if (!chan) {
4391 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4392 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4393 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4394 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4395 dahdi_enable_ec(p);
4396 ast_hangup(chan);
4397 } else {
4398 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4399 int way3bridge = 0, cdr3way = 0;
4401 if (!other) {
4402 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4403 } else
4404 way3bridge = 1;
4406 if (p->subs[SUB_THREEWAY].owner->cdr)
4407 cdr3way = 1;
4409 if (option_verbose > 2)
4410 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4411 /* Start music on hold if appropriate */
4412 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4413 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4414 S_OR(p->mohsuggest, NULL),
4415 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4417 p->subs[SUB_THREEWAY].needhold = 1;
4419 pthread_attr_destroy(&attr);
4421 } else {
4422 /* Already have a 3 way call */
4423 if (p->subs[SUB_THREEWAY].inthreeway) {
4424 /* Call is already up, drop the last person */
4425 if (option_debug)
4426 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4427 /* If the primary call isn't answered yet, use it */
4428 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4429 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4430 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4431 p->owner = p->subs[SUB_REAL].owner;
4433 /* Drop the last call and stop the conference */
4434 if (option_verbose > 2)
4435 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4436 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4437 p->subs[SUB_REAL].inthreeway = 0;
4438 p->subs[SUB_THREEWAY].inthreeway = 0;
4439 } else {
4440 /* Lets see what we're up to */
4441 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4442 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4443 int otherindex = SUB_THREEWAY;
4444 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4445 int way3bridge = 0, cdr3way = 0;
4447 if (!other) {
4448 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4449 } else
4450 way3bridge = 1;
4452 if (p->subs[SUB_THREEWAY].owner->cdr)
4453 cdr3way = 1;
4455 if (option_verbose > 2)
4456 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);
4457 /* Put them in the threeway, and flip */
4458 p->subs[SUB_THREEWAY].inthreeway = 1;
4459 p->subs[SUB_REAL].inthreeway = 1;
4460 if (ast->_state == AST_STATE_UP) {
4461 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4462 otherindex = SUB_REAL;
4464 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4465 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4466 p->subs[otherindex].needunhold = 1;
4467 p->owner = p->subs[SUB_REAL].owner;
4468 if (ast->_state == AST_STATE_RINGING) {
4469 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4470 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4471 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4473 } else {
4474 if (option_verbose > 2)
4475 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4476 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4477 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4478 p->owner = p->subs[SUB_REAL].owner;
4479 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4480 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4481 p->subs[SUB_REAL].needunhold = 1;
4482 dahdi_enable_ec(p);
4487 winkflashdone:
4488 update_conf(p);
4489 break;
4490 case SIG_EM:
4491 case SIG_EM_E1:
4492 case SIG_EMWINK:
4493 case SIG_FEATD:
4494 case SIG_SF:
4495 case SIG_SFWINK:
4496 case SIG_SF_FEATD:
4497 case SIG_FXSLS:
4498 case SIG_FXSGS:
4499 if (p->dialing)
4500 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4501 else
4502 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4503 break;
4504 case SIG_FEATDMF_TA:
4505 switch (p->whichwink) {
4506 case 0:
4507 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4508 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4509 break;
4510 case 1:
4511 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4512 break;
4513 case 2:
4514 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4515 return NULL;
4517 p->whichwink++;
4518 /* Fall through */
4519 case SIG_FEATDMF:
4520 case SIG_E911:
4521 case SIG_FGC_CAMAMF:
4522 case SIG_FGC_CAMA:
4523 case SIG_FEATB:
4524 case SIG_SF_FEATDMF:
4525 case SIG_SF_FEATB:
4526 /* FGD MF *Must* wait for wink */
4527 if (!ast_strlen_zero(p->dop.dialstr)) {
4528 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4529 if (res < 0) {
4530 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4531 p->dop.dialstr[0] = '\0';
4532 return NULL;
4533 } else
4534 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4536 p->dop.dialstr[0] = '\0';
4537 break;
4538 default:
4539 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4541 break;
4542 case DAHDI_EVENT_HOOKCOMPLETE:
4543 if (p->inalarm) break;
4544 if ((p->radio || (p->oprmode < 0))) break;
4545 switch (mysig) {
4546 case SIG_FXSLS: /* only interesting for FXS */
4547 case SIG_FXSGS:
4548 case SIG_FXSKS:
4549 case SIG_EM:
4550 case SIG_EM_E1:
4551 case SIG_EMWINK:
4552 case SIG_FEATD:
4553 case SIG_SF:
4554 case SIG_SFWINK:
4555 case SIG_SF_FEATD:
4556 if (!ast_strlen_zero(p->dop.dialstr)) {
4557 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4558 if (res < 0) {
4559 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4560 p->dop.dialstr[0] = '\0';
4561 return NULL;
4562 } else
4563 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4565 p->dop.dialstr[0] = '\0';
4566 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4567 break;
4568 case SIG_FEATDMF:
4569 case SIG_FEATDMF_TA:
4570 case SIG_E911:
4571 case SIG_FGC_CAMA:
4572 case SIG_FGC_CAMAMF:
4573 case SIG_FEATB:
4574 case SIG_SF_FEATDMF:
4575 case SIG_SF_FEATB:
4576 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4577 break;
4578 default:
4579 break;
4581 break;
4582 case DAHDI_EVENT_POLARITY:
4584 * If we get a Polarity Switch event, check to see
4585 * if we should change the polarity state and
4586 * mark the channel as UP or if this is an indication
4587 * of remote end disconnect.
4589 if (p->polarity == POLARITY_IDLE) {
4590 p->polarity = POLARITY_REV;
4591 if (p->answeronpolarityswitch &&
4592 ((ast->_state == AST_STATE_DIALING) ||
4593 (ast->_state == AST_STATE_RINGING))) {
4594 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4595 ast_setstate(p->owner, AST_STATE_UP);
4596 if (p->hanguponpolarityswitch) {
4597 gettimeofday(&p->polaritydelaytv, NULL);
4599 } else
4600 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4602 /* Removed else statement from here as it was preventing hangups from ever happening*/
4603 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4604 if (p->hanguponpolarityswitch &&
4605 (p->polarityonanswerdelay > 0) &&
4606 (p->polarity == POLARITY_REV) &&
4607 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4608 /* Added log_debug information below to provide a better indication of what is going on */
4609 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) );
4611 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4612 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4613 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4614 p->polarity = POLARITY_IDLE;
4615 } else {
4616 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);
4618 } else {
4619 p->polarity = POLARITY_IDLE;
4620 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4622 /* Added more log_debug information below to provide a better indication of what is going on */
4623 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) );
4624 break;
4625 default:
4626 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4628 return &p->subs[index].f;
4631 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4633 struct dahdi_pvt *p = ast->tech_pvt;
4634 int res;
4635 int usedindex=-1;
4636 int index;
4637 struct ast_frame *f;
4640 index = dahdi_get_index(ast, p, 1);
4642 p->subs[index].f.frametype = AST_FRAME_NULL;
4643 p->subs[index].f.datalen = 0;
4644 p->subs[index].f.samples = 0;
4645 p->subs[index].f.mallocd = 0;
4646 p->subs[index].f.offset = 0;
4647 p->subs[index].f.subclass = 0;
4648 p->subs[index].f.delivery = ast_tv(0,0);
4649 p->subs[index].f.src = "dahdi_exception";
4650 p->subs[index].f.data = NULL;
4653 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4654 /* If nobody owns us, absorb the event appropriately, otherwise
4655 we loop indefinitely. This occurs when, during call waiting, the
4656 other end hangs up our channel so that it no longer exists, but we
4657 have neither FLASH'd nor ONHOOK'd to signify our desire to
4658 change to the other channel. */
4659 if (p->fake_event) {
4660 res = p->fake_event;
4661 p->fake_event = 0;
4662 } else
4663 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4664 /* Switch to real if there is one and this isn't something really silly... */
4665 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4666 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4667 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4668 p->owner = p->subs[SUB_REAL].owner;
4669 if (p->owner && ast_bridged_channel(p->owner))
4670 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4671 p->subs[SUB_REAL].needunhold = 1;
4673 switch (res) {
4674 case DAHDI_EVENT_ONHOOK:
4675 dahdi_disable_ec(p);
4676 if (p->owner) {
4677 if (option_verbose > 2)
4678 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4679 dahdi_ring_phone(p);
4680 p->callwaitingrepeat = 0;
4681 p->cidcwexpire = 0;
4682 } else
4683 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4684 update_conf(p);
4685 break;
4686 case DAHDI_EVENT_RINGOFFHOOK:
4687 dahdi_enable_ec(p);
4688 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4689 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4690 p->subs[SUB_REAL].needanswer = 1;
4691 p->dialing = 0;
4693 break;
4694 case DAHDI_EVENT_HOOKCOMPLETE:
4695 case DAHDI_EVENT_RINGERON:
4696 case DAHDI_EVENT_RINGEROFF:
4697 /* Do nothing */
4698 break;
4699 case DAHDI_EVENT_WINKFLASH:
4700 gettimeofday(&p->flashtime, NULL);
4701 if (p->owner) {
4702 if (option_verbose > 2)
4703 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4704 if (p->owner->_state != AST_STATE_UP) {
4705 /* Answer if necessary */
4706 usedindex = dahdi_get_index(p->owner, p, 0);
4707 if (usedindex > -1) {
4708 p->subs[usedindex].needanswer = 1;
4710 ast_setstate(p->owner, AST_STATE_UP);
4712 p->callwaitingrepeat = 0;
4713 p->cidcwexpire = 0;
4714 if (ast_bridged_channel(p->owner))
4715 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4716 p->subs[SUB_REAL].needunhold = 1;
4717 } else
4718 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4719 update_conf(p);
4720 break;
4721 default:
4722 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4724 f = &p->subs[index].f;
4725 return f;
4727 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4728 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4729 /* If it's not us, return NULL immediately */
4730 if (ast != p->owner) {
4731 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4732 f = &p->subs[index].f;
4733 return f;
4735 f = dahdi_handle_event(ast);
4736 return f;
4739 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4741 struct dahdi_pvt *p = ast->tech_pvt;
4742 struct ast_frame *f;
4743 ast_mutex_lock(&p->lock);
4744 f = __dahdi_exception(ast);
4745 ast_mutex_unlock(&p->lock);
4746 return f;
4749 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4751 struct dahdi_pvt *p = ast->tech_pvt;
4752 int res;
4753 int index;
4754 void *readbuf;
4755 struct ast_frame *f;
4757 while (ast_mutex_trylock(&p->lock)) {
4758 DEADLOCK_AVOIDANCE(&ast->lock);
4761 index = dahdi_get_index(ast, p, 0);
4763 /* Hang up if we don't really exist */
4764 if (index < 0) {
4765 ast_log(LOG_WARNING, "We dont exist?\n");
4766 ast_mutex_unlock(&p->lock);
4767 return NULL;
4770 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4772 p->subs[index].f.frametype = AST_FRAME_NULL;
4773 p->subs[index].f.datalen = 0;
4774 p->subs[index].f.samples = 0;
4775 p->subs[index].f.mallocd = 0;
4776 p->subs[index].f.offset = 0;
4777 p->subs[index].f.subclass = 0;
4778 p->subs[index].f.delivery = ast_tv(0,0);
4779 p->subs[index].f.src = "dahdi_read";
4780 p->subs[index].f.data = NULL;
4782 /* make sure it sends initial key state as first frame */
4783 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4785 struct dahdi_params ps;
4787 ps.channo = p->channel;
4788 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4789 ast_mutex_unlock(&p->lock);
4790 return NULL;
4792 p->firstradio = 1;
4793 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4794 if (ps.rxisoffhook)
4796 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4798 else
4800 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4802 ast_mutex_unlock(&p->lock);
4803 return &p->subs[index].f;
4805 if (p->ringt == 1) {
4806 ast_mutex_unlock(&p->lock);
4807 return NULL;
4809 else if (p->ringt > 0)
4810 p->ringt--;
4812 if (p->subs[index].needringing) {
4813 /* Send ringing frame if requested */
4814 p->subs[index].needringing = 0;
4815 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4816 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4817 ast_setstate(ast, AST_STATE_RINGING);
4818 ast_mutex_unlock(&p->lock);
4819 return &p->subs[index].f;
4822 if (p->subs[index].needbusy) {
4823 /* Send busy frame if requested */
4824 p->subs[index].needbusy = 0;
4825 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4826 p->subs[index].f.subclass = AST_CONTROL_BUSY;
4827 ast_mutex_unlock(&p->lock);
4828 return &p->subs[index].f;
4831 if (p->subs[index].needcongestion) {
4832 /* Send congestion frame if requested */
4833 p->subs[index].needcongestion = 0;
4834 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4835 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
4836 ast_mutex_unlock(&p->lock);
4837 return &p->subs[index].f;
4840 if (p->subs[index].needcallerid) {
4841 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
4842 S_OR(p->lastcid_name, NULL),
4843 S_OR(p->lastcid_num, NULL)
4845 p->subs[index].needcallerid = 0;
4848 if (p->subs[index].needanswer) {
4849 /* Send answer frame if requested */
4850 p->subs[index].needanswer = 0;
4851 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4852 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4853 ast_mutex_unlock(&p->lock);
4854 return &p->subs[index].f;
4857 if (p->subs[index].needflash) {
4858 /* Send answer frame if requested */
4859 p->subs[index].needflash = 0;
4860 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4861 p->subs[index].f.subclass = AST_CONTROL_FLASH;
4862 ast_mutex_unlock(&p->lock);
4863 return &p->subs[index].f;
4866 if (p->subs[index].needhold) {
4867 /* Send answer frame if requested */
4868 p->subs[index].needhold = 0;
4869 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4870 p->subs[index].f.subclass = AST_CONTROL_HOLD;
4871 ast_mutex_unlock(&p->lock);
4872 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
4873 return &p->subs[index].f;
4876 if (p->subs[index].needunhold) {
4877 /* Send answer frame if requested */
4878 p->subs[index].needunhold = 0;
4879 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4880 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
4881 ast_mutex_unlock(&p->lock);
4882 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
4883 return &p->subs[index].f;
4886 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
4887 if (!p->subs[index].linear) {
4888 p->subs[index].linear = 1;
4889 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4890 if (res)
4891 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
4893 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
4894 (ast->rawreadformat == AST_FORMAT_ALAW)) {
4895 if (p->subs[index].linear) {
4896 p->subs[index].linear = 0;
4897 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
4898 if (res)
4899 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
4901 } else {
4902 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
4903 ast_mutex_unlock(&p->lock);
4904 return NULL;
4906 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
4907 CHECK_BLOCKING(ast);
4908 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4909 ast_clear_flag(ast, AST_FLAG_BLOCKING);
4910 /* Check for hangup */
4911 if (res < 0) {
4912 f = NULL;
4913 if (res == -1) {
4914 if (errno == EAGAIN) {
4915 /* Return "NULL" frame if there is nobody there */
4916 ast_mutex_unlock(&p->lock);
4917 return &p->subs[index].f;
4918 } else if (errno == ELAST) {
4919 f = __dahdi_exception(ast);
4920 } else
4921 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
4923 ast_mutex_unlock(&p->lock);
4924 return f;
4926 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
4927 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
4928 f = __dahdi_exception(ast);
4929 ast_mutex_unlock(&p->lock);
4930 return f;
4932 if (p->tdd) { /* if in TDD mode, see if we receive that */
4933 int c;
4935 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
4936 if (c < 0) {
4937 ast_log(LOG_DEBUG,"tdd_feed failed\n");
4938 ast_mutex_unlock(&p->lock);
4939 return NULL;
4941 if (c) { /* if a char to return */
4942 p->subs[index].f.subclass = 0;
4943 p->subs[index].f.frametype = AST_FRAME_TEXT;
4944 p->subs[index].f.mallocd = 0;
4945 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4946 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
4947 p->subs[index].f.datalen = 1;
4948 *((char *) p->subs[index].f.data) = c;
4949 ast_mutex_unlock(&p->lock);
4950 return &p->subs[index].f;
4953 /* Ensure the CW timer decrements only on a single subchannel */
4954 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
4955 p->callwaitingrepeat--;
4957 if (p->cidcwexpire)
4958 p->cidcwexpire--;
4959 /* Repeat callwaiting */
4960 if (p->callwaitingrepeat == 1) {
4961 p->callwaitrings++;
4962 dahdi_callwait(ast);
4964 /* Expire CID/CW */
4965 if (p->cidcwexpire == 1) {
4966 if (option_verbose > 2)
4967 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
4968 restore_conference(p);
4970 if (p->subs[index].linear) {
4971 p->subs[index].f.datalen = READ_SIZE * 2;
4972 } else
4973 p->subs[index].f.datalen = READ_SIZE;
4975 /* Handle CallerID Transmission */
4976 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
4977 send_callerid(p);
4980 p->subs[index].f.frametype = AST_FRAME_VOICE;
4981 p->subs[index].f.subclass = ast->rawreadformat;
4982 p->subs[index].f.samples = READ_SIZE;
4983 p->subs[index].f.mallocd = 0;
4984 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
4985 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
4986 #if 0
4987 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
4988 #endif
4989 if (p->dialing || /* Transmitting something */
4990 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
4991 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
4993 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
4994 don't send anything */
4995 p->subs[index].f.frametype = AST_FRAME_NULL;
4996 p->subs[index].f.subclass = 0;
4997 p->subs[index].f.samples = 0;
4998 p->subs[index].f.mallocd = 0;
4999 p->subs[index].f.offset = 0;
5000 p->subs[index].f.data = NULL;
5001 p->subs[index].f.datalen= 0;
5003 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
5004 /* Perform busy detection. etc on the dahdi line */
5005 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
5006 if (f) {
5007 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
5008 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
5009 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5010 a busy */
5011 f = NULL;
5013 } else if (f->frametype == AST_FRAME_DTMF) {
5014 #ifdef HAVE_PRI
5015 if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
5016 /* Don't accept in-band DTMF when in overlap dial mode */
5017 f->frametype = AST_FRAME_NULL;
5018 f->subclass = 0;
5020 #endif
5021 /* DSP clears us of being pulse */
5022 p->pulsedial = 0;
5025 } else
5026 f = &p->subs[index].f;
5028 if (f && (f->frametype == AST_FRAME_DTMF))
5029 dahdi_handle_dtmfup(ast, index, &f);
5031 /* If we have a fake_event, trigger exception to handle it */
5032 if (p->fake_event)
5033 ast_set_flag(ast, AST_FLAG_EXCEPTION);
5035 ast_mutex_unlock(&p->lock);
5036 return f;
5039 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
5041 int sent=0;
5042 int size;
5043 int res;
5044 int fd;
5045 fd = p->subs[index].dfd;
5046 while (len) {
5047 size = len;
5048 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
5049 size = (linear ? READ_SIZE * 2 : READ_SIZE);
5050 res = write(fd, buf, size);
5051 if (res != size) {
5052 if (option_debug)
5053 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
5054 return sent;
5056 len -= size;
5057 buf += size;
5059 return sent;
5062 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
5064 struct dahdi_pvt *p = ast->tech_pvt;
5065 int res;
5066 int index;
5067 index = dahdi_get_index(ast, p, 0);
5068 if (index < 0) {
5069 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
5070 return -1;
5073 #if 0
5074 #ifdef HAVE_PRI
5075 ast_mutex_lock(&p->lock);
5076 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5077 if (p->pri->pri) {
5078 if (!pri_grab(p, p->pri)) {
5079 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5080 pri_rel(p->pri);
5081 } else
5082 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5084 p->proceeding=1;
5086 ast_mutex_unlock(&p->lock);
5087 #endif
5088 #endif
5089 /* Write a frame of (presumably voice) data */
5090 if (frame->frametype != AST_FRAME_VOICE) {
5091 if (frame->frametype != AST_FRAME_IMAGE)
5092 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
5093 return 0;
5095 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
5096 (frame->subclass != AST_FORMAT_ULAW) &&
5097 (frame->subclass != AST_FORMAT_ALAW)) {
5098 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
5099 return -1;
5101 if (p->dialing) {
5102 if (option_debug)
5103 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
5104 return 0;
5106 if (!p->owner) {
5107 if (option_debug)
5108 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
5109 return 0;
5111 if (p->cidspill) {
5112 if (option_debug)
5113 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5114 return 0;
5116 /* Return if it's not valid data */
5117 if (!frame->data || !frame->datalen)
5118 return 0;
5120 if (frame->subclass == AST_FORMAT_SLINEAR) {
5121 if (!p->subs[index].linear) {
5122 p->subs[index].linear = 1;
5123 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5124 if (res)
5125 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5127 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5128 } else {
5129 /* x-law already */
5130 if (p->subs[index].linear) {
5131 p->subs[index].linear = 0;
5132 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5133 if (res)
5134 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5136 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5138 if (res < 0) {
5139 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5140 return -1;
5142 return 0;
5145 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5147 struct dahdi_pvt *p = chan->tech_pvt;
5148 int res=-1;
5149 int index;
5150 int func = DAHDI_FLASH;
5151 ast_mutex_lock(&p->lock);
5152 index = dahdi_get_index(chan, p, 0);
5153 if (option_debug)
5154 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5155 if (index == SUB_REAL) {
5156 switch (condition) {
5157 case AST_CONTROL_BUSY:
5158 #ifdef HAVE_PRI
5159 if (p->priindication_oob && p->sig == SIG_PRI) {
5160 chan->hangupcause = AST_CAUSE_USER_BUSY;
5161 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5162 res = 0;
5163 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5164 if (p->pri->pri) {
5165 if (!pri_grab(p, p->pri)) {
5166 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5167 pri_rel(p->pri);
5169 else
5170 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5172 p->progress = 1;
5173 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5174 } else
5175 #endif
5176 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5177 break;
5178 case AST_CONTROL_RINGING:
5179 #ifdef HAVE_PRI
5180 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5181 if (p->pri->pri) {
5182 if (!pri_grab(p, p->pri)) {
5183 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5184 pri_rel(p->pri);
5186 else
5187 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5189 p->alerting = 1;
5191 #endif
5192 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5193 if (chan->_state != AST_STATE_UP) {
5194 if ((chan->_state != AST_STATE_RING) ||
5195 ((p->sig != SIG_FXSKS) &&
5196 (p->sig != SIG_FXSLS) &&
5197 (p->sig != SIG_FXSGS)))
5198 ast_setstate(chan, AST_STATE_RINGING);
5200 break;
5201 case AST_CONTROL_PROCEEDING:
5202 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5203 #ifdef HAVE_PRI
5204 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5205 if (p->pri->pri) {
5206 if (!pri_grab(p, p->pri)) {
5207 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5208 pri_rel(p->pri);
5210 else
5211 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5213 p->proceeding = 1;
5215 #endif
5216 /* don't continue in ast_indicate */
5217 res = 0;
5218 break;
5219 case AST_CONTROL_PROGRESS:
5220 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5221 #ifdef HAVE_PRI
5222 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5223 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5224 if (p->pri->pri) {
5225 if (!pri_grab(p, p->pri)) {
5226 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5227 pri_rel(p->pri);
5229 else
5230 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5232 p->progress = 1;
5234 #endif
5235 /* don't continue in ast_indicate */
5236 res = 0;
5237 break;
5238 case AST_CONTROL_CONGESTION:
5239 chan->hangupcause = AST_CAUSE_CONGESTION;
5240 #ifdef HAVE_PRI
5241 if (p->priindication_oob && p->sig == SIG_PRI) {
5242 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5243 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5244 res = 0;
5245 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5246 if (p->pri) {
5247 if (!pri_grab(p, p->pri)) {
5248 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5249 pri_rel(p->pri);
5250 } else
5251 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5253 p->progress = 1;
5254 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5255 } else
5256 #endif
5257 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5258 break;
5259 case AST_CONTROL_HOLD:
5260 #ifdef HAVE_PRI
5261 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5262 if (!pri_grab(p, p->pri)) {
5263 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5264 pri_rel(p->pri);
5265 } else
5266 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5267 } else
5268 #endif
5269 ast_moh_start(chan, data, p->mohinterpret);
5270 break;
5271 case AST_CONTROL_UNHOLD:
5272 #ifdef HAVE_PRI
5273 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5274 if (!pri_grab(p, p->pri)) {
5275 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5276 pri_rel(p->pri);
5277 } else
5278 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5279 } else
5280 #endif
5281 ast_moh_stop(chan);
5282 break;
5283 case AST_CONTROL_RADIO_KEY:
5284 if (p->radio)
5285 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5286 res = 0;
5287 break;
5288 case AST_CONTROL_RADIO_UNKEY:
5289 if (p->radio)
5290 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5291 res = 0;
5292 break;
5293 case AST_CONTROL_FLASH:
5294 /* flash hookswitch */
5295 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5296 /* Clear out the dial buffer */
5297 p->dop.dialstr[0] = '\0';
5298 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5299 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5300 chan->name, strerror(errno));
5301 } else
5302 res = 0;
5303 } else
5304 res = 0;
5305 break;
5306 case AST_CONTROL_SRCUPDATE:
5307 res = 0;
5308 break;
5309 case -1:
5310 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5311 break;
5313 } else
5314 res = 0;
5315 ast_mutex_unlock(&p->lock);
5316 return res;
5319 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5321 struct ast_channel *tmp;
5322 int deflaw;
5323 int res;
5324 int x,y;
5325 int features;
5326 char *b2 = NULL;
5327 struct dahdi_params ps;
5328 char chanprefix[*dahdi_chan_name_len + 4];
5330 if (i->subs[index].owner) {
5331 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5332 return NULL;
5334 y = 1;
5335 do {
5336 if (b2)
5337 free(b2);
5338 #ifdef HAVE_PRI
5339 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5340 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5341 else
5342 #endif
5343 if (i->channel == CHAN_PSEUDO)
5344 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5345 else
5346 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5347 for (x = 0; x < 3; x++) {
5348 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
5349 break;
5351 y++;
5352 } while (x < 3);
5353 strcpy(chanprefix, dahdi_chan_name);
5354 strcat(chanprefix, "/%s");
5355 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
5356 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5357 free(b2);
5358 if (!tmp)
5359 return NULL;
5360 tmp->tech = chan_tech;
5361 ps.channo = i->channel;
5362 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5363 if (res) {
5364 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5365 ps.curlaw = DAHDI_LAW_MULAW;
5367 if (ps.curlaw == DAHDI_LAW_ALAW)
5368 deflaw = AST_FORMAT_ALAW;
5369 else
5370 deflaw = AST_FORMAT_ULAW;
5371 if (law) {
5372 if (law == DAHDI_LAW_ALAW)
5373 deflaw = AST_FORMAT_ALAW;
5374 else
5375 deflaw = AST_FORMAT_ULAW;
5377 tmp->fds[0] = i->subs[index].dfd;
5378 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5379 /* Start out assuming ulaw since it's smaller :) */
5380 tmp->rawreadformat = deflaw;
5381 tmp->readformat = deflaw;
5382 tmp->rawwriteformat = deflaw;
5383 tmp->writeformat = deflaw;
5384 i->subs[index].linear = 0;
5385 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5386 features = 0;
5387 if (index == SUB_REAL) {
5388 if (i->busydetect && CANBUSYDETECT(i))
5389 features |= DSP_FEATURE_BUSY_DETECT;
5390 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5391 features |= DSP_FEATURE_CALL_PROGRESS;
5392 if ((!i->outgoing && (i->callprogress & 4)) ||
5393 (i->outgoing && (i->callprogress & 2))) {
5394 features |= DSP_FEATURE_FAX_DETECT;
5396 #ifdef DAHDI_TONEDETECT
5397 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5398 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5399 #endif
5400 i->hardwaredtmf = 0;
5401 features |= DSP_FEATURE_DTMF_DETECT;
5402 #ifdef DAHDI_TONEDETECT
5403 } else if (NEED_MFDETECT(i)) {
5404 i->hardwaredtmf = 1;
5405 features |= DSP_FEATURE_DTMF_DETECT;
5407 #endif
5409 if (features) {
5410 if (i->dsp) {
5411 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5412 } else {
5413 if (i->channel != CHAN_PSEUDO)
5414 i->dsp = ast_dsp_new();
5415 else
5416 i->dsp = NULL;
5417 if (i->dsp) {
5418 i->dsp_features = features;
5419 #ifdef HAVE_PRI
5420 /* We cannot do progress detection until receives PROGRESS message */
5421 if (i->outgoing && (i->sig == SIG_PRI)) {
5422 /* Remember requested DSP features, don't treat
5423 talking as ANSWER */
5424 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5425 features = 0;
5427 #endif
5428 ast_dsp_set_features(i->dsp, features);
5429 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5430 if (!ast_strlen_zero(progzone))
5431 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5432 if (i->busydetect && CANBUSYDETECT(i)) {
5433 ast_dsp_set_busy_count(i->dsp, i->busycount);
5434 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5440 if (state == AST_STATE_RING)
5441 tmp->rings = 1;
5442 tmp->tech_pvt = i;
5443 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5444 /* Only FXO signalled stuff can be picked up */
5445 tmp->callgroup = i->callgroup;
5446 tmp->pickupgroup = i->pickupgroup;
5448 if (!ast_strlen_zero(i->language))
5449 ast_string_field_set(tmp, language, i->language);
5450 if (!i->owner)
5451 i->owner = tmp;
5452 if (!ast_strlen_zero(i->accountcode))
5453 ast_string_field_set(tmp, accountcode, i->accountcode);
5454 if (i->amaflags)
5455 tmp->amaflags = i->amaflags;
5456 i->subs[index].owner = tmp;
5457 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5458 ast_string_field_set(tmp, call_forward, i->call_forward);
5459 /* If we've been told "no ADSI" then enforce it */
5460 if (!i->adsi)
5461 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5462 if (!ast_strlen_zero(i->exten))
5463 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5464 if (!ast_strlen_zero(i->rdnis))
5465 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5466 if (!ast_strlen_zero(i->dnid))
5467 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5469 /* Don't use ast_set_callerid() here because it will
5470 * generate a needless NewCallerID event */
5471 #ifdef PRI_ANI
5472 if (!ast_strlen_zero(i->cid_ani))
5473 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5474 else
5475 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5476 #else
5477 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5478 #endif
5479 tmp->cid.cid_pres = i->callingpres;
5480 tmp->cid.cid_ton = i->cid_ton;
5481 #ifdef HAVE_PRI
5482 tmp->transfercapability = transfercapability;
5483 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5484 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5485 i->digital = 1;
5486 /* Assume calls are not idle calls unless we're told differently */
5487 i->isidlecall = 0;
5488 i->alreadyhungup = 0;
5489 #endif
5490 /* clear the fake event in case we posted one before we had ast_channel */
5491 i->fake_event = 0;
5492 /* Assure there is no confmute on this channel */
5493 dahdi_confmute(i, 0);
5494 /* Configure the new channel jb */
5495 ast_jb_configure(tmp, &global_jbconf);
5496 if (startpbx) {
5497 if (ast_pbx_start(tmp)) {
5498 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5499 ast_hangup(tmp);
5500 i->owner = NULL;
5501 return NULL;
5505 ast_module_ref(ast_module_info->self);
5507 return tmp;
5511 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5513 char c;
5515 *str = 0; /* start with empty output buffer */
5516 for (;;)
5518 /* Wait for the first digit (up to specified ms). */
5519 c = ast_waitfordigit(chan, ms);
5520 /* if timeout, hangup or error, return as such */
5521 if (c < 1)
5522 return c;
5523 *str++ = c;
5524 *str = 0;
5525 if (strchr(term, c))
5526 return 1;
5530 static int dahdi_wink(struct dahdi_pvt *p, int index)
5532 int j;
5533 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5534 for (;;)
5536 /* set bits of interest */
5537 j = DAHDI_IOMUX_SIGEVENT;
5538 /* wait for some happening */
5539 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5540 /* exit loop if we have it */
5541 if (j & DAHDI_IOMUX_SIGEVENT) break;
5543 /* get the event info */
5544 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5545 return 0;
5548 static void *ss_thread(void *data)
5550 struct ast_channel *chan = data;
5551 struct dahdi_pvt *p = chan->tech_pvt;
5552 char exten[AST_MAX_EXTENSION] = "";
5553 char exten2[AST_MAX_EXTENSION] = "";
5554 unsigned char buf[256];
5555 char dtmfcid[300];
5556 char dtmfbuf[300];
5557 struct callerid_state *cs = NULL;
5558 char *name = NULL, *number = NULL;
5559 int distMatches;
5560 int curRingData[3];
5561 int receivedRingT;
5562 int counter1;
5563 int counter;
5564 int samples = 0;
5565 struct ast_smdi_md_message *smdi_msg = NULL;
5566 int flags;
5567 int i;
5568 int timeout;
5569 int getforward = 0;
5570 char *s1, *s2;
5571 int len = 0;
5572 int res;
5573 int index;
5575 ast_mutex_lock(&ss_thread_lock);
5576 ss_thread_count++;
5577 ast_mutex_unlock(&ss_thread_lock);
5578 /* in the bizarre case where the channel has become a zombie before we
5579 even get started here, abort safely
5581 if (!p) {
5582 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5583 ast_hangup(chan);
5584 goto quit;
5586 if (option_verbose > 2)
5587 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5588 index = dahdi_get_index(chan, p, 1);
5589 if (index < 0) {
5590 ast_log(LOG_WARNING, "Huh?\n");
5591 ast_hangup(chan);
5592 goto quit;
5594 if (p->dsp)
5595 ast_dsp_digitreset(p->dsp);
5596 switch (p->sig) {
5597 #ifdef HAVE_PRI
5598 case SIG_PRI:
5599 /* Now loop looking for an extension */
5600 ast_copy_string(exten, p->exten, sizeof(exten));
5601 len = strlen(exten);
5602 res = 0;
5603 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5604 if (len && !ast_ignore_pattern(chan->context, exten))
5605 tone_zone_play_tone(p->subs[index].dfd, -1);
5606 else
5607 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5608 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5609 timeout = matchdigittimeout;
5610 else
5611 timeout = gendigittimeout;
5612 res = ast_waitfordigit(chan, timeout);
5613 if (res < 0) {
5614 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5615 ast_hangup(chan);
5616 goto quit;
5617 } else if (res) {
5618 exten[len++] = res;
5619 exten[len] = '\0';
5620 } else
5621 break;
5623 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5624 if (ast_strlen_zero(exten)) {
5625 if (option_verbose > 2)
5626 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5627 exten[0] = 's';
5628 exten[1] = '\0';
5630 tone_zone_play_tone(p->subs[index].dfd, -1);
5631 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5632 /* Start the real PBX */
5633 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5634 if (p->dsp) ast_dsp_digitreset(p->dsp);
5635 dahdi_enable_ec(p);
5636 ast_setstate(chan, AST_STATE_RING);
5637 res = ast_pbx_run(chan);
5638 if (res) {
5639 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5641 } else {
5642 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5643 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5644 ast_hangup(chan);
5645 p->exten[0] = '\0';
5646 /* Since we send release complete here, we won't get one */
5647 p->call = NULL;
5649 goto quit;
5650 break;
5651 #endif
5652 case SIG_FEATD:
5653 case SIG_FEATDMF:
5654 case SIG_FEATDMF_TA:
5655 case SIG_E911:
5656 case SIG_FGC_CAMAMF:
5657 case SIG_FEATB:
5658 case SIG_EMWINK:
5659 case SIG_SF_FEATD:
5660 case SIG_SF_FEATDMF:
5661 case SIG_SF_FEATB:
5662 case SIG_SFWINK:
5663 if (dahdi_wink(p, index))
5664 goto quit;
5665 /* Fall through */
5666 case SIG_EM:
5667 case SIG_EM_E1:
5668 case SIG_SF:
5669 case SIG_FGC_CAMA:
5670 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5671 if (p->dsp)
5672 ast_dsp_digitreset(p->dsp);
5673 /* set digit mode appropriately */
5674 if (p->dsp) {
5675 if (NEED_MFDETECT(p))
5676 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5677 else
5678 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5680 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5681 /* Wait for the first digit only if immediate=no */
5682 if (!p->immediate)
5683 /* Wait for the first digit (up to 5 seconds). */
5684 res = ast_waitfordigit(chan, 5000);
5685 else
5686 res = 0;
5687 if (res > 0) {
5688 /* save first char */
5689 dtmfbuf[0] = res;
5690 switch (p->sig) {
5691 case SIG_FEATD:
5692 case SIG_SF_FEATD:
5693 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5694 if (res > 0)
5695 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5696 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5697 break;
5698 case SIG_FEATDMF_TA:
5699 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5700 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5701 if (dahdi_wink(p, index)) goto quit;
5702 dtmfbuf[0] = 0;
5703 /* Wait for the first digit (up to 5 seconds). */
5704 res = ast_waitfordigit(chan, 5000);
5705 if (res <= 0) break;
5706 dtmfbuf[0] = res;
5707 /* fall through intentionally */
5708 case SIG_FEATDMF:
5709 case SIG_E911:
5710 case SIG_FGC_CAMAMF:
5711 case SIG_SF_FEATDMF:
5712 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5713 /* if international caca, do it again to get real ANO */
5714 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5716 if (dahdi_wink(p, index)) goto quit;
5717 dtmfbuf[0] = 0;
5718 /* Wait for the first digit (up to 5 seconds). */
5719 res = ast_waitfordigit(chan, 5000);
5720 if (res <= 0) break;
5721 dtmfbuf[0] = res;
5722 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5724 if (res > 0) {
5725 /* if E911, take off hook */
5726 if (p->sig == SIG_E911)
5727 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5728 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5730 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5731 break;
5732 case SIG_FEATB:
5733 case SIG_SF_FEATB:
5734 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5735 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5736 break;
5737 case SIG_EMWINK:
5738 /* if we received a '*', we are actually receiving Feature Group D
5739 dial syntax, so use that mode; otherwise, fall through to normal
5740 mode
5742 if (res == '*') {
5743 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5744 if (res > 0)
5745 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5746 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5747 break;
5749 default:
5750 /* If we got the first digit, get the rest */
5751 len = 1;
5752 dtmfbuf[len] = '\0';
5753 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5754 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5755 timeout = matchdigittimeout;
5756 } else {
5757 timeout = gendigittimeout;
5759 res = ast_waitfordigit(chan, timeout);
5760 if (res < 0) {
5761 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5762 ast_hangup(chan);
5763 goto quit;
5764 } else if (res) {
5765 dtmfbuf[len++] = res;
5766 dtmfbuf[len] = '\0';
5767 } else {
5768 break;
5771 break;
5774 if (res == -1) {
5775 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5776 ast_hangup(chan);
5777 goto quit;
5778 } else if (res < 0) {
5779 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
5780 ast_hangup(chan);
5781 goto quit;
5784 if (p->sig == SIG_FGC_CAMA) {
5785 char anibuf[100];
5787 if (ast_safe_sleep(chan,1000) == -1) {
5788 ast_hangup(chan);
5789 goto quit;
5791 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5792 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5793 res = my_getsigstr(chan, anibuf, "#", 10000);
5794 if ((res > 0) && (strlen(anibuf) > 2)) {
5795 if (anibuf[strlen(anibuf) - 1] == '#')
5796 anibuf[strlen(anibuf) - 1] = 0;
5797 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
5799 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5802 ast_copy_string(exten, dtmfbuf, sizeof(exten));
5803 if (ast_strlen_zero(exten))
5804 ast_copy_string(exten, "s", sizeof(exten));
5805 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
5806 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
5807 if (exten[0] == '*') {
5808 char *stringp=NULL;
5809 ast_copy_string(exten2, exten, sizeof(exten2));
5810 /* Parse out extension and callerid */
5811 stringp=exten2 +1;
5812 s1 = strsep(&stringp, "*");
5813 s2 = strsep(&stringp, "*");
5814 if (s2) {
5815 if (!ast_strlen_zero(p->cid_num))
5816 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5817 else
5818 ast_set_callerid(chan, s1, NULL, s1);
5819 ast_copy_string(exten, s2, sizeof(exten));
5820 } else
5821 ast_copy_string(exten, s1, sizeof(exten));
5822 } else if (p->sig == SIG_FEATD)
5823 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5825 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5826 if (exten[0] == '*') {
5827 char *stringp=NULL;
5828 ast_copy_string(exten2, exten, sizeof(exten2));
5829 /* Parse out extension and callerid */
5830 stringp=exten2 +1;
5831 s1 = strsep(&stringp, "#");
5832 s2 = strsep(&stringp, "#");
5833 if (s2) {
5834 if (!ast_strlen_zero(p->cid_num))
5835 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5836 else
5837 if (*(s1 + 2))
5838 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
5839 ast_copy_string(exten, s2 + 1, sizeof(exten));
5840 } else
5841 ast_copy_string(exten, s1 + 2, sizeof(exten));
5842 } else
5843 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
5845 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
5846 if (exten[0] == '*') {
5847 char *stringp=NULL;
5848 ast_copy_string(exten2, exten, sizeof(exten2));
5849 /* Parse out extension and callerid */
5850 stringp=exten2 +1;
5851 s1 = strsep(&stringp, "#");
5852 s2 = strsep(&stringp, "#");
5853 if (s2 && (*(s2 + 1) == '0')) {
5854 if (*(s2 + 2))
5855 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
5857 if (s1) ast_copy_string(exten, s1, sizeof(exten));
5858 else ast_copy_string(exten, "911", sizeof(exten));
5859 } else
5860 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
5862 if (p->sig == SIG_FEATB) {
5863 if (exten[0] == '*') {
5864 char *stringp=NULL;
5865 ast_copy_string(exten2, exten, sizeof(exten2));
5866 /* Parse out extension and callerid */
5867 stringp=exten2 +1;
5868 s1 = strsep(&stringp, "#");
5869 ast_copy_string(exten, exten2 + 1, sizeof(exten));
5870 } else
5871 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
5873 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
5874 dahdi_wink(p, index);
5875 /* some switches require a minimum guard time between
5876 the last FGD wink and something that answers
5877 immediately. This ensures it */
5878 if (ast_safe_sleep(chan,100)) goto quit;
5880 dahdi_enable_ec(p);
5881 if (NEED_MFDETECT(p)) {
5882 if (p->dsp) {
5883 if (!p->hardwaredtmf)
5884 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5885 else {
5886 ast_dsp_free(p->dsp);
5887 p->dsp = NULL;
5892 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
5893 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5894 if (p->dsp) ast_dsp_digitreset(p->dsp);
5895 res = ast_pbx_run(chan);
5896 if (res) {
5897 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5898 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5900 goto quit;
5901 } else {
5902 if (option_verbose > 2)
5903 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
5904 sleep(2);
5905 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
5906 if (res < 0)
5907 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
5908 else
5909 sleep(1);
5910 res = ast_streamfile(chan, "ss-noservice", chan->language);
5911 if (res >= 0)
5912 ast_waitstream(chan, "");
5913 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5914 ast_hangup(chan);
5915 goto quit;
5917 break;
5918 case SIG_FXOLS:
5919 case SIG_FXOGS:
5920 case SIG_FXOKS:
5921 /* Read the first digit */
5922 timeout = firstdigittimeout;
5923 /* If starting a threeway call, never timeout on the first digit so someone
5924 can use flash-hook as a "hold" feature */
5925 if (p->subs[SUB_THREEWAY].owner)
5926 timeout = 999999;
5927 while (len < AST_MAX_EXTENSION-1) {
5928 /* Read digit unless it's supposed to be immediate, in which case the
5929 only answer is 's' */
5930 if (p->immediate)
5931 res = 's';
5932 else
5933 res = ast_waitfordigit(chan, timeout);
5934 timeout = 0;
5935 if (res < 0) {
5936 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5937 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5938 ast_hangup(chan);
5939 goto quit;
5940 } else if (res) {
5941 exten[len++]=res;
5942 exten[len] = '\0';
5944 if (!ast_ignore_pattern(chan->context, exten))
5945 tone_zone_play_tone(p->subs[index].dfd, -1);
5946 else
5947 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5948 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
5949 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5950 if (getforward) {
5951 /* Record this as the forwarding extension */
5952 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
5953 if (option_verbose > 2)
5954 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
5955 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
5956 if (res)
5957 break;
5958 usleep(500000);
5959 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5960 sleep(1);
5961 memset(exten, 0, sizeof(exten));
5962 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5963 len = 0;
5964 getforward = 0;
5965 } else {
5966 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5967 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5968 if (!ast_strlen_zero(p->cid_num)) {
5969 if (!p->hidecallerid)
5970 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
5971 else
5972 ast_set_callerid(chan, NULL, NULL, p->cid_num);
5974 if (!ast_strlen_zero(p->cid_name)) {
5975 if (!p->hidecallerid)
5976 ast_set_callerid(chan, NULL, p->cid_name, NULL);
5978 ast_setstate(chan, AST_STATE_RING);
5979 dahdi_enable_ec(p);
5980 res = ast_pbx_run(chan);
5981 if (res) {
5982 ast_log(LOG_WARNING, "PBX exited non-zero\n");
5983 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5985 goto quit;
5987 } else {
5988 /* It's a match, but they just typed a digit, and there is an ambiguous match,
5989 so just set the timeout to matchdigittimeout and wait some more */
5990 timeout = matchdigittimeout;
5992 } else if (res == 0) {
5993 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
5994 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5995 dahdi_wait_event(p->subs[index].dfd);
5996 ast_hangup(chan);
5997 goto quit;
5998 } else if (p->callwaiting && !strcmp(exten, "*70")) {
5999 if (option_verbose > 2)
6000 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
6001 /* Disable call waiting if enabled */
6002 p->callwaiting = 0;
6003 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6004 if (res) {
6005 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6006 chan->name, strerror(errno));
6008 len = 0;
6009 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
6010 memset(exten, 0, sizeof(exten));
6011 timeout = firstdigittimeout;
6013 } else if (!strcmp(exten,ast_pickup_ext())) {
6014 /* Scan all channels and see if there are any
6015 * ringing channels that have call groups
6016 * that equal this channels pickup group
6018 if (index == SUB_REAL) {
6019 /* Switch us from Third call to Call Wait */
6020 if (p->subs[SUB_THREEWAY].owner) {
6021 /* If you make a threeway call and the *8# a call, it should actually
6022 look like a callwait */
6023 alloc_sub(p, SUB_CALLWAIT);
6024 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6025 unalloc_sub(p, SUB_THREEWAY);
6027 dahdi_enable_ec(p);
6028 if (ast_pickup_call(chan)) {
6029 ast_log(LOG_DEBUG, "No call pickup possible...\n");
6030 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6031 dahdi_wait_event(p->subs[index].dfd);
6033 ast_hangup(chan);
6034 goto quit;
6035 } else {
6036 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
6037 ast_hangup(chan);
6038 goto quit;
6041 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
6042 if (option_verbose > 2)
6043 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
6044 /* Disable Caller*ID if enabled */
6045 p->hidecallerid = 1;
6046 if (chan->cid.cid_num)
6047 free(chan->cid.cid_num);
6048 chan->cid.cid_num = NULL;
6049 if (chan->cid.cid_name)
6050 free(chan->cid.cid_name);
6051 chan->cid.cid_name = NULL;
6052 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6053 if (res) {
6054 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6055 chan->name, strerror(errno));
6057 len = 0;
6058 memset(exten, 0, sizeof(exten));
6059 timeout = firstdigittimeout;
6060 } else if (p->callreturn && !strcmp(exten, "*69")) {
6061 res = 0;
6062 if (!ast_strlen_zero(p->lastcid_num)) {
6063 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
6065 if (!res)
6066 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6067 break;
6068 } else if (!strcmp(exten, "*78")) {
6069 /* Do not disturb */
6070 if (option_verbose > 2)
6071 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
6072 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6073 "Channel: %s/%d\r\n"
6074 "Status: enabled\r\n", dahdi_chan_name, p->channel);
6075 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6076 p->dnd = 1;
6077 getforward = 0;
6078 memset(exten, 0, sizeof(exten));
6079 len = 0;
6080 } else if (!strcmp(exten, "*79")) {
6081 /* Do not disturb */
6082 if (option_verbose > 2)
6083 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
6084 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6085 "Channel: %s/%d\r\n"
6086 "Status: disabled\r\n", dahdi_chan_name, p->channel);
6087 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6088 p->dnd = 0;
6089 getforward = 0;
6090 memset(exten, 0, sizeof(exten));
6091 len = 0;
6092 } else if (p->cancallforward && !strcmp(exten, "*72")) {
6093 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6094 getforward = 1;
6095 memset(exten, 0, sizeof(exten));
6096 len = 0;
6097 } else if (p->cancallforward && !strcmp(exten, "*73")) {
6098 if (option_verbose > 2)
6099 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
6100 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6101 memset(p->call_forward, 0, sizeof(p->call_forward));
6102 getforward = 0;
6103 memset(exten, 0, sizeof(exten));
6104 len = 0;
6105 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
6106 p->subs[SUB_THREEWAY].owner &&
6107 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6108 /* This is a three way call, the main call being a real channel,
6109 and we're parking the first call. */
6110 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
6111 if (option_verbose > 2)
6112 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
6113 break;
6114 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
6115 if (option_verbose > 2)
6116 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
6117 res = ast_db_put("blacklist", p->lastcid_num, "1");
6118 if (!res) {
6119 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6120 memset(exten, 0, sizeof(exten));
6121 len = 0;
6123 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6124 if (option_verbose > 2)
6125 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6126 /* Enable Caller*ID if enabled */
6127 p->hidecallerid = 0;
6128 if (chan->cid.cid_num)
6129 free(chan->cid.cid_num);
6130 chan->cid.cid_num = NULL;
6131 if (chan->cid.cid_name)
6132 free(chan->cid.cid_name);
6133 chan->cid.cid_name = NULL;
6134 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6135 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6136 if (res) {
6137 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6138 chan->name, strerror(errno));
6140 len = 0;
6141 memset(exten, 0, sizeof(exten));
6142 timeout = firstdigittimeout;
6143 } else if (!strcmp(exten, "*0")) {
6144 struct ast_channel *nbridge =
6145 p->subs[SUB_THREEWAY].owner;
6146 struct dahdi_pvt *pbridge = NULL;
6147 /* set up the private struct of the bridged one, if any */
6148 if (nbridge && ast_bridged_channel(nbridge))
6149 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6150 if (nbridge && pbridge &&
6151 (nbridge->tech == chan_tech) &&
6152 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
6153 ISTRUNK(pbridge)) {
6154 int func = DAHDI_FLASH;
6155 /* Clear out the dial buffer */
6156 p->dop.dialstr[0] = '\0';
6157 /* flash hookswitch */
6158 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6159 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6160 nbridge->name, strerror(errno));
6162 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6163 unalloc_sub(p, SUB_THREEWAY);
6164 p->owner = p->subs[SUB_REAL].owner;
6165 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6166 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6167 ast_hangup(chan);
6168 goto quit;
6169 } else {
6170 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6171 dahdi_wait_event(p->subs[index].dfd);
6172 tone_zone_play_tone(p->subs[index].dfd, -1);
6173 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6174 unalloc_sub(p, SUB_THREEWAY);
6175 p->owner = p->subs[SUB_REAL].owner;
6176 ast_hangup(chan);
6177 goto quit;
6179 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6180 ((exten[0] != '*') || (strlen(exten) > 2))) {
6181 if (option_debug)
6182 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);
6183 break;
6185 if (!timeout)
6186 timeout = gendigittimeout;
6187 if (len && !ast_ignore_pattern(chan->context, exten))
6188 tone_zone_play_tone(p->subs[index].dfd, -1);
6190 break;
6191 case SIG_FXSLS:
6192 case SIG_FXSGS:
6193 case SIG_FXSKS:
6194 #ifdef HAVE_PRI
6195 if (p->pri) {
6196 /* This is a GR-303 trunk actually. Wait for the first ring... */
6197 struct ast_frame *f;
6198 int res;
6199 time_t start;
6201 time(&start);
6202 ast_setstate(chan, AST_STATE_RING);
6203 while (time(NULL) < start + 3) {
6204 res = ast_waitfor(chan, 1000);
6205 if (res) {
6206 f = ast_read(chan);
6207 if (!f) {
6208 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6209 ast_hangup(chan);
6210 goto quit;
6211 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6212 res = 1;
6213 } else
6214 res = 0;
6215 ast_frfree(f);
6216 if (res) {
6217 ast_log(LOG_DEBUG, "Got ring!\n");
6218 res = 0;
6219 break;
6224 #endif
6225 /* check for SMDI messages */
6226 if (p->use_smdi && p->smdi_iface) {
6227 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6229 if (smdi_msg != NULL) {
6230 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6232 if (smdi_msg->type == 'B')
6233 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6234 else if (smdi_msg->type == 'N')
6235 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6237 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6238 } else {
6239 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6243 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6244 number = smdi_msg->calling_st;
6246 /* If we want caller id, we're in a prering state due to a polarity reversal
6247 * and we're set to use a polarity reversal to trigger the start of caller id,
6248 * grab the caller id and wait for ringing to start... */
6249 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6250 /* If set to use DTMF CID signalling, listen for DTMF */
6251 if (p->cid_signalling == CID_SIG_DTMF) {
6252 int i = 0;
6253 cs = NULL;
6254 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6255 "channel %s\n", chan->name);
6256 dahdi_setlinear(p->subs[index].dfd, 0);
6257 res = 2000;
6258 for (;;) {
6259 struct ast_frame *f;
6260 res = ast_waitfor(chan, res);
6261 if (res <= 0) {
6262 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6263 "Exiting simple switch\n");
6264 ast_hangup(chan);
6265 goto quit;
6267 f = ast_read(chan);
6268 if (!f)
6269 break;
6270 if (f->frametype == AST_FRAME_DTMF) {
6271 dtmfbuf[i++] = f->subclass;
6272 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6273 res = 2000;
6275 ast_frfree(f);
6276 if (chan->_state == AST_STATE_RING ||
6277 chan->_state == AST_STATE_RINGING)
6278 break; /* Got ring */
6280 dtmfbuf[i] = '\0';
6281 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6282 /* Got cid and ring. */
6283 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6284 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6285 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6286 dtmfcid, flags);
6287 /* If first byte is NULL, we have no cid */
6288 if (!ast_strlen_zero(dtmfcid))
6289 number = dtmfcid;
6290 else
6291 number = NULL;
6292 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6293 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6294 cs = callerid_new(p->cid_signalling);
6295 if (cs) {
6296 samples = 0;
6297 #if 1
6298 bump_gains(p);
6299 #endif
6300 /* Take out of linear mode for Caller*ID processing */
6301 dahdi_setlinear(p->subs[index].dfd, 0);
6303 /* First we wait and listen for the Caller*ID */
6304 for (;;) {
6305 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6306 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6307 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6308 callerid_free(cs);
6309 ast_hangup(chan);
6310 goto quit;
6312 if (i & DAHDI_IOMUX_SIGEVENT) {
6313 res = dahdi_get_event(p->subs[index].dfd);
6314 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6316 if (p->cid_signalling == CID_SIG_V23_JP) {
6317 #ifdef DAHDI_EVENT_RINGBEGIN
6318 if (res == DAHDI_EVENT_RINGBEGIN) {
6319 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6320 usleep(1);
6322 #endif
6323 } else {
6324 res = 0;
6325 break;
6327 } else if (i & DAHDI_IOMUX_READ) {
6328 res = read(p->subs[index].dfd, buf, sizeof(buf));
6329 if (res < 0) {
6330 if (errno != ELAST) {
6331 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6332 callerid_free(cs);
6333 ast_hangup(chan);
6334 goto quit;
6336 break;
6338 samples += res;
6340 if (p->cid_signalling == CID_SIG_V23_JP) {
6341 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6342 } else {
6343 res = callerid_feed(cs, buf, res, AST_LAW(p));
6346 if (res < 0) {
6347 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6348 break;
6349 } else if (res)
6350 break;
6351 else if (samples > (8000 * 10))
6352 break;
6355 if (res == 1) {
6356 callerid_get(cs, &name, &number, &flags);
6357 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6360 if (p->cid_signalling == CID_SIG_V23_JP) {
6361 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6362 usleep(1);
6363 res = 4000;
6364 } else {
6366 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6367 res = 2000;
6370 for (;;) {
6371 struct ast_frame *f;
6372 res = ast_waitfor(chan, res);
6373 if (res <= 0) {
6374 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6375 "Exiting simple switch\n");
6376 ast_hangup(chan);
6377 goto quit;
6379 if (!(f = ast_read(chan))) {
6380 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6381 ast_hangup(chan);
6382 goto quit;
6384 ast_frfree(f);
6385 if (chan->_state == AST_STATE_RING ||
6386 chan->_state == AST_STATE_RINGING)
6387 break; /* Got ring */
6390 /* We must have a ring by now, so, if configured, lets try to listen for
6391 * distinctive ringing */
6392 if (p->usedistinctiveringdetection == 1) {
6393 len = 0;
6394 distMatches = 0;
6395 /* Clear the current ring data array so we dont have old data in it. */
6396 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6397 curRingData[receivedRingT] = 0;
6398 receivedRingT = 0;
6399 counter = 0;
6400 counter1 = 0;
6401 /* Check to see if context is what it should be, if not set to be. */
6402 if (strcmp(p->context,p->defcontext) != 0) {
6403 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6404 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6407 for (;;) {
6408 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6409 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6410 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6411 callerid_free(cs);
6412 ast_hangup(chan);
6413 goto quit;
6415 if (i & DAHDI_IOMUX_SIGEVENT) {
6416 res = dahdi_get_event(p->subs[index].dfd);
6417 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6418 res = 0;
6419 /* Let us detect distinctive ring */
6421 curRingData[receivedRingT] = p->ringt;
6423 if (p->ringt < p->ringt_base/2)
6424 break;
6425 /* Increment the ringT counter so we can match it against
6426 values in chan_dahdi.conf for distinctive ring */
6427 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6428 break;
6429 } else if (i & DAHDI_IOMUX_READ) {
6430 res = read(p->subs[index].dfd, buf, sizeof(buf));
6431 if (res < 0) {
6432 if (errno != ELAST) {
6433 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6434 callerid_free(cs);
6435 ast_hangup(chan);
6436 goto quit;
6438 break;
6440 if (p->ringt)
6441 p->ringt--;
6442 if (p->ringt == 1) {
6443 res = -1;
6444 break;
6448 if (option_verbose > 2)
6449 /* this only shows up if you have n of the dring patterns filled in */
6450 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6452 for (counter = 0; counter < 3; counter++) {
6453 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6454 channel */
6455 distMatches = 0;
6456 for (counter1 = 0; counter1 < 3; counter1++) {
6457 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6458 (p->drings.ringnum[counter].ring[counter1]-10)) {
6459 distMatches++;
6462 if (distMatches == 3) {
6463 /* The ring matches, set the context to whatever is for distinctive ring.. */
6464 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6465 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6466 if (option_verbose > 2)
6467 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6468 break;
6472 /* Restore linear mode (if appropriate) for Caller*ID processing */
6473 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6474 #if 1
6475 restore_gains(p);
6476 #endif
6477 } else
6478 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6479 } else {
6480 ast_log(LOG_WARNING, "Channel %s in prering "
6481 "state, but I have nothing to do. "
6482 "Terminating simple switch, should be "
6483 "restarted by the actual ring.\n",
6484 chan->name);
6485 ast_hangup(chan);
6486 goto quit;
6488 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6489 /* FSK Bell202 callerID */
6490 cs = callerid_new(p->cid_signalling);
6491 if (cs) {
6492 #if 1
6493 bump_gains(p);
6494 #endif
6495 samples = 0;
6496 len = 0;
6497 distMatches = 0;
6498 /* Clear the current ring data array so we dont have old data in it. */
6499 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6500 curRingData[receivedRingT] = 0;
6501 receivedRingT = 0;
6502 counter = 0;
6503 counter1 = 0;
6504 /* Check to see if context is what it should be, if not set to be. */
6505 if (strcmp(p->context,p->defcontext) != 0) {
6506 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6507 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6510 /* Take out of linear mode for Caller*ID processing */
6511 dahdi_setlinear(p->subs[index].dfd, 0);
6512 for (;;) {
6513 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6514 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6515 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6516 callerid_free(cs);
6517 ast_hangup(chan);
6518 goto quit;
6520 if (i & DAHDI_IOMUX_SIGEVENT) {
6521 res = dahdi_get_event(p->subs[index].dfd);
6522 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6523 /* If we get a PR event, they hung up while processing calerid */
6524 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6525 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6526 p->polarity = POLARITY_IDLE;
6527 callerid_free(cs);
6528 ast_hangup(chan);
6529 goto quit;
6531 res = 0;
6532 /* Let us detect callerid when the telco uses distinctive ring */
6534 curRingData[receivedRingT] = p->ringt;
6536 if (p->ringt < p->ringt_base/2)
6537 break;
6538 /* Increment the ringT counter so we can match it against
6539 values in chan_dahdi.conf for distinctive ring */
6540 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6541 break;
6542 } else if (i & DAHDI_IOMUX_READ) {
6543 res = read(p->subs[index].dfd, buf, sizeof(buf));
6544 if (res < 0) {
6545 if (errno != ELAST) {
6546 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6547 callerid_free(cs);
6548 ast_hangup(chan);
6549 goto quit;
6551 break;
6553 if (p->ringt)
6554 p->ringt--;
6555 if (p->ringt == 1) {
6556 res = -1;
6557 break;
6559 samples += res;
6560 res = callerid_feed(cs, buf, res, AST_LAW(p));
6561 if (res < 0) {
6562 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6563 break;
6564 } else if (res)
6565 break;
6566 else if (samples > (8000 * 10))
6567 break;
6570 if (res == 1) {
6571 callerid_get(cs, &name, &number, &flags);
6572 if (option_debug)
6573 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6575 if (distinctiveringaftercid == 1) {
6576 /* Clear the current ring data array so we dont have old data in it. */
6577 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6578 curRingData[receivedRingT] = 0;
6580 receivedRingT = 0;
6581 if (option_verbose > 2)
6582 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6583 for (;;) {
6584 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6585 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6586 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6587 callerid_free(cs);
6588 ast_hangup(chan);
6589 goto quit;
6591 if (i & DAHDI_IOMUX_SIGEVENT) {
6592 res = dahdi_get_event(p->subs[index].dfd);
6593 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6594 res = 0;
6595 /* Let us detect callerid when the telco uses distinctive ring */
6597 curRingData[receivedRingT] = p->ringt;
6599 if (p->ringt < p->ringt_base/2)
6600 break;
6601 /* Increment the ringT counter so we can match it against
6602 values in chan_dahdi.conf for distinctive ring */
6603 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6604 break;
6605 } else if (i & DAHDI_IOMUX_READ) {
6606 res = read(p->subs[index].dfd, buf, sizeof(buf));
6607 if (res < 0) {
6608 if (errno != ELAST) {
6609 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6610 callerid_free(cs);
6611 ast_hangup(chan);
6612 goto quit;
6614 break;
6616 if (p->ringt)
6617 p->ringt--;
6618 if (p->ringt == 1) {
6619 res = -1;
6620 break;
6625 if (p->usedistinctiveringdetection == 1) {
6626 if (option_verbose > 2)
6627 /* this only shows up if you have n of the dring patterns filled in */
6628 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6630 for (counter = 0; counter < 3; counter++) {
6631 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6632 channel */
6633 if (option_verbose > 2)
6634 /* this only shows up if you have n of the dring patterns filled in */
6635 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6636 p->drings.ringnum[counter].ring[0],
6637 p->drings.ringnum[counter].ring[1],
6638 p->drings.ringnum[counter].ring[2]);
6639 distMatches = 0;
6640 for (counter1 = 0; counter1 < 3; counter1++) {
6641 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6642 (p->drings.ringnum[counter].ring[counter1]-10)) {
6643 distMatches++;
6646 if (distMatches == 3) {
6647 /* The ring matches, set the context to whatever is for distinctive ring.. */
6648 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6649 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6650 if (option_verbose > 2)
6651 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6652 break;
6656 /* Restore linear mode (if appropriate) for Caller*ID processing */
6657 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6658 #if 1
6659 restore_gains(p);
6660 #endif
6661 if (res < 0) {
6662 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6664 } else
6665 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6667 else
6668 cs = NULL;
6670 if (number)
6671 ast_shrink_phone_number(number);
6672 ast_set_callerid(chan, number, name, number);
6674 if (smdi_msg)
6675 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6677 if (cs)
6678 callerid_free(cs);
6680 ast_setstate(chan, AST_STATE_RING);
6681 chan->rings = 1;
6682 p->ringt = p->ringt_base;
6683 res = ast_pbx_run(chan);
6684 if (res) {
6685 ast_hangup(chan);
6686 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6688 goto quit;
6689 default:
6690 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6691 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6692 if (res < 0)
6693 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6695 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6696 if (res < 0)
6697 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6698 ast_hangup(chan);
6699 quit:
6700 ast_mutex_lock(&ss_thread_lock);
6701 ss_thread_count--;
6702 ast_cond_signal(&ss_thread_complete);
6703 ast_mutex_unlock(&ss_thread_lock);
6704 return NULL;
6707 /* destroy a DAHDI channel, identified by its number */
6708 static int dahdi_destroy_channel_bynum(int channel)
6710 struct dahdi_pvt *tmp = NULL;
6711 struct dahdi_pvt *prev = NULL;
6713 tmp = iflist;
6714 while (tmp) {
6715 if (tmp->channel == channel) {
6716 int x = DAHDI_FLASH;
6717 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 */
6718 destroy_channel(prev, tmp, 1);
6719 ast_module_unref(ast_module_info->self);
6720 return RESULT_SUCCESS;
6722 prev = tmp;
6723 tmp = tmp->next;
6725 return RESULT_FAILURE;
6728 static int handle_init_event(struct dahdi_pvt *i, int event)
6730 int res;
6731 pthread_t threadid;
6732 pthread_attr_t attr;
6733 struct ast_channel *chan;
6734 pthread_attr_init(&attr);
6735 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6736 /* Handle an event on a given channel for the monitor thread. */
6737 switch (event) {
6738 case DAHDI_EVENT_NONE:
6739 case DAHDI_EVENT_BITSCHANGED:
6740 break;
6741 case DAHDI_EVENT_WINKFLASH:
6742 case DAHDI_EVENT_RINGOFFHOOK:
6743 if (i->inalarm) break;
6744 if (i->radio) break;
6745 /* Got a ring/answer. What kind of channel are we? */
6746 switch (i->sig) {
6747 case SIG_FXOLS:
6748 case SIG_FXOGS:
6749 case SIG_FXOKS:
6750 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6751 if (res && (errno == EBUSY))
6752 break;
6753 if (i->cidspill) {
6754 /* Cancel VMWI spill */
6755 free(i->cidspill);
6756 i->cidspill = NULL;
6758 if (i->immediate) {
6759 dahdi_enable_ec(i);
6760 /* The channel is immediately up. Start right away */
6761 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6762 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6763 if (!chan) {
6764 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6765 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6766 if (res < 0)
6767 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6769 } else {
6770 /* Check for callerid, digits, etc */
6771 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6772 if (chan) {
6773 if (has_voicemail(i))
6774 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6775 else
6776 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6777 if (res < 0)
6778 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
6779 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6780 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6781 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6782 if (res < 0)
6783 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6784 ast_hangup(chan);
6786 } else
6787 ast_log(LOG_WARNING, "Unable to create channel\n");
6789 break;
6790 case SIG_FXSLS:
6791 case SIG_FXSGS:
6792 case SIG_FXSKS:
6793 i->ringt = i->ringt_base;
6794 /* Fall through */
6795 case SIG_EMWINK:
6796 case SIG_FEATD:
6797 case SIG_FEATDMF:
6798 case SIG_FEATDMF_TA:
6799 case SIG_E911:
6800 case SIG_FGC_CAMA:
6801 case SIG_FGC_CAMAMF:
6802 case SIG_FEATB:
6803 case SIG_EM:
6804 case SIG_EM_E1:
6805 case SIG_SFWINK:
6806 case SIG_SF_FEATD:
6807 case SIG_SF_FEATDMF:
6808 case SIG_SF_FEATB:
6809 case SIG_SF:
6810 /* Check for callerid, digits, etc */
6811 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
6812 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6813 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6814 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6815 if (res < 0)
6816 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6817 ast_hangup(chan);
6818 } else if (!chan) {
6819 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
6821 break;
6822 default:
6823 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6824 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6825 if (res < 0)
6826 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6827 return -1;
6829 break;
6830 case DAHDI_EVENT_NOALARM:
6831 i->inalarm = 0;
6832 if (!i->unknown_alarm) {
6833 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
6834 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
6835 "Channel: %d\r\n", i->channel);
6836 } else {
6837 i->unknown_alarm = 0;
6839 break;
6840 case DAHDI_EVENT_ALARM:
6841 i->inalarm = 1;
6842 res = get_alarms(i);
6843 handle_alarms(i, res);
6844 /* fall thru intentionally */
6845 case DAHDI_EVENT_ONHOOK:
6846 if (i->radio)
6847 break;
6848 /* Back on hook. Hang up. */
6849 switch (i->sig) {
6850 case SIG_FXOLS:
6851 case SIG_FXOGS:
6852 case SIG_FEATD:
6853 case SIG_FEATDMF:
6854 case SIG_FEATDMF_TA:
6855 case SIG_E911:
6856 case SIG_FGC_CAMA:
6857 case SIG_FGC_CAMAMF:
6858 case SIG_FEATB:
6859 case SIG_EM:
6860 case SIG_EM_E1:
6861 case SIG_EMWINK:
6862 case SIG_SF_FEATD:
6863 case SIG_SF_FEATDMF:
6864 case SIG_SF_FEATB:
6865 case SIG_SF:
6866 case SIG_SFWINK:
6867 case SIG_FXSLS:
6868 case SIG_FXSGS:
6869 case SIG_FXSKS:
6870 case SIG_GR303FXSKS:
6871 dahdi_disable_ec(i);
6872 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6873 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6874 break;
6875 case SIG_GR303FXOKS:
6876 case SIG_FXOKS:
6877 dahdi_disable_ec(i);
6878 /* Diddle the battery for the zhone */
6879 #ifdef ZHONE_HACK
6880 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6881 usleep(1);
6882 #endif
6883 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6884 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6885 break;
6886 case SIG_PRI:
6887 dahdi_disable_ec(i);
6888 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6889 break;
6890 default:
6891 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
6892 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
6893 return -1;
6895 break;
6896 case DAHDI_EVENT_POLARITY:
6897 switch (i->sig) {
6898 case SIG_FXSLS:
6899 case SIG_FXSKS:
6900 case SIG_FXSGS:
6901 /* We have already got a PR before the channel was
6902 created, but it wasn't handled. We need polarity
6903 to be REV for remote hangup detection to work.
6904 At least in Spain */
6905 if (i->hanguponpolarityswitch)
6906 i->polarity = POLARITY_REV;
6908 if (i->cid_start == CID_START_POLARITY) {
6909 i->polarity = POLARITY_REV;
6910 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
6911 "CID detection on channel %d\n",
6912 i->channel);
6913 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
6914 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
6915 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
6918 break;
6919 default:
6920 ast_log(LOG_WARNING, "handle_init_event detected "
6921 "polarity reversal on non-FXO (SIG_FXS) "
6922 "interface %d\n", i->channel);
6924 break;
6925 case DAHDI_EVENT_REMOVED: /* destroy channel */
6926 ast_log(LOG_NOTICE,
6927 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
6928 i->channel);
6929 dahdi_destroy_channel_bynum(i->channel);
6930 break;
6932 pthread_attr_destroy(&attr);
6933 return 0;
6936 static void *do_monitor(void *data)
6938 int count, res, res2, spoint, pollres=0;
6939 struct dahdi_pvt *i;
6940 struct dahdi_pvt *last = NULL;
6941 time_t thispass = 0, lastpass = 0;
6942 int found;
6943 char buf[1024];
6944 struct pollfd *pfds=NULL;
6945 int lastalloc = -1;
6946 /* This thread monitors all the frame relay interfaces which are not yet in use
6947 (and thus do not have a separate thread) indefinitely */
6948 /* From here on out, we die whenever asked */
6949 #if 0
6950 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
6951 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
6952 return NULL;
6954 ast_log(LOG_DEBUG, "Monitor starting...\n");
6955 #endif
6956 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
6958 for (;;) {
6959 /* Lock the interface list */
6960 ast_mutex_lock(&iflock);
6961 if (!pfds || (lastalloc != ifcount)) {
6962 if (pfds) {
6963 free(pfds);
6964 pfds = NULL;
6966 if (ifcount) {
6967 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
6968 ast_mutex_unlock(&iflock);
6969 return NULL;
6972 lastalloc = ifcount;
6974 /* Build the stuff we're going to poll on, that is the socket of every
6975 dahdi_pvt that does not have an associated owner channel */
6976 count = 0;
6977 i = iflist;
6978 while (i) {
6979 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
6980 if (!i->owner && !i->subs[SUB_REAL].owner) {
6981 /* This needs to be watched, as it lacks an owner */
6982 pfds[count].fd = i->subs[SUB_REAL].dfd;
6983 pfds[count].events = POLLPRI;
6984 pfds[count].revents = 0;
6985 /* Message waiting or r2 channels also get watched for reading */
6986 if (i->cidspill)
6987 pfds[count].events |= POLLIN;
6988 count++;
6991 i = i->next;
6993 /* Okay, now that we know what to do, release the interface lock */
6994 ast_mutex_unlock(&iflock);
6996 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
6997 pthread_testcancel();
6998 /* Wait at least a second for something to happen */
6999 res = poll(pfds, count, 1000);
7000 pthread_testcancel();
7001 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
7003 /* Okay, poll has finished. Let's see what happened. */
7004 if (res < 0) {
7005 if ((errno != EAGAIN) && (errno != EINTR))
7006 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
7007 continue;
7009 /* Alright, lock the interface list again, and let's look and see what has
7010 happened */
7011 ast_mutex_lock(&iflock);
7012 found = 0;
7013 spoint = 0;
7014 lastpass = thispass;
7015 thispass = time(NULL);
7016 i = iflist;
7017 while (i) {
7018 if (thispass != lastpass) {
7019 if (!found && ((i == last) || ((i == iflist) && !last))) {
7020 last = i;
7021 if (last) {
7022 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
7023 (last->sig & __DAHDI_SIG_FXO)) {
7024 res = ast_app_has_voicemail(last->mailbox, NULL);
7025 if (last->msgstate != res) {
7026 int x;
7027 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
7028 x = DAHDI_FLUSH_BOTH;
7029 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
7030 if (res2)
7031 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
7032 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
7033 /* Turn on on hook transfer for 4 seconds */
7034 x = 4000;
7035 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
7036 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
7037 last->cidpos = 0;
7038 last->msgstate = res;
7039 last->onhooktime = thispass;
7041 found ++;
7044 last = last->next;
7048 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
7049 if (i->radio && !i->owner)
7051 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7052 if (res)
7054 if (option_debug)
7055 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
7056 /* Don't hold iflock while handling init events */
7057 ast_mutex_unlock(&iflock);
7058 handle_init_event(i, res);
7059 ast_mutex_lock(&iflock);
7061 i = i->next;
7062 continue;
7064 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
7065 if (pollres & POLLIN) {
7066 if (i->owner || i->subs[SUB_REAL].owner) {
7067 #ifdef HAVE_PRI
7068 if (!i->pri)
7069 #endif
7070 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
7071 i = i->next;
7072 continue;
7074 if (!i->cidspill) {
7075 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
7076 i = i->next;
7077 continue;
7079 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
7080 if (res > 0) {
7081 /* We read some number of bytes. Write an equal amount of data */
7082 if (res > i->cidlen - i->cidpos)
7083 res = i->cidlen - i->cidpos;
7084 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
7085 if (res2 > 0) {
7086 i->cidpos += res2;
7087 if (i->cidpos >= i->cidlen) {
7088 free(i->cidspill);
7089 i->cidspill = 0;
7090 i->cidpos = 0;
7091 i->cidlen = 0;
7093 } else {
7094 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
7095 i->msgstate = -1;
7097 } else {
7098 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
7101 if (pollres & POLLPRI) {
7102 if (i->owner || i->subs[SUB_REAL].owner) {
7103 #ifdef HAVE_PRI
7104 if (!i->pri)
7105 #endif
7106 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
7107 i = i->next;
7108 continue;
7110 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7111 if (option_debug)
7112 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
7113 /* Don't hold iflock while handling init events */
7114 ast_mutex_unlock(&iflock);
7115 handle_init_event(i, res);
7116 ast_mutex_lock(&iflock);
7119 i=i->next;
7121 ast_mutex_unlock(&iflock);
7123 /* Never reached */
7124 return NULL;
7128 static int restart_monitor(void)
7130 pthread_attr_t attr;
7131 pthread_attr_init(&attr);
7132 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7133 /* If we're supposed to be stopped -- stay stopped */
7134 if (monitor_thread == AST_PTHREADT_STOP)
7135 return 0;
7136 ast_mutex_lock(&monlock);
7137 if (monitor_thread == pthread_self()) {
7138 ast_mutex_unlock(&monlock);
7139 ast_log(LOG_WARNING, "Cannot kill myself\n");
7140 return -1;
7142 if (monitor_thread != AST_PTHREADT_NULL) {
7143 /* Wake up the thread */
7144 pthread_kill(monitor_thread, SIGURG);
7145 } else {
7146 /* Start a new monitor */
7147 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7148 ast_mutex_unlock(&monlock);
7149 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7150 pthread_attr_destroy(&attr);
7151 return -1;
7154 ast_mutex_unlock(&monlock);
7155 pthread_attr_destroy(&attr);
7156 return 0;
7159 #ifdef HAVE_PRI
7160 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
7162 int x;
7163 int trunkgroup;
7164 /* Get appropriate trunk group if there is one */
7165 trunkgroup = pris[*span].mastertrunkgroup;
7166 if (trunkgroup) {
7167 /* Select a specific trunk group */
7168 for (x = 0; x < NUM_SPANS; x++) {
7169 if (pris[x].trunkgroup == trunkgroup) {
7170 *span = x;
7171 return 0;
7174 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7175 *span = -1;
7176 } else {
7177 if (pris[*span].trunkgroup) {
7178 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7179 *span = -1;
7180 } else if (pris[*span].mastertrunkgroup) {
7181 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7182 *span = -1;
7183 } else {
7184 if (si->totalchans == 31) {
7185 /* E1 */
7186 pris[*span].dchannels[0] = 16 + offset;
7187 } else if (si->totalchans == 24) {
7188 /* T1 or J1 */
7189 pris[*span].dchannels[0] = 24 + offset;
7190 } else if (si->totalchans == 3) {
7191 /* BRI */
7192 pris[*span].dchannels[0] = 3 + offset;
7193 } else {
7194 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);
7195 *span = -1;
7196 return 0;
7198 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7199 pris[*span].offset = offset;
7200 pris[*span].span = *span + 1;
7203 return 0;
7206 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7208 struct dahdi_spaninfo si;
7209 struct dahdi_params p;
7210 int fd;
7211 int span;
7212 int ospan=0;
7213 int x,y;
7214 for (x = 0; x < NUM_SPANS; x++) {
7215 if (pris[x].trunkgroup == trunkgroup) {
7216 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7217 return -1;
7220 for (y = 0; y < NUM_DCHANS; y++) {
7221 if (!channels[y])
7222 break;
7223 memset(&si, 0, sizeof(si));
7224 memset(&p, 0, sizeof(p));
7225 #ifdef HAVE_ZAPTEL
7226 fd = open("/dev/zap/channel", O_RDWR);
7227 #else
7228 fd = open("/dev/dahdi/channel", O_RDWR);
7229 #endif
7230 if (fd < 0) {
7231 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7232 return -1;
7234 x = channels[y];
7235 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7236 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7237 close(fd);
7238 return -1;
7240 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7241 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7242 return -1;
7244 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7245 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7246 close(fd);
7247 return -1;
7249 span = p.spanno - 1;
7250 if (pris[span].trunkgroup) {
7251 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7252 close(fd);
7253 return -1;
7255 if (pris[span].pvts[0]) {
7256 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7257 close(fd);
7258 return -1;
7260 if (!y) {
7261 pris[span].trunkgroup = trunkgroup;
7262 pris[span].offset = channels[y] - p.chanpos;
7263 ospan = span;
7265 pris[ospan].dchannels[y] = channels[y];
7266 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7267 pris[span].span = span + 1;
7268 close(fd);
7270 return 0;
7273 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7275 if (pris[span].mastertrunkgroup) {
7276 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);
7277 return -1;
7279 pris[span].mastertrunkgroup = trunkgroup;
7280 pris[span].prilogicalspan = logicalspan;
7281 return 0;
7284 #endif
7286 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7288 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7289 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7290 char fn[80];
7291 #if 1
7292 struct dahdi_bufferinfo bi;
7293 #endif
7294 int res;
7295 int span=0;
7296 int here = 0;
7297 int x;
7298 struct dahdi_pvt **wlist;
7299 struct dahdi_pvt **wend;
7300 struct dahdi_params p;
7302 wlist = &iflist;
7303 wend = &ifend;
7305 #ifdef HAVE_PRI
7306 if (pri) {
7307 wlist = &pri->crvs;
7308 wend = &pri->crvend;
7310 #endif
7312 tmp2 = *wlist;
7313 prev = NULL;
7315 while (tmp2) {
7316 if (!tmp2->destroy) {
7317 if (tmp2->channel == channel) {
7318 tmp = tmp2;
7319 here = 1;
7320 break;
7322 if (tmp2->channel > channel) {
7323 break;
7326 prev = tmp2;
7327 tmp2 = tmp2->next;
7330 if (!here && reloading != 1) {
7331 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7332 if (tmp)
7333 free(tmp);
7334 return NULL;
7336 ast_mutex_init(&tmp->lock);
7337 ifcount++;
7338 for (x = 0; x < 3; x++)
7339 tmp->subs[x].dfd = -1;
7340 tmp->channel = channel;
7343 if (tmp) {
7344 int chan_sig = conf->chan.sig;
7345 if (!here) {
7346 if ((channel != CHAN_PSEUDO) && !pri) {
7347 int count = 0;
7348 snprintf(fn, sizeof(fn), "%d", channel);
7349 /* Open non-blocking */
7350 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7351 while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2 && count < 1000) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
7352 usleep(1);
7353 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7354 count++;
7356 /* Allocate a DAHDI structure */
7357 if (tmp->subs[SUB_REAL].dfd < 0) {
7358 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);
7359 destroy_dahdi_pvt(&tmp);
7360 return NULL;
7362 memset(&p, 0, sizeof(p));
7363 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7364 if (res < 0) {
7365 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7366 destroy_dahdi_pvt(&tmp);
7367 return NULL;
7369 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7370 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));
7371 destroy_dahdi_pvt(&tmp);
7372 return NULL;
7374 tmp->law = p.curlaw;
7375 tmp->span = p.spanno;
7376 span = p.spanno - 1;
7377 } else {
7378 if (channel == CHAN_PSEUDO)
7379 chan_sig = 0;
7380 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7381 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7382 return NULL;
7385 #ifdef HAVE_PRI
7386 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7387 int offset;
7388 int myswitchtype;
7389 int matchesdchan;
7390 int x,y;
7391 offset = 0;
7392 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7393 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7394 destroy_dahdi_pvt(&tmp);
7395 return NULL;
7397 if (span >= NUM_SPANS) {
7398 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7399 destroy_dahdi_pvt(&tmp);
7400 return NULL;
7401 } else {
7402 struct dahdi_spaninfo si;
7403 si.spanno = 0;
7404 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7405 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7406 destroy_dahdi_pvt(&tmp);
7407 return NULL;
7409 /* Store the logical span first based upon the real span */
7410 tmp->logicalspan = pris[span].prilogicalspan;
7411 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7412 if (span < 0) {
7413 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7414 destroy_dahdi_pvt(&tmp);
7415 return NULL;
7417 if (chan_sig == SIG_PRI)
7418 myswitchtype = conf->pri.switchtype;
7419 else
7420 myswitchtype = PRI_SWITCH_GR303_TMC;
7421 /* Make sure this isn't a d-channel */
7422 matchesdchan=0;
7423 for (x = 0; x < NUM_SPANS; x++) {
7424 for (y = 0; y < NUM_DCHANS; y++) {
7425 if (pris[x].dchannels[y] == tmp->channel) {
7426 matchesdchan = 1;
7427 break;
7431 offset = p.chanpos;
7432 if (!matchesdchan) {
7433 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7434 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7435 destroy_dahdi_pvt(&tmp);
7436 return NULL;
7438 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7439 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7440 destroy_dahdi_pvt(&tmp);
7441 return NULL;
7443 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7444 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7445 destroy_dahdi_pvt(&tmp);
7446 return NULL;
7448 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7449 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7450 destroy_dahdi_pvt(&tmp);
7451 return NULL;
7453 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7454 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7455 destroy_dahdi_pvt(&tmp);
7456 return NULL;
7458 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7459 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7460 destroy_dahdi_pvt(&tmp);
7461 return NULL;
7463 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7464 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7465 destroy_dahdi_pvt(&tmp);
7466 return NULL;
7468 if (pris[span].numchans >= MAX_CHANNELS) {
7469 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7470 pris[span].trunkgroup);
7471 destroy_dahdi_pvt(&tmp);
7472 return NULL;
7474 pris[span].nodetype = conf->pri.nodetype;
7475 pris[span].switchtype = myswitchtype;
7476 pris[span].nsf = conf->pri.nsf;
7477 pris[span].dialplan = conf->pri.dialplan;
7478 pris[span].localdialplan = conf->pri.localdialplan;
7479 pris[span].pvts[pris[span].numchans++] = tmp;
7480 pris[span].minunused = conf->pri.minunused;
7481 pris[span].minidle = conf->pri.minidle;
7482 pris[span].overlapdial = conf->pri.overlapdial;
7483 #ifdef HAVE_PRI_INBANDDISCONNECT
7484 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
7485 #endif
7486 pris[span].facilityenable = conf->pri.facilityenable;
7487 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7488 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7489 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7490 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7491 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7492 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7493 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7494 pris[span].resetinterval = conf->pri.resetinterval;
7496 tmp->pri = &pris[span];
7497 tmp->prioffset = offset;
7498 tmp->call = NULL;
7499 } else {
7500 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7501 destroy_dahdi_pvt(&tmp);
7502 return NULL;
7505 } else {
7506 tmp->prioffset = 0;
7508 #endif
7509 } else {
7510 chan_sig = tmp->sig;
7511 memset(&p, 0, sizeof(p));
7512 if (tmp->subs[SUB_REAL].dfd > -1)
7513 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7515 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7516 switch (chan_sig) {
7517 case SIG_FXSKS:
7518 case SIG_FXSLS:
7519 case SIG_EM:
7520 case SIG_EM_E1:
7521 case SIG_EMWINK:
7522 case SIG_FEATD:
7523 case SIG_FEATDMF:
7524 case SIG_FEATDMF_TA:
7525 case SIG_FEATB:
7526 case SIG_E911:
7527 case SIG_SF:
7528 case SIG_SFWINK:
7529 case SIG_FGC_CAMA:
7530 case SIG_FGC_CAMAMF:
7531 case SIG_SF_FEATD:
7532 case SIG_SF_FEATDMF:
7533 case SIG_SF_FEATB:
7534 p.starttime = 250;
7535 break;
7538 if (tmp->radio) {
7539 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7540 p.channo = channel;
7541 p.rxwinktime = 1;
7542 p.rxflashtime = 1;
7543 p.starttime = 1;
7544 p.debouncetime = 5;
7546 if (!tmp->radio) {
7547 p.channo = channel;
7548 /* Override timing settings based on config file */
7549 if (conf->timing.prewinktime >= 0)
7550 p.prewinktime = conf->timing.prewinktime;
7551 if (conf->timing.preflashtime >= 0)
7552 p.preflashtime = conf->timing.preflashtime;
7553 if (conf->timing.winktime >= 0)
7554 p.winktime = conf->timing.winktime;
7555 if (conf->timing.flashtime >= 0)
7556 p.flashtime = conf->timing.flashtime;
7557 if (conf->timing.starttime >= 0)
7558 p.starttime = conf->timing.starttime;
7559 if (conf->timing.rxwinktime >= 0)
7560 p.rxwinktime = conf->timing.rxwinktime;
7561 if (conf->timing.rxflashtime >= 0)
7562 p.rxflashtime = conf->timing.rxflashtime;
7563 if (conf->timing.debouncetime >= 0)
7564 p.debouncetime = conf->timing.debouncetime;
7567 /* dont set parms on a pseudo-channel (or CRV) */
7568 if (tmp->subs[SUB_REAL].dfd >= 0)
7570 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7571 if (res < 0) {
7572 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7573 destroy_dahdi_pvt(&tmp);
7574 return NULL;
7577 #if 1
7578 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7579 memset(&bi, 0, sizeof(bi));
7580 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7581 if (!res) {
7582 bi.txbufpolicy = conf->chan.buf_policy;
7583 bi.rxbufpolicy = conf->chan.buf_policy;
7584 bi.numbufs = conf->chan.buf_no;
7585 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7586 if (res < 0) {
7587 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7589 } else
7590 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7592 #endif
7593 tmp->immediate = conf->chan.immediate;
7594 tmp->transfertobusy = conf->chan.transfertobusy;
7595 tmp->sig = chan_sig;
7596 tmp->outsigmod = conf->chan.outsigmod;
7597 tmp->ringt_base = ringt_base;
7598 tmp->firstradio = 0;
7599 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7600 tmp->permcallwaiting = conf->chan.callwaiting;
7601 else
7602 tmp->permcallwaiting = 0;
7603 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7604 tmp->destroy = 0;
7605 tmp->drings = drings;
7606 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7607 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7608 tmp->threewaycalling = conf->chan.threewaycalling;
7609 tmp->adsi = conf->chan.adsi;
7610 tmp->use_smdi = conf->chan.use_smdi;
7611 tmp->permhidecallerid = conf->chan.hidecallerid;
7612 tmp->callreturn = conf->chan.callreturn;
7613 tmp->echocancel = conf->chan.echocancel;
7614 tmp->echotraining = conf->chan.echotraining;
7615 tmp->pulse = conf->chan.pulse;
7616 if (tmp->echocancel)
7617 tmp->echocanbridged = conf->chan.echocanbridged;
7618 else {
7619 if (conf->chan.echocanbridged)
7620 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7621 tmp->echocanbridged = 0;
7623 tmp->busydetect = conf->chan.busydetect;
7624 tmp->busycount = conf->chan.busycount;
7625 tmp->busy_tonelength = conf->chan.busy_tonelength;
7626 tmp->busy_quietlength = conf->chan.busy_quietlength;
7627 tmp->callprogress = conf->chan.callprogress;
7628 tmp->cancallforward = conf->chan.cancallforward;
7629 tmp->dtmfrelax = conf->chan.dtmfrelax;
7630 tmp->callwaiting = tmp->permcallwaiting;
7631 tmp->hidecallerid = tmp->permhidecallerid;
7632 tmp->channel = channel;
7633 tmp->stripmsd = conf->chan.stripmsd;
7634 tmp->use_callerid = conf->chan.use_callerid;
7635 tmp->cid_signalling = conf->chan.cid_signalling;
7636 tmp->cid_start = conf->chan.cid_start;
7637 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7638 tmp->restrictcid = conf->chan.restrictcid;
7639 tmp->use_callingpres = conf->chan.use_callingpres;
7640 tmp->priindication_oob = conf->chan.priindication_oob;
7641 tmp->priexclusive = conf->chan.priexclusive;
7642 if (tmp->usedistinctiveringdetection) {
7643 if (!tmp->use_callerid) {
7644 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7645 tmp->use_callerid = 1;
7649 if (tmp->cid_signalling == CID_SIG_SMDI) {
7650 if (!tmp->use_smdi) {
7651 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7652 tmp->use_smdi = 1;
7655 if (tmp->use_smdi) {
7656 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7657 if (!(tmp->smdi_iface)) {
7658 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7659 tmp->use_smdi = 0;
7663 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7664 tmp->amaflags = conf->chan.amaflags;
7665 if (!here) {
7666 tmp->confno = -1;
7667 tmp->propconfno = -1;
7669 tmp->canpark = conf->chan.canpark;
7670 tmp->transfer = conf->chan.transfer;
7671 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7672 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7673 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7674 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7675 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7676 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7677 tmp->cid_ton = 0;
7678 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7679 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7680 tmp->msgstate = -1;
7681 tmp->group = conf->chan.group;
7682 tmp->callgroup = conf->chan.callgroup;
7683 tmp->pickupgroup= conf->chan.pickupgroup;
7684 tmp->rxgain = conf->chan.rxgain;
7685 tmp->txgain = conf->chan.txgain;
7686 tmp->tonezone = conf->chan.tonezone;
7687 tmp->onhooktime = time(NULL);
7688 if (tmp->subs[SUB_REAL].dfd > -1) {
7689 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7690 if (tmp->dsp)
7691 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7692 update_conf(tmp);
7693 if (!here) {
7694 if (chan_sig != SIG_PRI)
7695 /* Hang it up to be sure it's good */
7696 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7698 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7699 #ifdef HAVE_PRI
7700 /* the dchannel is down so put the channel in alarm */
7701 if (tmp->pri && !pri_is_up(tmp->pri)) {
7702 tmp->inalarm = 1;
7704 #endif
7705 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
7706 tmp->inalarm = 1;
7707 handle_alarms(tmp, res);
7708 } else {
7709 /* yes, this looks strange... the unknown_alarm flag is only used to
7710 control whether an 'alarm cleared' message gets generated when we
7711 get an indication that the channel is no longer in alarm status.
7712 however, the channel *could* be in an alarm status that we aren't
7713 aware of (since get_alarms() only reports span alarms, not channel
7714 alarms). setting this flag will cause any potential 'alarm cleared'
7715 message to be suppressed, but if a real alarm occurs before that
7716 happens, this flag will get cleared by it and the situation will
7717 be normal.
7719 tmp->unknown_alarm = 1;
7723 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
7724 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
7725 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
7726 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
7729 if (tmp && !here) {
7730 /* nothing on the iflist */
7731 if (!*wlist) {
7732 *wlist = tmp;
7733 tmp->prev = NULL;
7734 tmp->next = NULL;
7735 *wend = tmp;
7736 } else {
7737 /* at least one member on the iflist */
7738 struct dahdi_pvt *working = *wlist;
7740 /* check if we maybe have to put it on the begining */
7741 if (working->channel > tmp->channel) {
7742 tmp->next = *wlist;
7743 tmp->prev = NULL;
7744 (*wlist)->prev = tmp;
7745 *wlist = tmp;
7746 } else {
7747 /* go through all the members and put the member in the right place */
7748 while (working) {
7749 /* in the middle */
7750 if (working->next) {
7751 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
7752 tmp->next = working->next;
7753 tmp->prev = working;
7754 working->next->prev = tmp;
7755 working->next = tmp;
7756 break;
7758 } else {
7759 /* the last */
7760 if (working->channel < tmp->channel) {
7761 working->next = tmp;
7762 tmp->next = NULL;
7763 tmp->prev = working;
7764 *wend = tmp;
7765 break;
7768 working = working->next;
7773 return tmp;
7776 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
7778 int res;
7779 struct dahdi_params par;
7781 /* First, check group matching */
7782 if (groupmatch) {
7783 if ((p->group & groupmatch) != groupmatch)
7784 return 0;
7785 *groupmatched = 1;
7787 /* Check to see if we have a channel match */
7788 if (channelmatch != -1) {
7789 if (p->channel != channelmatch)
7790 return 0;
7791 *channelmatched = 1;
7793 /* We're at least busy at this point */
7794 if (busy) {
7795 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
7796 *busy = 1;
7798 /* If do not disturb, definitely not */
7799 if (p->dnd)
7800 return 0;
7801 /* If guard time, definitely not */
7802 if (p->guardtime && (time(NULL) < p->guardtime))
7803 return 0;
7805 /* If no owner definitely available */
7806 if (!p->owner) {
7807 #ifdef HAVE_PRI
7808 /* Trust PRI */
7809 if (p->pri) {
7810 if (p->resetting || p->call)
7811 return 0;
7812 else
7813 return 1;
7815 #endif
7816 if (!(p->radio || (p->oprmode < 0)))
7818 if (!p->sig || (p->sig == SIG_FXSLS))
7819 return 1;
7820 /* Check hook state */
7821 if (p->subs[SUB_REAL].dfd > -1)
7822 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
7823 else {
7824 /* Assume not off hook on CVRS */
7825 res = 0;
7826 par.rxisoffhook = 0;
7828 if (res) {
7829 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
7830 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
7831 /* When "onhook" that means no battery on the line, and thus
7832 it is out of service..., if it's on a TDM card... If it's a channel
7833 bank, there is no telling... */
7834 if (par.rxbits > -1)
7835 return 1;
7836 if (par.rxisoffhook)
7837 return 1;
7838 else
7839 #ifdef DAHDI_CHECK_HOOKSTATE
7840 return 0;
7841 #else
7842 return 1;
7843 #endif
7844 } else if (par.rxisoffhook) {
7845 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
7846 /* Not available when the other end is off hook */
7847 return 0;
7850 return 1;
7853 /* If it's not an FXO, forget about call wait */
7854 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
7855 return 0;
7857 if (!p->callwaiting) {
7858 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
7859 return 0;
7862 if (p->subs[SUB_CALLWAIT].dfd > -1) {
7863 /* If there is already a call waiting call, then we can't take a second one */
7864 return 0;
7867 if ((p->owner->_state != AST_STATE_UP) &&
7868 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
7869 /* If the current call is not up, then don't allow the call */
7870 return 0;
7872 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
7873 /* Can't take a call wait when the three way calling hasn't been merged yet. */
7874 return 0;
7876 /* We're cool */
7877 return 1;
7880 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
7882 struct dahdi_pvt *p;
7883 struct dahdi_bufferinfo bi;
7884 int res;
7886 if ((p = ast_malloc(sizeof(*p)))) {
7887 memcpy(p, src, sizeof(struct dahdi_pvt));
7888 ast_mutex_init(&p->lock);
7889 #ifdef HAVE_ZAPTEL
7890 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
7891 #else
7892 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
7893 #endif
7894 /* Allocate a DAHDI structure */
7895 if (p->subs[SUB_REAL].dfd < 0) {
7896 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
7897 destroy_dahdi_pvt(&p);
7898 return NULL;
7900 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7901 if (!res) {
7902 bi.txbufpolicy = p->buf_policy;
7903 bi.rxbufpolicy = p->buf_policy;
7904 bi.numbufs = p->buf_no;
7905 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7906 if (res < 0) {
7907 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
7909 } else
7910 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
7912 p->destroy = 1;
7913 p->next = iflist;
7914 p->prev = NULL;
7915 iflist = p;
7916 if (iflist->next)
7917 iflist->next->prev = p;
7918 return p;
7922 #ifdef HAVE_PRI
7923 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
7925 int x;
7926 if (backwards)
7927 x = pri->numchans;
7928 else
7929 x = 0;
7930 for (;;) {
7931 if (backwards && (x < 0))
7932 break;
7933 if (!backwards && (x >= pri->numchans))
7934 break;
7935 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
7936 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
7937 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
7938 return x;
7940 if (backwards)
7941 x--;
7942 else
7943 x++;
7945 return -1;
7947 #endif
7949 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
7951 ast_group_t groupmatch = 0;
7952 int channelmatch = -1;
7953 int roundrobin = 0;
7954 int callwait = 0;
7955 int busy = 0;
7956 struct dahdi_pvt *p;
7957 struct ast_channel *tmp = NULL;
7958 char *dest=NULL;
7959 int x;
7960 char *s;
7961 char opt=0;
7962 int res=0, y=0;
7963 int backwards = 0;
7964 #ifdef HAVE_PRI
7965 int crv;
7966 int bearer = -1;
7967 int trunkgroup;
7968 struct dahdi_pri *pri=NULL;
7969 #endif
7970 struct dahdi_pvt *exit, *start, *end;
7971 ast_mutex_t *lock;
7972 int channelmatched = 0;
7973 int groupmatched = 0;
7975 /* Assume we're locking the iflock */
7976 lock = &iflock;
7977 start = iflist;
7978 end = ifend;
7979 if (data) {
7980 dest = ast_strdupa((char *)data);
7981 } else {
7982 ast_log(LOG_WARNING, "Channel requested with no data\n");
7983 return NULL;
7985 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
7986 /* Retrieve the group number */
7987 char *stringp=NULL;
7988 stringp=dest + 1;
7989 s = strsep(&stringp, "/");
7990 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
7991 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
7992 return NULL;
7994 groupmatch = ((ast_group_t) 1 << x);
7995 if (toupper(dest[0]) == 'G') {
7996 if (dest[0] == 'G') {
7997 backwards = 1;
7998 p = ifend;
7999 } else
8000 p = iflist;
8001 } else {
8002 if (dest[0] == 'R') {
8003 backwards = 1;
8004 p = round_robin[x]?round_robin[x]->prev:ifend;
8005 if (!p)
8006 p = ifend;
8007 } else {
8008 p = round_robin[x]?round_robin[x]->next:iflist;
8009 if (!p)
8010 p = iflist;
8012 roundrobin = 1;
8014 } else {
8015 char *stringp=NULL;
8016 stringp=dest;
8017 s = strsep(&stringp, "/");
8018 p = iflist;
8019 if (!strcasecmp(s, "pseudo")) {
8020 /* Special case for pseudo */
8021 x = CHAN_PSEUDO;
8022 channelmatch = x;
8024 #ifdef HAVE_PRI
8025 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
8026 if ((trunkgroup < 1) || (crv < 1)) {
8027 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
8028 return NULL;
8030 res--;
8031 for (x = 0; x < NUM_SPANS; x++) {
8032 if (pris[x].trunkgroup == trunkgroup) {
8033 pri = pris + x;
8034 lock = &pri->lock;
8035 start = pri->crvs;
8036 end = pri->crvend;
8037 break;
8040 if (!pri) {
8041 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
8042 return NULL;
8044 channelmatch = crv;
8045 p = pris[x].crvs;
8047 #endif
8048 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
8049 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
8050 return NULL;
8051 } else {
8052 channelmatch = x;
8055 /* Search for an unowned channel */
8056 ast_mutex_lock(lock);
8057 exit = p;
8058 while (p && !tmp) {
8059 if (roundrobin)
8060 round_robin[x] = p;
8061 #if 0
8062 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
8063 #endif
8065 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
8066 if (option_debug)
8067 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
8068 if (p->inalarm)
8069 goto next;
8071 callwait = (p->owner != NULL);
8072 #ifdef HAVE_PRI
8073 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
8074 if (p->sig != SIG_FXSKS) {
8075 /* Gotta find an actual channel to use for this
8076 CRV if this isn't a callwait */
8077 bearer = pri_find_empty_chan(pri, 0);
8078 if (bearer < 0) {
8079 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
8080 p = NULL;
8081 break;
8083 pri_assign_bearer(p, pri, pri->pvts[bearer]);
8084 } else {
8085 if (alloc_sub(p, 0)) {
8086 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
8087 p = NULL;
8088 break;
8089 } else
8090 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
8091 p->pri = pri;
8094 #endif
8095 if (p->channel == CHAN_PSEUDO) {
8096 p = chandup(p);
8097 if (!p) {
8098 break;
8101 if (p->owner) {
8102 if (alloc_sub(p, SUB_CALLWAIT)) {
8103 p = NULL;
8104 break;
8107 p->outgoing = 1;
8108 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
8109 #ifdef HAVE_PRI
8110 if (p->bearer) {
8111 /* Log owner to bearer channel, too */
8112 p->bearer->owner = tmp;
8114 #endif
8115 /* Make special notes */
8116 if (res > 1) {
8117 if (opt == 'c') {
8118 /* Confirm answer */
8119 p->confirmanswer = 1;
8120 } else if (opt == 'r') {
8121 /* Distinctive ring */
8122 if (res < 3)
8123 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
8124 else
8125 p->distinctivering = y;
8126 } else if (opt == 'd') {
8127 /* If this is an ISDN call, make it digital */
8128 p->digital = 1;
8129 if (tmp)
8130 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
8131 } else {
8132 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
8135 /* Note if the call is a call waiting call */
8136 if (tmp && callwait)
8137 tmp->cdrflags |= AST_CDR_CALLWAIT;
8138 break;
8140 next:
8141 if (backwards) {
8142 p = p->prev;
8143 if (!p)
8144 p = end;
8145 } else {
8146 p = p->next;
8147 if (!p)
8148 p = start;
8150 /* stop when you roll to the one that we started from */
8151 if (p == exit)
8152 break;
8154 ast_mutex_unlock(lock);
8155 restart_monitor();
8156 if (callwait)
8157 *cause = AST_CAUSE_BUSY;
8158 else if (!tmp) {
8159 if (channelmatched) {
8160 if (busy)
8161 *cause = AST_CAUSE_BUSY;
8162 } else if (groupmatched) {
8163 *cause = AST_CAUSE_CONGESTION;
8167 return tmp;
8171 #ifdef HAVE_PRI
8172 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8174 struct dahdi_pvt *p;
8175 p = pri->crvs;
8176 while (p) {
8177 if (p->channel == crv)
8178 return p;
8179 p = p->next;
8181 return NULL;
8185 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8187 int x;
8188 int span = PRI_SPAN(channel);
8189 int spanfd;
8190 struct dahdi_params param;
8191 int principle = -1;
8192 int explicit = PRI_EXPLICIT(channel);
8193 channel = PRI_CHANNEL(channel);
8195 if (!explicit) {
8196 spanfd = pri_active_dchan_fd(pri);
8197 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8198 return -1;
8199 span = pris[param.spanno - 1].prilogicalspan;
8202 for (x = 0; x < pri->numchans; x++) {
8203 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8204 principle = x;
8205 break;
8209 return principle;
8212 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8214 int x;
8215 struct dahdi_pvt *crv;
8216 if (!c) {
8217 if (principle < 0)
8218 return -1;
8219 return principle;
8221 if ((principle > -1) &&
8222 (principle < pri->numchans) &&
8223 (pri->pvts[principle]) &&
8224 (pri->pvts[principle]->call == c))
8225 return principle;
8226 /* First, check for other bearers */
8227 for (x = 0; x < pri->numchans; x++) {
8228 if (!pri->pvts[x])
8229 continue;
8230 if (pri->pvts[x]->call == c) {
8231 /* Found our call */
8232 if (principle != x) {
8233 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8235 if (option_verbose > 2)
8236 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8237 old->channel, new->channel);
8238 if (new->owner) {
8239 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8240 old->channel, new->channel, new->channel);
8241 return -1;
8243 /* Fix it all up now */
8244 new->owner = old->owner;
8245 old->owner = NULL;
8246 if (new->owner) {
8247 ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
8248 new->owner->tech_pvt = new;
8249 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8250 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8251 old->subs[SUB_REAL].owner = NULL;
8252 } else
8253 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);
8254 new->call = old->call;
8255 old->call = NULL;
8257 /* Copy any DSP that may be present */
8258 new->dsp = old->dsp;
8259 new->dsp_features = old->dsp_features;
8260 old->dsp = NULL;
8261 old->dsp_features = 0;
8263 return principle;
8266 /* Now check for a CRV with no bearer */
8267 crv = pri->crvs;
8268 while (crv) {
8269 if (crv->call == c) {
8270 /* This is our match... Perform some basic checks */
8271 if (crv->bearer)
8272 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8273 else if (pri->pvts[principle]->owner)
8274 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8275 else {
8276 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8277 wakeup the potential sleeper */
8278 dahdi_close_sub(crv, SUB_REAL);
8279 pri->pvts[principle]->call = crv->call;
8280 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8281 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8282 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8283 pri->trunkgroup, crv->channel);
8284 wakeup_sub(crv, SUB_REAL, pri);
8286 return principle;
8288 crv = crv->next;
8290 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8291 return -1;
8294 static void *do_idle_thread(void *vchan)
8296 struct ast_channel *chan = vchan;
8297 struct dahdi_pvt *pvt = chan->tech_pvt;
8298 struct ast_frame *f;
8299 char ex[80];
8300 /* Wait up to 30 seconds for an answer */
8301 int newms, ms = 30000;
8302 if (option_verbose > 2)
8303 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8304 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8305 if (ast_call(chan, ex, 0)) {
8306 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8307 ast_hangup(chan);
8308 return NULL;
8310 while ((newms = ast_waitfor(chan, ms)) > 0) {
8311 f = ast_read(chan);
8312 if (!f) {
8313 /* Got hangup */
8314 break;
8316 if (f->frametype == AST_FRAME_CONTROL) {
8317 switch (f->subclass) {
8318 case AST_CONTROL_ANSWER:
8319 /* Launch the PBX */
8320 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8321 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8322 chan->priority = 1;
8323 if (option_verbose > 3)
8324 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8325 ast_pbx_run(chan);
8326 /* It's already hungup, return immediately */
8327 return NULL;
8328 case AST_CONTROL_BUSY:
8329 if (option_verbose > 3)
8330 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8331 break;
8332 case AST_CONTROL_CONGESTION:
8333 if (option_verbose > 3)
8334 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8335 break;
8338 ast_frfree(f);
8339 ms = newms;
8341 /* Hangup the channel since nothing happend */
8342 ast_hangup(chan);
8343 return NULL;
8346 #ifndef PRI_RESTART
8347 #error "Upgrade your libpri"
8348 #endif
8349 static void dahdi_pri_message(struct pri *pri, char *s)
8351 int x, y;
8352 int dchan = -1, span = -1;
8353 int dchancount = 0;
8355 if (pri) {
8356 for (x = 0; x < NUM_SPANS; x++) {
8357 for (y = 0; y < NUM_DCHANS; y++) {
8358 if (pris[x].dchans[y])
8359 dchancount++;
8361 if (pris[x].dchans[y] == pri)
8362 dchan = y;
8364 if (dchan >= 0) {
8365 span = x;
8366 break;
8368 dchancount = 0;
8370 if ((dchan >= 0) && (span >= 0)) {
8371 if (dchancount > 1)
8372 ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
8373 else
8374 ast_verbose("%s", s);
8375 } else
8376 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8377 } else
8378 ast_verbose("%s", s);
8380 ast_mutex_lock(&pridebugfdlock);
8382 if (pridebugfd >= 0)
8383 write(pridebugfd, s, strlen(s));
8385 ast_mutex_unlock(&pridebugfdlock);
8388 static void dahdi_pri_error(struct pri *pri, char *s)
8390 int x, y;
8391 int dchan = -1, span = -1;
8392 int dchancount = 0;
8394 if (pri) {
8395 for (x = 0; x < NUM_SPANS; x++) {
8396 for (y = 0; y < NUM_DCHANS; y++) {
8397 if (pris[x].dchans[y])
8398 dchancount++;
8400 if (pris[x].dchans[y] == pri)
8401 dchan = y;
8403 if (dchan >= 0) {
8404 span = x;
8405 break;
8407 dchancount = 0;
8409 if ((dchan >= 0) && (span >= 0)) {
8410 if (dchancount > 1)
8411 ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
8412 else
8413 ast_log(LOG_ERROR, "%s", s);
8414 } else
8415 ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
8416 } else
8417 ast_log(LOG_ERROR, "%s", s);
8419 ast_mutex_lock(&pridebugfdlock);
8421 if (pridebugfd >= 0)
8422 write(pridebugfd, s, strlen(s));
8424 ast_mutex_unlock(&pridebugfdlock);
8427 static int pri_check_restart(struct dahdi_pri *pri)
8429 do {
8430 pri->resetpos++;
8431 } while ((pri->resetpos < pri->numchans) &&
8432 (!pri->pvts[pri->resetpos] ||
8433 pri->pvts[pri->resetpos]->call ||
8434 pri->pvts[pri->resetpos]->resetting));
8435 if (pri->resetpos < pri->numchans) {
8436 /* Mark the channel as resetting and restart it */
8437 pri->pvts[pri->resetpos]->resetting = 1;
8438 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8439 } else {
8440 pri->resetting = 0;
8441 time(&pri->lastreset);
8443 return 0;
8446 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
8448 int x;
8449 int redo;
8450 ast_mutex_unlock(&pri->lock);
8451 ast_mutex_lock(&p->lock);
8452 do {
8453 redo = 0;
8454 for (x = 0; x < 3; x++) {
8455 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
8456 redo++;
8457 DEADLOCK_AVOIDANCE(&p->lock);
8459 if (p->subs[x].owner) {
8460 ast_queue_hangup(p->subs[x].owner);
8461 ast_mutex_unlock(&p->subs[x].owner->lock);
8464 } while (redo);
8465 ast_mutex_unlock(&p->lock);
8466 ast_mutex_lock(&pri->lock);
8467 return 0;
8470 static char * redirectingreason2str(int redirectingreason)
8472 switch (redirectingreason) {
8473 case 0:
8474 return "UNKNOWN";
8475 case 1:
8476 return "BUSY";
8477 case 2:
8478 return "NO_REPLY";
8479 case 0xF:
8480 return "UNCONDITIONAL";
8481 default:
8482 return "NOREDIRECT";
8486 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
8488 switch (plan) {
8489 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
8490 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
8491 break;
8492 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
8493 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
8494 break;
8495 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
8496 snprintf(buf, size, "%s%s", pri->localprefix, number);
8497 break;
8498 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
8499 snprintf(buf, size, "%s%s", pri->privateprefix, number);
8500 break;
8501 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
8502 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
8503 break;
8504 default: /* other Q.931 dialplan => don't twiddle with callingnum */
8505 snprintf(buf, size, "%s", number);
8506 break;
8510 static int dahdi_setlaw(int dfd, int law)
8512 int res;
8513 res = ioctl(dfd, DAHDI_SETLAW, &law);
8514 if (res)
8515 return res;
8516 return 0;
8519 static void *pri_dchannel(void *vpri)
8521 struct dahdi_pri *pri = vpri;
8522 pri_event *e;
8523 struct pollfd fds[NUM_DCHANS];
8524 int res;
8525 int chanpos = 0;
8526 int x;
8527 int haveidles;
8528 int activeidles;
8529 int nextidle = -1;
8530 struct ast_channel *c;
8531 struct timeval tv, lowest, *next;
8532 struct timeval lastidle = { 0, 0 };
8533 int doidling=0;
8534 char *cc;
8535 char idlen[80];
8536 struct ast_channel *idle;
8537 pthread_t p;
8538 time_t t;
8539 int i, which=-1;
8540 int numdchans;
8541 int cause=0;
8542 struct dahdi_pvt *crv;
8543 pthread_t threadid;
8544 pthread_attr_t attr;
8545 char ani2str[6];
8546 char plancallingnum[256];
8547 char plancallingani[256];
8548 char calledtonstr[10];
8550 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
8552 gettimeofday(&lastidle, NULL);
8553 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
8554 /* Need to do idle dialing, check to be sure though */
8555 cc = strchr(pri->idleext, '@');
8556 if (cc) {
8557 *cc = '\0';
8558 cc++;
8559 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
8560 #if 0
8561 /* Extensions may not be loaded yet */
8562 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
8563 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
8564 else
8565 #endif
8566 doidling = 1;
8567 } else
8568 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
8570 for (;;) {
8571 for (i = 0; i < NUM_DCHANS; i++) {
8572 if (!pri->dchannels[i])
8573 break;
8574 fds[i].fd = pri->fds[i];
8575 fds[i].events = POLLIN | POLLPRI;
8576 fds[i].revents = 0;
8578 numdchans = i;
8579 time(&t);
8580 ast_mutex_lock(&pri->lock);
8581 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
8582 if (pri->resetting && pri_is_up(pri)) {
8583 if (pri->resetpos < 0)
8584 pri_check_restart(pri);
8585 } else {
8586 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
8587 pri->resetting = 1;
8588 pri->resetpos = -1;
8592 /* Look for any idle channels if appropriate */
8593 if (doidling && pri_is_up(pri)) {
8594 nextidle = -1;
8595 haveidles = 0;
8596 activeidles = 0;
8597 for (x = pri->numchans; x >= 0; x--) {
8598 if (pri->pvts[x] && !pri->pvts[x]->owner &&
8599 !pri->pvts[x]->call) {
8600 if (haveidles < pri->minunused) {
8601 haveidles++;
8602 } else if (!pri->pvts[x]->resetting) {
8603 nextidle = x;
8604 break;
8606 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
8607 activeidles++;
8609 if (nextidle > -1) {
8610 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
8611 /* Don't create a new idle call more than once per second */
8612 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
8613 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
8614 if (idle) {
8615 pri->pvts[nextidle]->isidlecall = 1;
8616 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
8617 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
8618 dahdi_hangup(idle);
8620 } else
8621 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
8622 gettimeofday(&lastidle, NULL);
8624 } else if ((haveidles < pri->minunused) &&
8625 (activeidles > pri->minidle)) {
8626 /* Mark something for hangup if there is something
8627 that can be hungup */
8628 for (x = pri->numchans; x >= 0; x--) {
8629 /* find a candidate channel */
8630 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
8631 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8632 haveidles++;
8633 /* Stop if we have enough idle channels or
8634 can't spare any more active idle ones */
8635 if ((haveidles >= pri->minunused) ||
8636 (activeidles <= pri->minidle))
8637 break;
8642 /* Start with reasonable max */
8643 lowest = ast_tv(60, 0);
8644 for (i = 0; i < NUM_DCHANS; i++) {
8645 /* Find lowest available d-channel */
8646 if (!pri->dchannels[i])
8647 break;
8648 if ((next = pri_schedule_next(pri->dchans[i]))) {
8649 /* We need relative time here */
8650 tv = ast_tvsub(*next, ast_tvnow());
8651 if (tv.tv_sec < 0) {
8652 tv = ast_tv(0,0);
8654 if (doidling || pri->resetting) {
8655 if (tv.tv_sec > 1) {
8656 tv = ast_tv(1, 0);
8658 } else {
8659 if (tv.tv_sec > 60) {
8660 tv = ast_tv(60, 0);
8663 } else if (doidling || pri->resetting) {
8664 /* Make sure we stop at least once per second if we're
8665 monitoring idle channels */
8666 tv = ast_tv(1,0);
8667 } else {
8668 /* Don't poll for more than 60 seconds */
8669 tv = ast_tv(60, 0);
8671 if (!i || ast_tvcmp(tv, lowest) < 0) {
8672 lowest = tv;
8675 ast_mutex_unlock(&pri->lock);
8677 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
8678 pthread_testcancel();
8679 e = NULL;
8680 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
8681 pthread_testcancel();
8682 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
8684 ast_mutex_lock(&pri->lock);
8685 if (!res) {
8686 for (which = 0; which < NUM_DCHANS; which++) {
8687 if (!pri->dchans[which])
8688 break;
8689 /* Just a timeout, run the scheduler */
8690 e = pri_schedule_run(pri->dchans[which]);
8691 if (e)
8692 break;
8694 } else if (res > -1) {
8695 for (which = 0; which < NUM_DCHANS; which++) {
8696 if (!pri->dchans[which])
8697 break;
8698 if (fds[which].revents & POLLPRI) {
8699 /* Check for an event */
8700 x = 0;
8701 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
8702 if (x)
8703 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);
8704 /* Keep track of alarm state */
8705 if (x == DAHDI_EVENT_ALARM) {
8706 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
8707 pri_find_dchan(pri);
8708 } else if (x == DAHDI_EVENT_NOALARM) {
8709 pri->dchanavail[which] |= DCHAN_NOTINALARM;
8710 pri_restart(pri->dchans[which]);
8713 if (option_debug)
8714 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
8715 } else if (fds[which].revents & POLLIN) {
8716 e = pri_check_event(pri->dchans[which]);
8718 if (e)
8719 break;
8721 } else if (errno != EINTR)
8722 ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
8724 if (e) {
8725 if (pri->debug)
8726 pri_dump_event(pri->dchans[which], e);
8728 if (e->e != PRI_EVENT_DCHAN_DOWN) {
8729 if (!(pri->dchanavail[which] & DCHAN_UP)) {
8730 if (option_verbose > 1)
8731 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
8733 pri->dchanavail[which] |= DCHAN_UP;
8734 } else {
8735 if (pri->dchanavail[which] & DCHAN_UP) {
8736 if (option_verbose > 1)
8737 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
8739 pri->dchanavail[which] &= ~DCHAN_UP;
8742 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
8743 /* Must be an NFAS group that has the secondary dchan active */
8744 pri->pri = pri->dchans[which];
8746 switch (e->e) {
8747 case PRI_EVENT_DCHAN_UP:
8748 if (!pri->pri) pri_find_dchan(pri);
8750 /* Note presense of D-channel */
8751 time(&pri->lastreset);
8753 /* Restart in 5 seconds */
8754 if (pri->resetinterval > -1) {
8755 pri->lastreset -= pri->resetinterval;
8756 pri->lastreset += 5;
8758 pri->resetting = 0;
8759 /* Take the channels from inalarm condition */
8760 for (i = 0; i < pri->numchans; i++)
8761 if (pri->pvts[i]) {
8762 pri->pvts[i]->inalarm = 0;
8764 break;
8765 case PRI_EVENT_DCHAN_DOWN:
8766 pri_find_dchan(pri);
8767 if (!pri_is_up(pri)) {
8768 pri->resetting = 0;
8769 /* Hangup active channels and put them in alarm mode */
8770 for (i = 0; i < pri->numchans; i++) {
8771 struct dahdi_pvt *p = pri->pvts[i];
8772 if (p) {
8773 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
8774 /* T309 is not enabled : hangup calls when alarm occurs */
8775 if (p->call) {
8776 if (p->pri && p->pri->pri) {
8777 pri_hangup(p->pri->pri, p->call, -1);
8778 pri_destroycall(p->pri->pri, p->call);
8779 p->call = NULL;
8780 } else
8781 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
8783 if (p->realcall) {
8784 pri_hangup_all(p->realcall, pri);
8785 } else if (p->owner)
8786 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8788 p->inalarm = 1;
8792 break;
8793 case PRI_EVENT_RESTART:
8794 if (e->restart.channel > -1) {
8795 chanpos = pri_find_principle(pri, e->restart.channel);
8796 if (chanpos < 0)
8797 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
8798 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8799 else {
8800 if (option_verbose > 2)
8801 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
8802 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
8803 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8804 if (pri->pvts[chanpos]->call) {
8805 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
8806 pri->pvts[chanpos]->call = NULL;
8808 /* Force soft hangup if appropriate */
8809 if (pri->pvts[chanpos]->realcall)
8810 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8811 else if (pri->pvts[chanpos]->owner)
8812 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8813 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8815 } else {
8816 if (option_verbose > 2)
8817 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
8818 for (x = 0; x < pri->numchans; x++)
8819 if (pri->pvts[x]) {
8820 ast_mutex_lock(&pri->pvts[x]->lock);
8821 if (pri->pvts[x]->call) {
8822 pri_destroycall(pri->pri, pri->pvts[x]->call);
8823 pri->pvts[x]->call = NULL;
8825 if (pri->pvts[chanpos]->realcall)
8826 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
8827 else if (pri->pvts[x]->owner)
8828 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8829 ast_mutex_unlock(&pri->pvts[x]->lock);
8832 break;
8833 case PRI_EVENT_KEYPAD_DIGIT:
8834 chanpos = pri_find_principle(pri, e->digit.channel);
8835 if (chanpos < 0) {
8836 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
8837 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
8838 } else {
8839 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
8840 if (chanpos > -1) {
8841 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8842 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
8843 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
8844 /* how to do that */
8845 int digitlen = strlen(e->digit.digits);
8846 char digit;
8847 int i;
8848 for (i = 0; i < digitlen; i++) {
8849 digit = e->digit.digits[i];
8851 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8852 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8856 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8859 break;
8861 case PRI_EVENT_INFO_RECEIVED:
8862 chanpos = pri_find_principle(pri, e->ring.channel);
8863 if (chanpos < 0) {
8864 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
8865 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8866 } else {
8867 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
8868 if (chanpos > -1) {
8869 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8870 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
8871 if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
8872 /* how to do that */
8873 int digitlen = strlen(e->ring.callednum);
8874 char digit;
8875 int i;
8876 for (i = 0; i < digitlen; i++) {
8877 digit = e->ring.callednum[i];
8879 struct ast_frame f = { AST_FRAME_DTMF, digit, };
8880 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
8884 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8887 break;
8888 case PRI_EVENT_RING:
8889 crv = NULL;
8890 if (e->ring.channel == -1)
8891 chanpos = pri_find_empty_chan(pri, 1);
8892 else
8893 chanpos = pri_find_principle(pri, e->ring.channel);
8894 /* if no channel specified find one empty */
8895 if (chanpos < 0) {
8896 ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
8897 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8898 } else {
8899 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8900 if (pri->pvts[chanpos]->owner) {
8901 if (pri->pvts[chanpos]->call == e->ring.call) {
8902 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
8903 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8904 break;
8905 } else {
8906 /* This is where we handle initial glare */
8907 ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiating channel.\n",
8908 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
8909 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8910 chanpos = -1;
8913 if (chanpos > -1)
8914 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8916 if ((chanpos < 0) && (e->ring.flexible))
8917 chanpos = pri_find_empty_chan(pri, 1);
8918 if (chanpos > -1) {
8919 ast_mutex_lock(&pri->pvts[chanpos]->lock);
8920 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
8921 /* Should be safe to lock CRV AFAIK while bearer is still locked */
8922 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
8923 if (crv)
8924 ast_mutex_lock(&crv->lock);
8925 if (!crv || crv->owner) {
8926 pri->pvts[chanpos]->call = NULL;
8927 if (crv) {
8928 if (crv->owner)
8929 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8930 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);
8931 } else
8932 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);
8933 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
8934 if (crv)
8935 ast_mutex_unlock(&crv->lock);
8936 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
8937 break;
8940 pri->pvts[chanpos]->call = e->ring.call;
8941 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
8942 if (pri->pvts[chanpos]->use_callerid) {
8943 ast_shrink_phone_number(plancallingnum);
8944 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
8945 #ifdef PRI_ANI
8946 if (!ast_strlen_zero(e->ring.callingani)) {
8947 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
8948 ast_shrink_phone_number(plancallingani);
8949 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
8950 } else {
8951 pri->pvts[chanpos]->cid_ani[0] = '\0';
8953 #endif
8954 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
8955 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
8956 } else {
8957 pri->pvts[chanpos]->cid_num[0] = '\0';
8958 pri->pvts[chanpos]->cid_ani[0] = '\0';
8959 pri->pvts[chanpos]->cid_name[0] = '\0';
8960 pri->pvts[chanpos]->cid_ton = 0;
8962 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
8963 e->ring.redirectingnum, e->ring.callingplanrdnis);
8964 /* If immediate=yes go to s|1 */
8965 if (pri->pvts[chanpos]->immediate) {
8966 if (option_verbose > 2)
8967 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
8968 pri->pvts[chanpos]->exten[0] = 's';
8969 pri->pvts[chanpos]->exten[1] = '\0';
8971 /* Get called number */
8972 else if (!ast_strlen_zero(e->ring.callednum)) {
8973 ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
8974 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8975 } else if (pri->overlapdial)
8976 pri->pvts[chanpos]->exten[0] = '\0';
8977 else {
8978 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
8979 pri->pvts[chanpos]->exten[0] = 's';
8980 pri->pvts[chanpos]->exten[1] = '\0';
8982 /* Set DNID on all incoming calls -- even immediate */
8983 if (!ast_strlen_zero(e->ring.callednum))
8984 ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
8985 /* No number yet, but received "sending complete"? */
8986 if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
8987 if (option_verbose > 2)
8988 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
8989 pri->pvts[chanpos]->exten[0] = 's';
8990 pri->pvts[chanpos]->exten[1] = '\0';
8992 /* Make sure extension exists (or in overlap dial mode, can exist) */
8993 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
8994 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
8995 /* Setup law */
8996 int law;
8997 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
8998 /* Set to audio mode at this point */
8999 law = 1;
9000 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
9001 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
9003 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
9004 law = DAHDI_LAW_ALAW;
9005 else
9006 law = DAHDI_LAW_MULAW;
9007 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
9008 if (res < 0)
9009 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
9010 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
9011 if (res < 0)
9012 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
9013 if (e->ring.complete || !pri->overlapdial) {
9014 /* Just announce proceeding */
9015 pri->pvts[chanpos]->proceeding = 1;
9016 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
9017 } else {
9018 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
9019 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9020 else
9021 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9023 /* Get the use_callingpres state */
9024 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
9026 /* Start PBX */
9027 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
9028 /* Release the PRI lock while we create the channel */
9029 ast_mutex_unlock(&pri->lock);
9030 if (crv) {
9031 /* Set bearer and such */
9032 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
9033 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9034 pri->pvts[chanpos]->owner = &inuse;
9035 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
9036 } else {
9037 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9040 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9042 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
9043 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
9045 if (e->ring.ani2 >= 0) {
9046 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
9047 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9050 #ifdef SUPPORT_USERUSER
9051 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9052 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9054 #endif
9056 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9057 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9058 if (e->ring.redirectingreason >= 0)
9059 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9061 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9062 ast_mutex_lock(&pri->lock);
9064 pthread_attr_init(&attr);
9065 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
9066 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
9067 if (option_verbose > 2)
9068 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
9069 plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
9070 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9071 } else {
9072 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9073 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9074 if (c)
9075 ast_hangup(c);
9076 else {
9077 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9078 pri->pvts[chanpos]->call = NULL;
9081 pthread_attr_destroy(&attr);
9082 } else {
9083 ast_mutex_unlock(&pri->lock);
9084 /* Release PRI lock while we create the channel */
9085 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
9086 if (c) {
9087 char calledtonstr[10];
9089 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9091 if (e->ring.ani2 >= 0) {
9092 snprintf(ani2str, 5, "%d", e->ring.ani2);
9093 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9096 #ifdef SUPPORT_USERUSER
9097 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9098 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9100 #endif
9102 if (e->ring.redirectingreason >= 0)
9103 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9105 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9106 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9108 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9109 ast_mutex_lock(&pri->lock);
9111 if (option_verbose > 2)
9112 ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
9113 plancallingnum, pri->pvts[chanpos]->exten,
9114 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9115 dahdi_enable_ec(pri->pvts[chanpos]);
9116 } else {
9118 ast_mutex_lock(&pri->lock);
9120 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9121 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9122 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9123 pri->pvts[chanpos]->call = NULL;
9126 } else {
9127 if (option_verbose > 2)
9128 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9129 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
9130 pri->pvts[chanpos]->prioffset, pri->span);
9131 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
9132 pri->pvts[chanpos]->call = NULL;
9133 pri->pvts[chanpos]->exten[0] = '\0';
9135 if (crv)
9136 ast_mutex_unlock(&crv->lock);
9137 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9138 } else {
9139 if (e->ring.flexible)
9140 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
9141 else
9142 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
9144 break;
9145 case PRI_EVENT_RINGING:
9146 chanpos = pri_find_principle(pri, e->ringing.channel);
9147 if (chanpos < 0) {
9148 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9149 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9150 } else {
9151 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9152 if (chanpos < 0) {
9153 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9154 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9155 } else {
9156 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9157 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9158 dahdi_enable_ec(pri->pvts[chanpos]);
9159 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9160 pri->pvts[chanpos]->alerting = 1;
9161 } else
9162 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9163 #ifdef PRI_PROGRESS_MASK
9164 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9165 #else
9166 if (e->ringing.progress == 8) {
9167 #endif
9168 /* Now we can do call progress detection */
9169 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9170 /* RINGING detection isn't required because we got ALERTING signal */
9171 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9172 pri->pvts[chanpos]->dsp_features = 0;
9176 #ifdef SUPPORT_USERUSER
9177 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9178 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9179 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9180 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9181 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9183 #endif
9185 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9188 break;
9189 case PRI_EVENT_PROGRESS:
9190 /* Get chan value if e->e is not PRI_EVNT_RINGING */
9191 chanpos = pri_find_principle(pri, e->proceeding.channel);
9192 if (chanpos > -1) {
9193 #ifdef PRI_PROGRESS_MASK
9194 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9195 #else
9196 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9197 #endif
9198 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9200 if (e->proceeding.cause > -1) {
9201 if (option_verbose > 2)
9202 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9204 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9205 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9206 if (pri->pvts[chanpos]->owner) {
9207 if (option_verbose > 2)
9208 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9210 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9211 f.subclass = AST_CONTROL_BUSY;
9216 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9217 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9218 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9219 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9220 #ifdef PRI_PROGRESS_MASK
9221 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9222 #else
9223 if (e->proceeding.progress == 8) {
9224 #endif
9225 /* Now we can do call progress detection */
9226 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9227 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9228 pri->pvts[chanpos]->dsp_features = 0;
9231 pri->pvts[chanpos]->progress = 1;
9232 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9235 break;
9236 case PRI_EVENT_PROCEEDING:
9237 chanpos = pri_find_principle(pri, e->proceeding.channel);
9238 if (chanpos > -1) {
9239 if (!pri->pvts[chanpos]->proceeding) {
9240 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
9242 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9243 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
9244 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9245 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9246 #ifdef PRI_PROGRESS_MASK
9247 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9248 #else
9249 if (e->proceeding.progress == 8) {
9250 #endif
9251 /* Now we can do call progress detection */
9252 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9253 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9254 pri->pvts[chanpos]->dsp_features = 0;
9256 /* Bring voice path up */
9257 f.subclass = AST_CONTROL_PROGRESS;
9258 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9260 pri->pvts[chanpos]->proceeding = 1;
9261 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9264 break;
9265 case PRI_EVENT_FACNAME:
9266 chanpos = pri_find_principle(pri, e->facname.channel);
9267 if (chanpos < 0) {
9268 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
9269 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9270 } else {
9271 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
9272 if (chanpos < 0) {
9273 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
9274 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
9275 } else {
9276 /* Re-use *69 field for PRI */
9277 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9278 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
9279 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
9280 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
9281 dahdi_enable_ec(pri->pvts[chanpos]);
9282 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9285 break;
9286 case PRI_EVENT_ANSWER:
9287 chanpos = pri_find_principle(pri, e->answer.channel);
9288 if (chanpos < 0) {
9289 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
9290 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9291 } else {
9292 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
9293 if (chanpos < 0) {
9294 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
9295 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
9296 } else {
9297 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9298 /* Now we can do call progress detection */
9300 /* We changed this so it turns on the DSP no matter what... progress or no progress.
9301 * By this time, we need DTMF detection and other features that were previously disabled
9302 * -- Matt F */
9303 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9304 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9305 pri->pvts[chanpos]->dsp_features = 0;
9307 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
9308 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
9309 x = DAHDI_START;
9310 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
9311 if (res < 0) {
9312 if (errno != EINPROGRESS) {
9313 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
9316 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9317 pri->pvts[chanpos]->dialing = 1;
9318 /* Send any "w" waited stuff */
9319 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
9320 if (res < 0) {
9321 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
9322 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9323 } else
9324 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
9325 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
9326 } else if (pri->pvts[chanpos]->confirmanswer) {
9327 ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
9328 } else {
9329 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
9330 /* Enable echo cancellation if it's not on already */
9331 dahdi_enable_ec(pri->pvts[chanpos]);
9334 #ifdef SUPPORT_USERUSER
9335 if (!ast_strlen_zero(e->answer.useruserinfo)) {
9336 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9337 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9338 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
9339 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9341 #endif
9343 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9346 break;
9347 case PRI_EVENT_HANGUP:
9348 chanpos = pri_find_principle(pri, e->hangup.channel);
9349 if (chanpos < 0) {
9350 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
9351 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9352 } else {
9353 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9354 if (chanpos > -1) {
9355 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9356 if (!pri->pvts[chanpos]->alreadyhungup) {
9357 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
9358 pri->pvts[chanpos]->alreadyhungup = 1;
9359 if (pri->pvts[chanpos]->realcall)
9360 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9361 else if (pri->pvts[chanpos]->owner) {
9362 /* Queue a BUSY instead of a hangup if our cause is appropriate */
9363 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9364 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9365 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9366 else {
9367 switch (e->hangup.cause) {
9368 case PRI_CAUSE_USER_BUSY:
9369 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9370 break;
9371 case PRI_CAUSE_CALL_REJECTED:
9372 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9373 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9374 case PRI_CAUSE_SWITCH_CONGESTION:
9375 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9376 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9377 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9378 break;
9379 default:
9380 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9384 if (option_verbose > 2)
9385 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
9386 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
9387 } else {
9388 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9389 pri->pvts[chanpos]->call = NULL;
9391 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9392 if (option_verbose > 2)
9393 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
9394 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9395 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9396 pri->pvts[chanpos]->resetting = 1;
9398 if (e->hangup.aoc_units > -1)
9399 if (option_verbose > 2)
9400 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9401 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9403 #ifdef SUPPORT_USERUSER
9404 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
9405 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9406 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9407 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9408 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9410 #endif
9412 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9413 } else {
9414 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
9415 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9418 break;
9419 #ifndef PRI_EVENT_HANGUP_REQ
9420 #error please update libpri
9421 #endif
9422 case PRI_EVENT_HANGUP_REQ:
9423 chanpos = pri_find_principle(pri, e->hangup.channel);
9424 if (chanpos < 0) {
9425 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
9426 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9427 } else {
9428 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9429 if (chanpos > -1) {
9430 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9431 if (pri->pvts[chanpos]->realcall)
9432 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9433 else if (pri->pvts[chanpos]->owner) {
9434 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
9435 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
9436 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9437 else {
9438 switch (e->hangup.cause) {
9439 case PRI_CAUSE_USER_BUSY:
9440 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
9441 break;
9442 case PRI_CAUSE_CALL_REJECTED:
9443 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
9444 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
9445 case PRI_CAUSE_SWITCH_CONGESTION:
9446 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
9447 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
9448 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
9449 break;
9450 default:
9451 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9454 if (option_verbose > 2)
9455 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);
9456 if (e->hangup.aoc_units > -1)
9457 if (option_verbose > 2)
9458 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
9459 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
9460 } else {
9461 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
9462 pri->pvts[chanpos]->call = NULL;
9464 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
9465 if (option_verbose > 2)
9466 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
9467 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9468 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
9469 pri->pvts[chanpos]->resetting = 1;
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);
9482 } else {
9483 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);
9486 break;
9487 case PRI_EVENT_HANGUP_ACK:
9488 chanpos = pri_find_principle(pri, e->hangup.channel);
9489 if (chanpos < 0) {
9490 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
9491 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
9492 } else {
9493 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
9494 if (chanpos > -1) {
9495 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9496 pri->pvts[chanpos]->call = NULL;
9497 pri->pvts[chanpos]->resetting = 0;
9498 if (pri->pvts[chanpos]->owner) {
9499 if (option_verbose > 2)
9500 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);
9503 #ifdef SUPPORT_USERUSER
9504 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
9505 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9506 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9507 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
9508 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9510 #endif
9512 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9515 break;
9516 case PRI_EVENT_CONFIG_ERR:
9517 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
9518 break;
9519 case PRI_EVENT_RESTART_ACK:
9520 chanpos = pri_find_principle(pri, e->restartack.channel);
9521 if (chanpos < 0) {
9522 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
9523 channel number, so we have to figure it out... This must be why
9524 everybody resets exactly a channel at a time. */
9525 for (x = 0; x < pri->numchans; x++) {
9526 if (pri->pvts[x] && pri->pvts[x]->resetting) {
9527 chanpos = x;
9528 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9529 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
9530 pri->pvts[chanpos]->prioffset, pri->span);
9531 if (pri->pvts[chanpos]->realcall)
9532 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9533 else if (pri->pvts[chanpos]->owner) {
9534 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
9535 pri->pvts[chanpos]->prioffset, pri->span);
9536 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9538 pri->pvts[chanpos]->resetting = 0;
9539 if (option_verbose > 2)
9540 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9541 pri->pvts[chanpos]->prioffset, pri->span);
9542 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9543 if (pri->resetting)
9544 pri_check_restart(pri);
9545 break;
9548 if (chanpos < 0) {
9549 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
9550 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9552 } else {
9553 if (pri->pvts[chanpos]) {
9554 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9555 if (pri->pvts[chanpos]->realcall)
9556 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9557 else if (pri->pvts[chanpos]->owner) {
9558 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
9559 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
9560 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9562 pri->pvts[chanpos]->resetting = 0;
9563 if (option_verbose > 2)
9564 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
9565 pri->pvts[chanpos]->prioffset, pri->span);
9566 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9567 if (pri->resetting)
9568 pri_check_restart(pri);
9571 break;
9572 case PRI_EVENT_SETUP_ACK:
9573 chanpos = pri_find_principle(pri, e->setup_ack.channel);
9574 if (chanpos < 0) {
9575 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
9576 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
9577 } else {
9578 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
9579 if (chanpos > -1) {
9580 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9581 pri->pvts[chanpos]->setup_ack = 1;
9582 /* Send any queued digits */
9583 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
9584 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
9585 pri_information(pri->pri, pri->pvts[chanpos]->call,
9586 pri->pvts[chanpos]->dialdest[x]);
9588 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9589 } else
9590 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
9592 break;
9593 case PRI_EVENT_NOTIFY:
9594 chanpos = pri_find_principle(pri, e->notify.channel);
9595 if (chanpos < 0) {
9596 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
9597 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
9598 } else {
9599 struct ast_frame f = { AST_FRAME_CONTROL, };
9600 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9601 switch (e->notify.info) {
9602 case PRI_NOTIFY_REMOTE_HOLD:
9603 f.subclass = AST_CONTROL_HOLD;
9604 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9605 break;
9606 case PRI_NOTIFY_REMOTE_RETRIEVAL:
9607 f.subclass = AST_CONTROL_UNHOLD;
9608 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9609 break;
9611 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9613 break;
9614 default:
9615 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
9618 ast_mutex_unlock(&pri->lock);
9620 /* Never reached */
9621 return NULL;
9624 static int start_pri(struct dahdi_pri *pri)
9626 int res, x;
9627 struct dahdi_params p;
9628 struct dahdi_bufferinfo bi;
9629 struct dahdi_spaninfo si;
9630 int i;
9632 for (i = 0; i < NUM_DCHANS; i++) {
9633 if (!pri->dchannels[i])
9634 break;
9635 #ifdef HAVE_ZAPTEL
9636 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
9637 #else
9638 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
9639 #endif
9640 x = pri->dchannels[i];
9641 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
9642 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
9643 return -1;
9645 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
9646 if (res) {
9647 dahdi_close_pri_fd(pri, i);
9648 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
9649 return -1;
9651 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
9652 dahdi_close_pri_fd(pri, i);
9653 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
9654 return -1;
9656 memset(&si, 0, sizeof(si));
9657 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
9658 if (res) {
9659 dahdi_close_pri_fd(pri, i);
9660 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
9662 if (!si.alarms)
9663 pri->dchanavail[i] |= DCHAN_NOTINALARM;
9664 else
9665 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
9666 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
9667 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
9668 bi.numbufs = 32;
9669 bi.bufsize = 1024;
9670 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
9671 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
9672 dahdi_close_pri_fd(pri, i);
9673 return -1;
9675 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
9676 /* Force overlap dial if we're doing GR-303! */
9677 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
9678 pri->overlapdial = 1;
9679 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
9680 #ifdef HAVE_PRI_INBANDDISCONNECT
9681 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
9682 #endif
9683 /* Enslave to master if appropriate */
9684 if (i)
9685 pri_enslave(pri->dchans[0], pri->dchans[i]);
9686 if (!pri->dchans[i]) {
9687 dahdi_close_pri_fd(pri, i);
9688 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
9689 return -1;
9691 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
9692 pri_set_nsf(pri->dchans[i], pri->nsf);
9693 #ifdef PRI_GETSET_TIMERS
9694 for (x = 0; x < PRI_MAX_TIMERS; x++) {
9695 if (pritimers[x] != 0)
9696 pri_set_timer(pri->dchans[i], x, pritimers[x]);
9698 #endif
9700 /* Assume primary is the one we use */
9701 pri->pri = pri->dchans[0];
9702 pri->resetpos = -1;
9703 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
9704 for (i = 0; i < NUM_DCHANS; i++) {
9705 if (!pri->dchannels[i])
9706 break;
9707 dahdi_close_pri_fd(pri, i);
9709 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
9710 return -1;
9712 return 0;
9715 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
9717 int which, span;
9718 char *ret = NULL;
9720 if (pos != rpos)
9721 return ret;
9723 for (which = span = 0; span < NUM_SPANS; span++) {
9724 if (pris[span].pri && ++which > state) {
9725 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
9726 break;
9729 return ret;
9732 static char *complete_span_4(const char *line, const char *word, int pos, int state)
9734 return complete_span_helper(line,word,pos,state,3);
9737 static char *complete_span_5(const char *line, const char *word, int pos, int state)
9739 return complete_span_helper(line,word,pos,state,4);
9742 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
9744 int myfd;
9746 if (!strncasecmp(argv[1], "set", 3)) {
9747 if (argc < 5)
9748 return RESULT_SHOWUSAGE;
9750 if (ast_strlen_zero(argv[4]))
9751 return RESULT_SHOWUSAGE;
9753 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
9754 if (myfd < 0) {
9755 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
9756 return RESULT_SUCCESS;
9759 ast_mutex_lock(&pridebugfdlock);
9761 if (pridebugfd >= 0)
9762 close(pridebugfd);
9764 pridebugfd = myfd;
9765 ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
9767 ast_mutex_unlock(&pridebugfdlock);
9769 ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
9770 } else {
9771 /* Assume it is unset */
9772 ast_mutex_lock(&pridebugfdlock);
9773 close(pridebugfd);
9774 pridebugfd = -1;
9775 ast_cli(fd, "PRI debug output to file disabled\n");
9776 ast_mutex_unlock(&pridebugfdlock);
9779 return RESULT_SUCCESS;
9782 #ifdef HAVE_PRI_VERSION
9783 static int handle_pri_version(int fd, int agc, char *argv[]) {
9784 ast_cli(fd, "libpri version: %s\n", pri_get_version());
9785 return RESULT_SUCCESS;
9787 #endif
9789 static int handle_pri_debug(int fd, int argc, char *argv[])
9791 int span;
9792 int x;
9793 if (argc < 4) {
9794 return RESULT_SHOWUSAGE;
9796 span = atoi(argv[3]);
9797 if ((span < 1) || (span > NUM_SPANS)) {
9798 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
9799 return RESULT_SUCCESS;
9801 if (!pris[span-1].pri) {
9802 ast_cli(fd, "No PRI running on span %d\n", span);
9803 return RESULT_SUCCESS;
9805 for (x = 0; x < NUM_DCHANS; x++) {
9806 if (pris[span-1].dchans[x])
9807 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9808 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9809 PRI_DEBUG_Q921_STATE);
9811 ast_cli(fd, "Enabled debugging on span %d\n", span);
9812 return RESULT_SUCCESS;
9817 static int handle_pri_no_debug(int fd, int argc, char *argv[])
9819 int span;
9820 int x;
9821 if (argc < 5)
9822 return RESULT_SHOWUSAGE;
9823 span = atoi(argv[4]);
9824 if ((span < 1) || (span > NUM_SPANS)) {
9825 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9826 return RESULT_SUCCESS;
9828 if (!pris[span-1].pri) {
9829 ast_cli(fd, "No PRI running on span %d\n", span);
9830 return RESULT_SUCCESS;
9832 for (x = 0; x < NUM_DCHANS; x++) {
9833 if (pris[span-1].dchans[x])
9834 pri_set_debug(pris[span-1].dchans[x], 0);
9836 ast_cli(fd, "Disabled debugging on span %d\n", span);
9837 return RESULT_SUCCESS;
9840 static int handle_pri_really_debug(int fd, int argc, char *argv[])
9842 int span;
9843 int x;
9844 if (argc < 5)
9845 return RESULT_SHOWUSAGE;
9846 span = atoi(argv[4]);
9847 if ((span < 1) || (span > NUM_SPANS)) {
9848 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
9849 return RESULT_SUCCESS;
9851 if (!pris[span-1].pri) {
9852 ast_cli(fd, "No PRI running on span %d\n", span);
9853 return RESULT_SUCCESS;
9855 for (x = 0; x < NUM_DCHANS; x++) {
9856 if (pris[span-1].dchans[x])
9857 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
9858 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
9859 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
9861 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
9862 return RESULT_SUCCESS;
9865 static void build_status(char *s, size_t len, int status, int active)
9867 if (!s || len < 1) {
9868 return;
9870 s[0] = '\0';
9871 if (status & DCHAN_PROVISIONED)
9872 strncat(s, "Provisioned, ", len - strlen(s) - 1);
9873 if (!(status & DCHAN_NOTINALARM))
9874 strncat(s, "In Alarm, ", len - strlen(s) - 1);
9875 if (status & DCHAN_UP)
9876 strncat(s, "Up", len - strlen(s) - 1);
9877 else
9878 strncat(s, "Down", len - strlen(s) - 1);
9879 if (active)
9880 strncat(s, ", Active", len - strlen(s) - 1);
9881 else
9882 strncat(s, ", Standby", len - strlen(s) - 1);
9883 s[len - 1] = '\0';
9886 static int handle_pri_show_spans(int fd, int argc, char *argv[])
9888 int span;
9889 int x;
9890 char status[256];
9891 if (argc != 3)
9892 return RESULT_SHOWUSAGE;
9894 for (span = 0; span < NUM_SPANS; span++) {
9895 if (pris[span].pri) {
9896 for (x = 0; x < NUM_DCHANS; x++) {
9897 if (pris[span].dchannels[x]) {
9898 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
9899 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
9904 return RESULT_SUCCESS;
9907 static int handle_pri_show_span(int fd, int argc, char *argv[])
9909 int span;
9910 int x;
9911 char status[256];
9912 if (argc < 4)
9913 return RESULT_SHOWUSAGE;
9914 span = atoi(argv[3]);
9915 if ((span < 1) || (span > NUM_SPANS)) {
9916 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
9917 return RESULT_SUCCESS;
9919 if (!pris[span-1].pri) {
9920 ast_cli(fd, "No PRI running on span %d\n", span);
9921 return RESULT_SUCCESS;
9923 for (x = 0; x < NUM_DCHANS; x++) {
9924 if (pris[span-1].dchannels[x]) {
9925 #ifdef PRI_DUMP_INFO_STR
9926 char *info_str = NULL;
9927 #endif
9928 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
9929 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
9930 ast_cli(fd, "Status: %s\n", status);
9931 #ifdef PRI_DUMP_INFO_STR
9932 info_str = pri_dump_info_str(pris[span-1].pri);
9933 if (info_str) {
9934 ast_cli(fd, "%s", info_str);
9935 free(info_str);
9937 #else
9938 pri_dump_info(pris[span-1].pri);
9939 #endif
9940 ast_cli(fd, "\n");
9943 return RESULT_SUCCESS;
9946 static int handle_pri_show_debug(int fd, int argc, char *argv[])
9948 int x;
9949 int span;
9950 int count=0;
9951 int debug=0;
9953 for (span = 0; span < NUM_SPANS; span++) {
9954 if (pris[span].pri) {
9955 for (x = 0; x < NUM_DCHANS; x++) {
9956 debug = 0;
9957 if (pris[span].dchans[x]) {
9958 debug = pri_get_debug(pris[span].dchans[x]);
9959 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" );
9960 count++;
9966 ast_mutex_lock(&pridebugfdlock);
9967 if (pridebugfd >= 0)
9968 ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
9969 ast_mutex_unlock(&pridebugfdlock);
9971 if (!count)
9972 ast_cli(fd, "No debug set or no PRI running\n");
9973 return RESULT_SUCCESS;
9976 static const char pri_debug_help[] =
9977 "Usage: pri debug span <span>\n"
9978 " Enables debugging on a given PRI span\n";
9980 static const char pri_no_debug_help[] =
9981 "Usage: pri no debug span <span>\n"
9982 " Disables debugging on a given PRI span\n";
9984 static const char pri_really_debug_help[] =
9985 "Usage: pri intensive debug span <span>\n"
9986 " Enables debugging down to the Q.921 level\n";
9988 static const char pri_show_span_help[] =
9989 "Usage: pri show span <span>\n"
9990 " Displays PRI Information on a given PRI span\n";
9992 static const char pri_show_spans_help[] =
9993 "Usage: pri show spans\n"
9994 " Displays PRI Information\n";
9996 static struct ast_cli_entry dahdi_pri_cli[] = {
9997 { { "pri", "debug", "span", NULL },
9998 handle_pri_debug, "Enables PRI debugging on a span",
9999 pri_debug_help, complete_span_4 },
10001 { { "pri", "no", "debug", "span", NULL },
10002 handle_pri_no_debug, "Disables PRI debugging on a span",
10003 pri_no_debug_help, complete_span_5 },
10005 { { "pri", "intense", "debug", "span", NULL },
10006 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
10007 pri_really_debug_help, complete_span_5 },
10009 { { "pri", "show", "spans", NULL },
10010 handle_pri_show_spans, "Displays PRI Information",
10011 pri_show_spans_help },
10013 { { "pri", "show", "span", NULL },
10014 handle_pri_show_span, "Displays PRI Information",
10015 pri_show_span_help, complete_span_4 },
10017 { { "pri", "show", "debug", NULL },
10018 handle_pri_show_debug, "Displays current PRI debug settings" },
10020 { { "pri", "set", "debug", "file", NULL },
10021 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
10023 { { "pri", "unset", "debug", "file", NULL },
10024 handle_pri_set_debug_file, "Ends PRI debug output to file" },
10026 #ifdef HAVE_PRI_VERSION
10027 { { "pri", "show", "version", NULL },
10028 handle_pri_version, "Displays version of libpri" },
10029 #endif
10032 #endif /* HAVE_PRI */
10034 static int dahdi_destroy_channel(int fd, int argc, char **argv)
10036 int channel;
10038 if (argc != 4)
10039 return RESULT_SHOWUSAGE;
10041 channel = atoi(argv[3]);
10043 return dahdi_destroy_channel_bynum(channel);
10046 static void dahdi_softhangup_all(void)
10048 struct dahdi_pvt *p;
10049 retry:
10050 ast_mutex_lock(&iflock);
10051 for (p = iflist; p; p = p->next) {
10052 ast_mutex_lock(&p->lock);
10053 if (p->owner && !p->restartpending) {
10054 if (ast_channel_trylock(p->owner)) {
10055 if (option_debug > 2)
10056 ast_verbose("Avoiding deadlock\n");
10057 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10058 ast_mutex_unlock(&p->lock);
10059 ast_mutex_unlock(&iflock);
10060 goto retry;
10062 if (option_debug > 2)
10063 ast_verbose("Softhanging up on %s\n", p->owner->name);
10064 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10065 p->restartpending = 1;
10066 num_restart_pending++;
10067 ast_channel_unlock(p->owner);
10069 ast_mutex_unlock(&p->lock);
10071 ast_mutex_unlock(&iflock);
10074 static int setup_dahdi(int reload);
10075 static int dahdi_restart(void)
10077 #if defined(HAVE_PRI)
10078 int i, j;
10079 #endif
10080 int cancel_code;
10081 struct dahdi_pvt *p;
10083 ast_mutex_lock(&restart_lock);
10085 if (option_verbose)
10086 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10087 dahdi_softhangup_all();
10088 if (option_verbose > 3)
10089 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10091 #if defined(HAVE_PRI)
10092 for (i = 0; i < NUM_SPANS; i++) {
10093 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10094 cancel_code = pthread_cancel(pris[i].master);
10095 pthread_kill(pris[i].master, SIGURG);
10096 if (option_debug > 3)
10097 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10098 pthread_join(pris[i].master, NULL);
10099 if (option_debug > 3)
10100 ast_verbose("Joined thread of span %d\n", i);
10103 #endif
10105 ast_mutex_lock(&monlock);
10106 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10107 cancel_code = pthread_cancel(monitor_thread);
10108 pthread_kill(monitor_thread, SIGURG);
10109 if (option_debug > 3)
10110 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10111 pthread_join(monitor_thread, NULL);
10112 if (option_debug > 3)
10113 ast_verbose("Joined monitor thread\n");
10115 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10117 ast_mutex_lock(&ss_thread_lock);
10118 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10119 int x = DAHDI_FLASH;
10120 if (option_debug > 2)
10121 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10123 for (p = iflist; p; p = p->next) {
10124 if (p->owner)
10125 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 */
10127 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10130 /* ensure any created channels before monitor threads were stopped are hungup */
10131 dahdi_softhangup_all();
10132 if (option_verbose > 3)
10133 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10134 destroy_all_channels();
10135 if (option_debug)
10136 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10138 ast_mutex_unlock(&monlock);
10140 #ifdef HAVE_PRI
10141 for (i = 0; i < NUM_SPANS; i++) {
10142 for (j = 0; j < NUM_DCHANS; j++)
10143 dahdi_close_pri_fd(&(pris[i]), j);
10146 memset(pris, 0, sizeof(pris));
10147 for (i = 0; i < NUM_SPANS; i++) {
10148 ast_mutex_init(&pris[i].lock);
10149 pris[i].offset = -1;
10150 pris[i].master = AST_PTHREADT_NULL;
10151 for (j = 0; j < NUM_DCHANS; j++)
10152 pris[i].fds[j] = -1;
10154 pri_set_error(dahdi_pri_error);
10155 pri_set_message(dahdi_pri_message);
10156 #endif
10158 if (setup_dahdi(2) != 0) {
10159 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10160 ast_mutex_unlock(&ss_thread_lock);
10161 return 1;
10163 ast_mutex_unlock(&ss_thread_lock);
10164 ast_mutex_unlock(&restart_lock);
10165 return 0;
10168 static int dahdi_restart_cmd(int fd, int argc, char **argv)
10170 if (argc != 2) {
10171 return RESULT_SHOWUSAGE;
10174 if (dahdi_restart() != 0)
10175 return RESULT_FAILURE;
10176 return RESULT_SUCCESS;
10179 static int dahdi_show_channels(int fd, int argc, char **argv)
10181 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10182 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10183 struct dahdi_pvt *tmp = NULL;
10184 char tmps[20] = "";
10185 ast_mutex_t *lock;
10186 struct dahdi_pvt *start;
10187 #ifdef HAVE_PRI
10188 int trunkgroup;
10189 struct dahdi_pri *pri = NULL;
10190 int x;
10191 #endif
10193 lock = &iflock;
10194 start = iflist;
10196 #ifdef HAVE_PRI
10197 if (argc == 4) {
10198 if ((trunkgroup = atoi(argv[3])) < 1)
10199 return RESULT_SHOWUSAGE;
10200 for (x = 0; x < NUM_SPANS; x++) {
10201 if (pris[x].trunkgroup == trunkgroup) {
10202 pri = pris + x;
10203 break;
10206 if (pri) {
10207 start = pri->crvs;
10208 lock = &pri->lock;
10209 } else {
10210 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10211 return RESULT_FAILURE;
10213 } else
10214 #endif
10215 if (argc != 3)
10216 return RESULT_SHOWUSAGE;
10218 ast_mutex_lock(lock);
10219 #ifdef HAVE_PRI
10220 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10221 #else
10222 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10223 #endif
10225 tmp = start;
10226 while (tmp) {
10227 if (tmp->channel > 0) {
10228 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10229 } else
10230 ast_copy_string(tmps, "pseudo", sizeof(tmps));
10231 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10232 tmp = tmp->next;
10234 ast_mutex_unlock(lock);
10235 return RESULT_SUCCESS;
10236 #undef FORMAT
10237 #undef FORMAT2
10240 static int dahdi_show_channel(int fd, int argc, char **argv)
10242 int channel;
10243 struct dahdi_pvt *tmp = NULL;
10244 struct dahdi_confinfo ci;
10245 struct dahdi_params ps;
10246 int x;
10247 ast_mutex_t *lock;
10248 struct dahdi_pvt *start;
10249 #ifdef HAVE_PRI
10250 char *c;
10251 int trunkgroup;
10252 struct dahdi_pri *pri=NULL;
10253 #endif
10255 lock = &iflock;
10256 start = iflist;
10258 if (argc != 4)
10259 return RESULT_SHOWUSAGE;
10260 #ifdef HAVE_PRI
10261 if ((c = strchr(argv[3], ':'))) {
10262 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
10263 return RESULT_SHOWUSAGE;
10264 if ((trunkgroup < 1) || (channel < 1))
10265 return RESULT_SHOWUSAGE;
10266 for (x = 0; x < NUM_SPANS; x++) {
10267 if (pris[x].trunkgroup == trunkgroup) {
10268 pri = pris + x;
10269 break;
10272 if (pri) {
10273 start = pri->crvs;
10274 lock = &pri->lock;
10275 } else {
10276 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10277 return RESULT_FAILURE;
10279 } else
10280 #endif
10281 channel = atoi(argv[3]);
10283 ast_mutex_lock(lock);
10284 tmp = start;
10285 while (tmp) {
10286 if (tmp->channel == channel) {
10287 #ifdef HAVE_PRI
10288 if (pri)
10289 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10290 else
10291 #endif
10292 ast_cli(fd, "Channel: %d\n", tmp->channel);
10293 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10294 ast_cli(fd, "Span: %d\n", tmp->span);
10295 ast_cli(fd, "Extension: %s\n", tmp->exten);
10296 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10297 ast_cli(fd, "Context: %s\n", tmp->context);
10298 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10299 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10300 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10301 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10302 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10303 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10304 ast_cli(fd, "Radio: %d\n", tmp->radio);
10305 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10306 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)" : "");
10307 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)" : "");
10308 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)" : "");
10309 ast_cli(fd, "Confno: %d\n", tmp->confno);
10310 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10311 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10312 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10313 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10314 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10315 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10316 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10317 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10318 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10319 if (tmp->master)
10320 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10321 for (x = 0; x < MAX_SLAVES; x++) {
10322 if (tmp->slaves[x])
10323 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10325 #ifdef HAVE_PRI
10326 if (tmp->pri) {
10327 ast_cli(fd, "PRI Flags: ");
10328 if (tmp->resetting)
10329 ast_cli(fd, "Resetting ");
10330 if (tmp->call)
10331 ast_cli(fd, "Call ");
10332 if (tmp->bearer)
10333 ast_cli(fd, "Bearer ");
10334 ast_cli(fd, "\n");
10335 if (tmp->logicalspan)
10336 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10337 else
10338 ast_cli(fd, "PRI Logical Span: Implicit\n");
10341 #endif
10342 memset(&ci, 0, sizeof(ci));
10343 ps.channo = tmp->channel;
10344 if (tmp->subs[SUB_REAL].dfd > -1) {
10345 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10346 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10348 #ifdef DAHDI_GETCONFMUTE
10349 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10350 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10352 #endif
10353 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10354 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10355 } else {
10356 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10359 ast_mutex_unlock(lock);
10360 return RESULT_SUCCESS;
10362 tmp = tmp->next;
10365 ast_cli(fd, "Unable to find given channel %d\n", channel);
10366 ast_mutex_unlock(lock);
10367 return RESULT_FAILURE;
10370 static char dahdi_show_cadences_usage[] =
10371 "Usage: dahdi show cadences\n"
10372 " Shows all cadences currently defined\n";
10374 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
10376 int i, j;
10377 for (i = 0; i < num_cadence; i++) {
10378 char output[1024];
10379 char tmp[16], tmp2[64];
10380 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10381 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10383 for (j = 0; j < 16; j++) {
10384 if (cadences[i].ringcadence[j] == 0)
10385 break;
10386 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10387 if (cidrings[i] * 2 - 1 == j)
10388 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10389 else
10390 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10391 if (j != 0)
10392 strncat(output, ",", sizeof(output) - strlen(output) - 1);
10393 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10395 ast_cli(fd,"%s\n",output);
10397 return 0;
10400 /* Based on irqmiss.c */
10401 static int dahdi_show_status(int fd, int argc, char *argv[]) {
10402 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10403 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10405 int span;
10406 int res;
10407 char alarms[50];
10409 int ctl;
10410 struct dahdi_spaninfo s;
10412 #ifdef HAVE_ZAPTEL
10413 if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
10414 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
10415 ast_cli(fd, "No Zaptel interface found.\n");
10416 return RESULT_FAILURE;
10418 #else
10419 if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
10420 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
10421 ast_cli(fd, "No DAHDI interface found.\n");
10422 return RESULT_FAILURE;
10424 #endif
10425 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10427 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10428 s.spanno = span;
10429 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10430 if (res) {
10431 continue;
10433 alarms[0] = '\0';
10434 if (s.alarms > 0) {
10435 if (s.alarms & DAHDI_ALARM_BLUE)
10436 strcat(alarms, "BLU/");
10437 if (s.alarms & DAHDI_ALARM_YELLOW)
10438 strcat(alarms, "YEL/");
10439 if (s.alarms & DAHDI_ALARM_RED)
10440 strcat(alarms, "RED/");
10441 if (s.alarms & DAHDI_ALARM_LOOPBACK)
10442 strcat(alarms, "LB/");
10443 if (s.alarms & DAHDI_ALARM_RECOVER)
10444 strcat(alarms, "REC/");
10445 if (s.alarms & DAHDI_ALARM_NOTOPEN)
10446 strcat(alarms, "NOP/");
10447 if (!strlen(alarms))
10448 strcat(alarms, "UUU/");
10449 if (strlen(alarms)) {
10450 /* Strip trailing / */
10451 alarms[strlen(alarms) - 1] = '\0';
10453 } else {
10454 if (s.numchans)
10455 strcpy(alarms, "OK");
10456 else
10457 strcpy(alarms, "UNCONFIGURED");
10460 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10462 close(ctl);
10464 return RESULT_SUCCESS;
10465 #undef FORMAT
10466 #undef FORMAT2
10469 static char show_channels_usage[] =
10470 "Usage: dahdi show channels\n"
10471 " Shows a list of available channels\n";
10473 static char show_channel_usage[] =
10474 "Usage: dahdi show channel <chan num>\n"
10475 " Detailed information about a given channel\n";
10477 static char dahdi_show_status_usage[] =
10478 "Usage: dahdi show status\n"
10479 " Shows a list of DAHDI cards with status\n";
10481 static char destroy_channel_usage[] =
10482 "Usage: dahdi destroy channel <chan num>\n"
10483 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
10485 static char dahdi_restart_usage[] =
10486 "Usage: dahdi restart\n"
10487 " Restarts the DAHDI channels: destroys them all and then\n"
10488 " re-reads them from chan_dahdi.conf.\n"
10489 " Note that this will STOP any running CALL on DAHDI channels.\n"
10492 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
10493 { "zap", "show", "cadences", NULL },
10494 handle_dahdi_show_cadences, NULL,
10495 NULL };
10497 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
10498 { "zap", "show", "channels", NULL },
10499 dahdi_show_channels, NULL,
10500 NULL };
10502 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
10503 { "zap", "show", "channel", NULL },
10504 dahdi_show_channel, NULL,
10505 NULL };
10507 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
10508 { "zap", "destroy", "channel", NULL },
10509 dahdi_destroy_channel, NULL,
10510 NULL };
10512 static struct ast_cli_entry cli_zap_restart_deprecated = {
10513 { "zap", "restart", NULL },
10514 dahdi_restart_cmd, NULL,
10515 NULL };
10517 static struct ast_cli_entry cli_zap_show_status_deprecated = {
10518 { "zap", "show", "status", NULL },
10519 dahdi_show_status, NULL,
10520 NULL };
10522 static struct ast_cli_entry dahdi_cli[] = {
10523 { { "dahdi", "show", "cadences", NULL },
10524 handle_dahdi_show_cadences, "List cadences",
10525 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
10527 { { "dahdi", "show", "channels", NULL},
10528 dahdi_show_channels, "Show active DAHDI channels",
10529 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
10531 { { "dahdi", "show", "channel", NULL},
10532 dahdi_show_channel, "Show information on a channel",
10533 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
10535 { { "dahdi", "destroy", "channel", NULL},
10536 dahdi_destroy_channel, "Destroy a channel",
10537 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
10539 { { "dahdi", "restart", NULL},
10540 dahdi_restart_cmd, "Fully restart DAHDI channels",
10541 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
10543 { { "dahdi", "show", "status", NULL},
10544 dahdi_show_status, "Show all DAHDI cards status",
10545 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
10548 #define TRANSFER 0
10549 #define HANGUP 1
10551 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
10553 if (p) {
10554 switch (mode) {
10555 case TRANSFER:
10556 p->fake_event = DAHDI_EVENT_WINKFLASH;
10557 break;
10558 case HANGUP:
10559 p->fake_event = DAHDI_EVENT_ONHOOK;
10560 break;
10561 default:
10562 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
10565 return 0;
10567 static struct dahdi_pvt *find_channel(int channel)
10569 struct dahdi_pvt *p = iflist;
10570 while (p) {
10571 if (p->channel == channel) {
10572 break;
10574 p = p->next;
10576 return p;
10579 #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)
10580 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
10582 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
10584 struct dahdi_pvt *p = NULL;
10585 const char *channel = local_astman_header(m, "Channel", zap_mode);
10587 if (ast_strlen_zero(channel)) {
10588 astman_send_error(s, m, "No channel specified");
10589 return 0;
10591 if (!(p = find_channel(atoi(channel)))) {
10592 astman_send_error(s, m, "No such channel");
10593 return 0;
10595 p->dnd = dnd;
10596 local_astman_ack(s, m, "DND", zap_mode);
10598 return 0;
10601 static int zap_action_dndon(struct mansession *s, const struct message *m)
10603 return __action_dnd(s, m, 1, 1);
10606 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
10608 return __action_dnd(s, m, 0, 1);
10611 static int zap_action_dndoff(struct mansession *s, const struct message *m)
10613 return __action_dnd(s, m, 1, 0);
10616 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
10618 return __action_dnd(s, m, 0, 0);
10621 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
10623 struct dahdi_pvt *p = NULL;
10624 const char *channel = local_astman_header(m, "Channel", zap_mode);
10626 if (ast_strlen_zero(channel)) {
10627 astman_send_error(s, m, "No channel specified");
10628 return 0;
10630 if (!(p = find_channel(atoi(channel)))) {
10631 astman_send_error(s, m, "No such channel");
10632 return 0;
10634 dahdi_fake_event(p,TRANSFER);
10635 local_astman_ack(s, m, "Transfer", zap_mode);
10637 return 0;
10640 static int zap_action_transfer(struct mansession *s, const struct message *m)
10642 return __action_transfer(s, m, 1);
10645 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
10647 return __action_transfer(s, m, 0);
10650 static int __action_transferhangup(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);
10655 if (ast_strlen_zero(channel)) {
10656 astman_send_error(s, m, "No channel specified");
10657 return 0;
10659 if (!(p = find_channel(atoi(channel)))) {
10660 astman_send_error(s, m, "No such channel");
10661 return 0;
10663 dahdi_fake_event(p, HANGUP);
10664 local_astman_ack(s, m, "Hangup", zap_mode);
10665 return 0;
10668 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
10670 return __action_transferhangup(s, m, 1);
10673 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
10675 return __action_transferhangup(s, m, 0);
10678 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
10680 struct dahdi_pvt *p = NULL;
10681 const char *channel = local_astman_header(m, "Channel", zap_mode);
10682 const char *number = astman_get_header(m, "Number");
10683 int i;
10685 if (ast_strlen_zero(channel)) {
10686 astman_send_error(s, m, "No channel specified");
10687 return 0;
10689 if (ast_strlen_zero(number)) {
10690 astman_send_error(s, m, "No number specified");
10691 return 0;
10693 if (!(p = find_channel(atoi(channel)))) {
10694 astman_send_error(s, m, "No such channel");
10695 return 0;
10697 if (!p->owner) {
10698 astman_send_error(s, m, "Channel does not have an owner");
10699 return 0;
10701 for (i = 0; i < strlen(number); i++) {
10702 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
10704 dahdi_queue_frame(p, &f, NULL);
10706 local_astman_ack(s, m, "DialOffHook", zap_mode);
10708 return 0;
10711 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
10713 return __action_dialoffhook(s, m, 1);
10716 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
10718 return __action_dialoffhook(s, m, 0);
10721 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
10723 struct dahdi_pvt *tmp = NULL;
10724 const char *id = astman_get_header(m, "ActionID");
10725 char idText[256] = "";
10727 local_astman_ack(s, m, " channel status will follow", zap_mode);
10728 if (!ast_strlen_zero(id))
10729 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
10731 ast_mutex_lock(&iflock);
10733 tmp = iflist;
10734 while (tmp) {
10735 if (tmp->channel > 0) {
10736 int alarm = get_alarms(tmp);
10737 astman_append(s,
10738 "Event: %sShowChannels\r\n"
10739 "Channel: %d\r\n"
10740 "Signalling: %s\r\n"
10741 "Context: %s\r\n"
10742 "DND: %s\r\n"
10743 "Alarm: %s\r\n"
10744 "%s"
10745 "\r\n",
10746 dahdi_chan_name,
10747 tmp->channel, sig2str(tmp->sig), tmp->context,
10748 tmp->dnd ? "Enabled" : "Disabled",
10749 alarm2str(alarm), idText);
10752 tmp = tmp->next;
10755 ast_mutex_unlock(&iflock);
10757 astman_append(s,
10758 "Event: %sShowChannelsComplete\r\n"
10759 "%s"
10760 "\r\n",
10761 dahdi_chan_name,
10762 idText);
10763 return 0;
10766 static int zap_action_showchannels(struct mansession *s, const struct message *m)
10768 return __action_showchannels(s, m, 1);
10771 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
10773 return __action_showchannels(s, m, 0);
10776 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
10778 if (dahdi_restart() != 0) {
10779 if (zap_mode) {
10780 astman_send_error(s, m, "Failed to restart Zap");
10781 } else {
10782 astman_send_error(s, m, "Failed to restart DAHDI");
10784 return 1;
10786 local_astman_ack(s, m, "Restart: Success", zap_mode);
10787 return 0;
10790 static int zap_action_restart(struct mansession *s, const struct message *m)
10792 return __action_restart(s, m, 1);
10795 static int dahdi_action_restart(struct mansession *s, const struct message *m)
10797 return __action_restart(s, m, 0);
10800 #define local_astman_unregister(a) do { \
10801 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
10802 ast_manager_unregister("DAHDI" a); \
10804 ast_manager_unregister("Zap" a); \
10805 } while (0)
10807 static int __unload_module(void)
10809 struct dahdi_pvt *p;
10811 #ifdef HAVE_PRI
10812 int i, j;
10813 for (i = 0; i < NUM_SPANS; i++) {
10814 if (pris[i].master != AST_PTHREADT_NULL)
10815 pthread_cancel(pris[i].master);
10817 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
10819 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
10820 ast_unregister_application(dahdi_send_keypad_facility_app);
10822 ast_unregister_application(zap_send_keypad_facility_app);
10823 #endif
10824 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
10825 local_astman_unregister("DialOffHook");
10826 local_astman_unregister("Hangup");
10827 local_astman_unregister("Transfer");
10828 local_astman_unregister("DNDoff");
10829 local_astman_unregister("DNDon");
10830 local_astman_unregister("ShowChannels");
10831 local_astman_unregister("Restart");
10832 ast_channel_unregister(chan_tech);
10833 ast_mutex_lock(&iflock);
10834 /* Hangup all interfaces if they have an owner */
10835 p = iflist;
10836 while (p) {
10837 if (p->owner)
10838 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
10839 p = p->next;
10841 ast_mutex_unlock(&iflock);
10842 ast_mutex_lock(&monlock);
10843 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10844 pthread_cancel(monitor_thread);
10845 pthread_kill(monitor_thread, SIGURG);
10846 pthread_join(monitor_thread, NULL);
10848 monitor_thread = AST_PTHREADT_STOP;
10849 ast_mutex_unlock(&monlock);
10851 destroy_all_channels();
10852 #ifdef HAVE_PRI
10853 for (i = 0; i < NUM_SPANS; i++) {
10854 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
10855 pthread_join(pris[i].master, NULL);
10856 for (j = 0; j < NUM_DCHANS; j++) {
10857 dahdi_close_pri_fd(&(pris[i]), j);
10860 #endif
10861 ast_cond_destroy(&ss_thread_complete);
10862 return 0;
10865 static int unload_module(void)
10867 #ifdef HAVE_PRI
10868 int y;
10869 for (y = 0; y < NUM_SPANS; y++)
10870 ast_mutex_destroy(&pris[y].lock);
10871 #endif
10872 return __unload_module();
10875 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
10877 char *c, *chan;
10878 int x, start, finish;
10879 struct dahdi_pvt *tmp;
10880 #ifdef HAVE_PRI
10881 struct dahdi_pri *pri;
10882 int trunkgroup, y;
10883 #endif
10885 if ((reload == 0) && (conf->chan.sig < 0)) {
10886 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
10887 return -1;
10890 c = ast_strdupa(value);
10892 #ifdef HAVE_PRI
10893 pri = NULL;
10894 if (iscrv) {
10895 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
10896 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
10897 return -1;
10899 if (trunkgroup < 1) {
10900 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
10901 return -1;
10903 c += y;
10904 for (y = 0; y < NUM_SPANS; y++) {
10905 if (pris[y].trunkgroup == trunkgroup) {
10906 pri = pris + y;
10907 break;
10910 if (!pri) {
10911 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
10912 return -1;
10915 #endif
10917 while ((chan = strsep(&c, ","))) {
10918 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
10919 /* Range */
10920 } else if (sscanf(chan, "%d", &start)) {
10921 /* Just one */
10922 finish = start;
10923 } else if (!strcasecmp(chan, "pseudo")) {
10924 finish = start = CHAN_PSEUDO;
10925 if (found_pseudo)
10926 *found_pseudo = 1;
10927 } else {
10928 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
10929 return -1;
10931 if (finish < start) {
10932 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
10933 x = finish;
10934 finish = start;
10935 start = x;
10938 for (x = start; x <= finish; x++) {
10939 #ifdef HAVE_PRI
10940 tmp = mkintf(x, conf, pri, reload);
10941 #else
10942 tmp = mkintf(x, conf, NULL, reload);
10943 #endif
10945 if (tmp) {
10946 if (option_verbose > 2) {
10947 #ifdef HAVE_PRI
10948 if (pri)
10949 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
10950 else
10951 #endif
10952 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
10954 } else {
10955 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
10956 (reload == 1) ? "reconfigure" : "register", value);
10957 return -1;
10962 return 0;
10965 /** The length of the parameters list of 'dahdichan'.
10966 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
10967 #define MAX_CHANLIST_LEN 80
10968 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
10970 struct dahdi_pvt *tmp;
10971 int y;
10972 int found_pseudo = 0;
10973 char dahdichan[MAX_CHANLIST_LEN] = {};
10975 for (; v; v = v->next) {
10976 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
10977 continue;
10979 /* Create the interface list */
10980 if (!strcasecmp(v->name, "channel")
10981 #ifdef HAVE_PRI
10982 || !strcasecmp(v->name, "crv")
10983 #endif
10985 int iscrv;
10986 if (skipchannels)
10987 continue;
10988 iscrv = !strcasecmp(v->name, "crv");
10989 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
10990 return -1;
10991 } else if (!strcasecmp(v->name, "buffers")) {
10992 int res;
10993 char policy[21] = "";
10995 res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
10996 if (res != 2) {
10997 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
10998 confp->chan.buf_no = numbufs;
10999 continue;
11001 if (confp->chan.buf_no < 0)
11002 confp->chan.buf_no = numbufs;
11003 if (!strcasecmp(policy, "full")) {
11004 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11005 } else if (!strcasecmp(policy, "half")) {
11006 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /* TODO: change to HALF_FULL */;
11007 } else if (!strcasecmp(policy, "immediate")) {
11008 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11009 } else {
11010 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11012 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11013 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11014 if (v->name[0] == 'z' || v->name[0] == 'Z') {
11015 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11017 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11018 if (ast_true(v->value))
11019 confp->chan.usedistinctiveringdetection = 1;
11020 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11021 if (ast_true(v->value))
11022 distinctiveringaftercid = 1;
11023 } else if (!strcasecmp(v->name, "dring1context")) {
11024 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11025 } else if (!strcasecmp(v->name, "dring2context")) {
11026 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11027 } else if (!strcasecmp(v->name, "dring3context")) {
11028 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11029 } else if (!strcasecmp(v->name, "dring1")) {
11030 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11031 } else if (!strcasecmp(v->name, "dring2")) {
11032 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11033 } else if (!strcasecmp(v->name, "dring3")) {
11034 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11035 } else if (!strcasecmp(v->name, "usecallerid")) {
11036 confp->chan.use_callerid = ast_true(v->value);
11037 } else if (!strcasecmp(v->name, "cidsignalling")) {
11038 if (!strcasecmp(v->value, "bell"))
11039 confp->chan.cid_signalling = CID_SIG_BELL;
11040 else if (!strcasecmp(v->value, "v23"))
11041 confp->chan.cid_signalling = CID_SIG_V23;
11042 else if (!strcasecmp(v->value, "dtmf"))
11043 confp->chan.cid_signalling = CID_SIG_DTMF;
11044 else if (!strcasecmp(v->value, "smdi"))
11045 confp->chan.cid_signalling = CID_SIG_SMDI;
11046 else if (!strcasecmp(v->value, "v23_jp"))
11047 confp->chan.cid_signalling = CID_SIG_V23_JP;
11048 else if (ast_true(v->value))
11049 confp->chan.cid_signalling = CID_SIG_BELL;
11050 } else if (!strcasecmp(v->name, "cidstart")) {
11051 if (!strcasecmp(v->value, "ring"))
11052 confp->chan.cid_start = CID_START_RING;
11053 else if (!strcasecmp(v->value, "polarity"))
11054 confp->chan.cid_start = CID_START_POLARITY;
11055 else if (ast_true(v->value))
11056 confp->chan.cid_start = CID_START_RING;
11057 } else if (!strcasecmp(v->name, "threewaycalling")) {
11058 confp->chan.threewaycalling = ast_true(v->value);
11059 } else if (!strcasecmp(v->name, "cancallforward")) {
11060 confp->chan.cancallforward = ast_true(v->value);
11061 } else if (!strcasecmp(v->name, "relaxdtmf")) {
11062 if (ast_true(v->value))
11063 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11064 else
11065 confp->chan.dtmfrelax = 0;
11066 } else if (!strcasecmp(v->name, "mailbox")) {
11067 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11068 } else if (!strcasecmp(v->name, "hasvoicemail")) {
11069 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11070 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11072 } else if (!strcasecmp(v->name, "adsi")) {
11073 confp->chan.adsi = ast_true(v->value);
11074 } else if (!strcasecmp(v->name, "usesmdi")) {
11075 confp->chan.use_smdi = ast_true(v->value);
11076 } else if (!strcasecmp(v->name, "smdiport")) {
11077 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11078 } else if (!strcasecmp(v->name, "transfer")) {
11079 confp->chan.transfer = ast_true(v->value);
11080 } else if (!strcasecmp(v->name, "canpark")) {
11081 confp->chan.canpark = ast_true(v->value);
11082 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11083 confp->chan.echocanbridged = ast_true(v->value);
11084 } else if (!strcasecmp(v->name, "busydetect")) {
11085 confp->chan.busydetect = ast_true(v->value);
11086 } else if (!strcasecmp(v->name, "busycount")) {
11087 confp->chan.busycount = atoi(v->value);
11088 } else if (!strcasecmp(v->name, "busypattern")) {
11089 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
11090 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
11092 } else if (!strcasecmp(v->name, "callprogress")) {
11093 if (ast_true(v->value))
11094 confp->chan.callprogress |= 1;
11095 else
11096 confp->chan.callprogress &= ~1;
11097 } else if (!strcasecmp(v->name, "faxdetect")) {
11098 if (!strcasecmp(v->value, "incoming")) {
11099 confp->chan.callprogress |= 4;
11100 confp->chan.callprogress &= ~2;
11101 } else if (!strcasecmp(v->value, "outgoing")) {
11102 confp->chan.callprogress &= ~4;
11103 confp->chan.callprogress |= 2;
11104 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11105 confp->chan.callprogress |= 6;
11106 else
11107 confp->chan.callprogress &= ~6;
11108 } else if (!strcasecmp(v->name, "echocancel")) {
11109 if (!ast_strlen_zero(v->value)) {
11110 y = atoi(v->value);
11111 } else
11112 y = 0;
11113 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11114 confp->chan.echocancel = y;
11115 else {
11116 confp->chan.echocancel = ast_true(v->value);
11117 if (confp->chan.echocancel)
11118 confp->chan.echocancel=128;
11120 } else if (!strcasecmp(v->name, "echotraining")) {
11121 if (sscanf(v->value, "%d", &y) == 1) {
11122 if ((y < 10) || (y > 4000)) {
11123 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
11124 } else {
11125 confp->chan.echotraining = y;
11127 } else if (ast_true(v->value)) {
11128 confp->chan.echotraining = 400;
11129 } else
11130 confp->chan.echotraining = 0;
11131 } else if (!strcasecmp(v->name, "hidecallerid")) {
11132 confp->chan.hidecallerid = ast_true(v->value);
11133 } else if (!strcasecmp(v->name, "hidecalleridname")) {
11134 confp->chan.hidecalleridname = ast_true(v->value);
11135 } else if (!strcasecmp(v->name, "pulsedial")) {
11136 confp->chan.pulse = ast_true(v->value);
11137 } else if (!strcasecmp(v->name, "callreturn")) {
11138 confp->chan.callreturn = ast_true(v->value);
11139 } else if (!strcasecmp(v->name, "callwaiting")) {
11140 confp->chan.callwaiting = ast_true(v->value);
11141 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11142 confp->chan.callwaitingcallerid = ast_true(v->value);
11143 } else if (!strcasecmp(v->name, "context")) {
11144 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11145 } else if (!strcasecmp(v->name, "language")) {
11146 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11147 } else if (!strcasecmp(v->name, "progzone")) {
11148 ast_copy_string(progzone, v->value, sizeof(progzone));
11149 } else if (!strcasecmp(v->name, "mohinterpret")
11150 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11151 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11152 } else if (!strcasecmp(v->name, "mohsuggest")) {
11153 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11154 } else if (!strcasecmp(v->name, "stripmsd")) {
11155 confp->chan.stripmsd = atoi(v->value);
11156 } else if (!strcasecmp(v->name, "jitterbuffers")) {
11157 numbufs = atoi(v->value);
11158 } else if (!strcasecmp(v->name, "group")) {
11159 confp->chan.group = ast_get_group(v->value);
11160 } else if (!strcasecmp(v->name, "callgroup")) {
11161 confp->chan.callgroup = ast_get_group(v->value);
11162 } else if (!strcasecmp(v->name, "pickupgroup")) {
11163 confp->chan.pickupgroup = ast_get_group(v->value);
11164 } else if (!strcasecmp(v->name, "immediate")) {
11165 confp->chan.immediate = ast_true(v->value);
11166 } else if (!strcasecmp(v->name, "transfertobusy")) {
11167 confp->chan.transfertobusy = ast_true(v->value);
11168 } else if (!strcasecmp(v->name, "rxgain")) {
11169 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
11170 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11172 } else if (!strcasecmp(v->name, "txgain")) {
11173 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
11174 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11176 } else if (!strcasecmp(v->name, "tonezone")) {
11177 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
11178 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11180 } else if (!strcasecmp(v->name, "callerid")) {
11181 if (!strcasecmp(v->value, "asreceived")) {
11182 confp->chan.cid_num[0] = '\0';
11183 confp->chan.cid_name[0] = '\0';
11184 } else {
11185 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11187 } else if (!strcasecmp(v->name, "fullname")) {
11188 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11189 } else if (!strcasecmp(v->name, "cid_number")) {
11190 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11191 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11192 confp->chan.dahditrcallerid = ast_true(v->value);
11193 if (strstr(v->name, "zap")) {
11194 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11196 } else if (!strcasecmp(v->name, "restrictcid")) {
11197 confp->chan.restrictcid = ast_true(v->value);
11198 } else if (!strcasecmp(v->name, "usecallingpres")) {
11199 confp->chan.use_callingpres = ast_true(v->value);
11200 } else if (!strcasecmp(v->name, "accountcode")) {
11201 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11202 } else if (!strcasecmp(v->name, "amaflags")) {
11203 y = ast_cdr_amaflags2int(v->value);
11204 if (y < 0)
11205 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11206 else
11207 confp->chan.amaflags = y;
11208 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11209 confp->chan.polarityonanswerdelay = atoi(v->value);
11210 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11211 confp->chan.answeronpolarityswitch = ast_true(v->value);
11212 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11213 confp->chan.hanguponpolarityswitch = ast_true(v->value);
11214 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11215 confp->chan.sendcalleridafter = atoi(v->value);
11216 } else if (reload != 1){
11217 if (!strcasecmp(v->name, "signalling")) {
11218 confp->chan.outsigmod = -1;
11219 if (!strcasecmp(v->value, "em")) {
11220 confp->chan.sig = SIG_EM;
11221 } else if (!strcasecmp(v->value, "em_e1")) {
11222 confp->chan.sig = SIG_EM_E1;
11223 } else if (!strcasecmp(v->value, "em_w")) {
11224 confp->chan.sig = SIG_EMWINK;
11225 confp->chan.radio = 0;
11226 } else if (!strcasecmp(v->value, "fxs_ls")) {
11227 confp->chan.sig = SIG_FXSLS;
11228 confp->chan.radio = 0;
11229 } else if (!strcasecmp(v->value, "fxs_gs")) {
11230 confp->chan.sig = SIG_FXSGS;
11231 confp->chan.radio = 0;
11232 } else if (!strcasecmp(v->value, "fxs_ks")) {
11233 confp->chan.sig = SIG_FXSKS;
11234 confp->chan.radio = 0;
11235 } else if (!strcasecmp(v->value, "fxo_ls")) {
11236 confp->chan.sig = SIG_FXOLS;
11237 confp->chan.radio = 0;
11238 } else if (!strcasecmp(v->value, "fxo_gs")) {
11239 confp->chan.sig = SIG_FXOGS;
11240 confp->chan.radio = 0;
11241 } else if (!strcasecmp(v->value, "fxo_ks")) {
11242 confp->chan.sig = SIG_FXOKS;
11243 confp->chan.radio = 0;
11244 } else if (!strcasecmp(v->value, "fxs_rx")) {
11245 confp->chan.sig = SIG_FXSKS;
11246 confp->chan.radio = 1;
11247 } else if (!strcasecmp(v->value, "fxo_rx")) {
11248 confp->chan.sig = SIG_FXOLS;
11249 confp->chan.radio = 1;
11250 } else if (!strcasecmp(v->value, "fxs_tx")) {
11251 confp->chan.sig = SIG_FXSLS;
11252 confp->chan.radio = 1;
11253 } else if (!strcasecmp(v->value, "fxo_tx")) {
11254 confp->chan.sig = SIG_FXOGS;
11255 confp->chan.radio = 1;
11256 } else if (!strcasecmp(v->value, "em_rx")) {
11257 confp->chan.sig = SIG_EM;
11258 confp->chan.radio = 1;
11259 } else if (!strcasecmp(v->value, "em_tx")) {
11260 confp->chan.sig = SIG_EM;
11261 confp->chan.radio = 1;
11262 } else if (!strcasecmp(v->value, "em_rxtx")) {
11263 confp->chan.sig = SIG_EM;
11264 confp->chan.radio = 2;
11265 } else if (!strcasecmp(v->value, "em_txrx")) {
11266 confp->chan.sig = SIG_EM;
11267 confp->chan.radio = 2;
11268 } else if (!strcasecmp(v->value, "sf")) {
11269 confp->chan.sig = SIG_SF;
11270 confp->chan.radio = 0;
11271 } else if (!strcasecmp(v->value, "sf_w")) {
11272 confp->chan.sig = SIG_SFWINK;
11273 confp->chan.radio = 0;
11274 } else if (!strcasecmp(v->value, "sf_featd")) {
11275 confp->chan.sig = SIG_FEATD;
11276 confp->chan.radio = 0;
11277 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11278 confp->chan.sig = SIG_FEATDMF;
11279 confp->chan.radio = 0;
11280 } else if (!strcasecmp(v->value, "sf_featb")) {
11281 confp->chan.sig = SIG_SF_FEATB;
11282 confp->chan.radio = 0;
11283 } else if (!strcasecmp(v->value, "sf")) {
11284 confp->chan.sig = SIG_SF;
11285 confp->chan.radio = 0;
11286 } else if (!strcasecmp(v->value, "sf_rx")) {
11287 confp->chan.sig = SIG_SF;
11288 confp->chan.radio = 1;
11289 } else if (!strcasecmp(v->value, "sf_tx")) {
11290 confp->chan.sig = SIG_SF;
11291 confp->chan.radio = 1;
11292 } else if (!strcasecmp(v->value, "sf_rxtx")) {
11293 confp->chan.sig = SIG_SF;
11294 confp->chan.radio = 2;
11295 } else if (!strcasecmp(v->value, "sf_txrx")) {
11296 confp->chan.sig = SIG_SF;
11297 confp->chan.radio = 2;
11298 } else if (!strcasecmp(v->value, "featd")) {
11299 confp->chan.sig = SIG_FEATD;
11300 confp->chan.radio = 0;
11301 } else if (!strcasecmp(v->value, "featdmf")) {
11302 confp->chan.sig = SIG_FEATDMF;
11303 confp->chan.radio = 0;
11304 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11305 confp->chan.sig = SIG_FEATDMF_TA;
11306 confp->chan.radio = 0;
11307 } else if (!strcasecmp(v->value, "e911")) {
11308 confp->chan.sig = SIG_E911;
11309 confp->chan.radio = 0;
11310 } else if (!strcasecmp(v->value, "fgccama")) {
11311 confp->chan.sig = SIG_FGC_CAMA;
11312 confp->chan.radio = 0;
11313 } else if (!strcasecmp(v->value, "fgccamamf")) {
11314 confp->chan.sig = SIG_FGC_CAMAMF;
11315 confp->chan.radio = 0;
11316 } else if (!strcasecmp(v->value, "featb")) {
11317 confp->chan.sig = SIG_FEATB;
11318 confp->chan.radio = 0;
11319 #ifdef HAVE_PRI
11320 } else if (!strcasecmp(v->value, "pri_net")) {
11321 confp->chan.radio = 0;
11322 confp->chan.sig = SIG_PRI;
11323 confp->pri.nodetype = PRI_NETWORK;
11324 } else if (!strcasecmp(v->value, "pri_cpe")) {
11325 confp->chan.sig = SIG_PRI;
11326 confp->chan.radio = 0;
11327 confp->pri.nodetype = PRI_CPE;
11328 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11329 confp->chan.sig = SIG_GR303FXOKS;
11330 confp->chan.radio = 0;
11331 confp->pri.nodetype = PRI_NETWORK;
11332 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11333 confp->chan.sig = SIG_GR303FXSKS;
11334 confp->chan.radio = 0;
11335 confp->pri.nodetype = PRI_CPE;
11336 #endif
11337 } else {
11338 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11340 } else if (!strcasecmp(v->name, "outsignalling")) {
11341 if (!strcasecmp(v->value, "em")) {
11342 confp->chan.outsigmod = SIG_EM;
11343 } else if (!strcasecmp(v->value, "em_e1")) {
11344 confp->chan.outsigmod = SIG_EM_E1;
11345 } else if (!strcasecmp(v->value, "em_w")) {
11346 confp->chan.outsigmod = SIG_EMWINK;
11347 } else if (!strcasecmp(v->value, "sf")) {
11348 confp->chan.outsigmod = SIG_SF;
11349 } else if (!strcasecmp(v->value, "sf_w")) {
11350 confp->chan.outsigmod = SIG_SFWINK;
11351 } else if (!strcasecmp(v->value, "sf_featd")) {
11352 confp->chan.outsigmod = SIG_FEATD;
11353 } else if (!strcasecmp(v->value, "sf_featdmf")) {
11354 confp->chan.outsigmod = SIG_FEATDMF;
11355 } else if (!strcasecmp(v->value, "sf_featb")) {
11356 confp->chan.outsigmod = SIG_SF_FEATB;
11357 } else if (!strcasecmp(v->value, "sf")) {
11358 confp->chan.outsigmod = SIG_SF;
11359 } else if (!strcasecmp(v->value, "featd")) {
11360 confp->chan.outsigmod = SIG_FEATD;
11361 } else if (!strcasecmp(v->value, "featdmf")) {
11362 confp->chan.outsigmod = SIG_FEATDMF;
11363 } else if (!strcasecmp(v->value, "featdmf_ta")) {
11364 confp->chan.outsigmod = SIG_FEATDMF_TA;
11365 } else if (!strcasecmp(v->value, "e911")) {
11366 confp->chan.outsigmod = SIG_E911;
11367 } else if (!strcasecmp(v->value, "fgccama")) {
11368 confp->chan.outsigmod = SIG_FGC_CAMA;
11369 } else if (!strcasecmp(v->value, "fgccamamf")) {
11370 confp->chan.outsigmod = SIG_FGC_CAMAMF;
11371 } else if (!strcasecmp(v->value, "featb")) {
11372 confp->chan.outsigmod = SIG_FEATB;
11373 } else {
11374 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11376 #ifdef HAVE_PRI
11377 } else if (!strcasecmp(v->name, "pridialplan")) {
11378 if (!strcasecmp(v->value, "national")) {
11379 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11380 } else if (!strcasecmp(v->value, "unknown")) {
11381 confp->pri.dialplan = PRI_UNKNOWN + 1;
11382 } else if (!strcasecmp(v->value, "private")) {
11383 confp->pri.dialplan = PRI_PRIVATE + 1;
11384 } else if (!strcasecmp(v->value, "international")) {
11385 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11386 } else if (!strcasecmp(v->value, "local")) {
11387 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11388 } else if (!strcasecmp(v->value, "dynamic")) {
11389 confp->pri.dialplan = -1;
11390 } else {
11391 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11393 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11394 if (!strcasecmp(v->value, "national")) {
11395 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11396 } else if (!strcasecmp(v->value, "unknown")) {
11397 confp->pri.localdialplan = PRI_UNKNOWN + 1;
11398 } else if (!strcasecmp(v->value, "private")) {
11399 confp->pri.localdialplan = PRI_PRIVATE + 1;
11400 } else if (!strcasecmp(v->value, "international")) {
11401 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11402 } else if (!strcasecmp(v->value, "local")) {
11403 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11404 } else if (!strcasecmp(v->value, "dynamic")) {
11405 confp->pri.localdialplan = -1;
11406 } else {
11407 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11409 } else if (!strcasecmp(v->name, "switchtype")) {
11410 if (!strcasecmp(v->value, "national"))
11411 confp->pri.switchtype = PRI_SWITCH_NI2;
11412 else if (!strcasecmp(v->value, "ni1"))
11413 confp->pri.switchtype = PRI_SWITCH_NI1;
11414 else if (!strcasecmp(v->value, "dms100"))
11415 confp->pri.switchtype = PRI_SWITCH_DMS100;
11416 else if (!strcasecmp(v->value, "4ess"))
11417 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11418 else if (!strcasecmp(v->value, "5ess"))
11419 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11420 else if (!strcasecmp(v->value, "euroisdn"))
11421 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11422 else if (!strcasecmp(v->value, "qsig"))
11423 confp->pri.switchtype = PRI_SWITCH_QSIG;
11424 else {
11425 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11426 return -1;
11428 } else if (!strcasecmp(v->name, "nsf")) {
11429 if (!strcasecmp(v->value, "sdn"))
11430 confp->pri.nsf = PRI_NSF_SDN;
11431 else if (!strcasecmp(v->value, "megacom"))
11432 confp->pri.nsf = PRI_NSF_MEGACOM;
11433 else if (!strcasecmp(v->value, "tollfreemegacom"))
11434 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
11435 else if (!strcasecmp(v->value, "accunet"))
11436 confp->pri.nsf = PRI_NSF_ACCUNET;
11437 else if (!strcasecmp(v->value, "none"))
11438 confp->pri.nsf = PRI_NSF_NONE;
11439 else {
11440 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11441 confp->pri.nsf = PRI_NSF_NONE;
11443 } else if (!strcasecmp(v->name, "priindication")) {
11444 if (!strcasecmp(v->value, "outofband"))
11445 confp->chan.priindication_oob = 1;
11446 else if (!strcasecmp(v->value, "inband"))
11447 confp->chan.priindication_oob = 0;
11448 else
11449 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11450 v->value, v->lineno);
11451 } else if (!strcasecmp(v->name, "priexclusive")) {
11452 confp->chan.priexclusive = ast_true(v->value);
11453 } else if (!strcasecmp(v->name, "internationalprefix")) {
11454 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11455 } else if (!strcasecmp(v->name, "nationalprefix")) {
11456 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11457 } else if (!strcasecmp(v->name, "localprefix")) {
11458 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11459 } else if (!strcasecmp(v->name, "privateprefix")) {
11460 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11461 } else if (!strcasecmp(v->name, "unknownprefix")) {
11462 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11463 } else if (!strcasecmp(v->name, "resetinterval")) {
11464 if (!strcasecmp(v->value, "never"))
11465 confp->pri.resetinterval = -1;
11466 else if (atoi(v->value) >= 60)
11467 confp->pri.resetinterval = atoi(v->value);
11468 else
11469 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11470 v->value, v->lineno);
11471 } else if (!strcasecmp(v->name, "minunused")) {
11472 confp->pri.minunused = atoi(v->value);
11473 } else if (!strcasecmp(v->name, "minidle")) {
11474 confp->pri.minidle = atoi(v->value);
11475 } else if (!strcasecmp(v->name, "idleext")) {
11476 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11477 } else if (!strcasecmp(v->name, "idledial")) {
11478 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11479 } else if (!strcasecmp(v->name, "overlapdial")) {
11480 confp->pri.overlapdial = ast_true(v->value);
11481 #ifdef HAVE_PRI_INBANDDISCONNECT
11482 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11483 confp->pri.inbanddisconnect = ast_true(v->value);
11484 #endif
11485 } else if (!strcasecmp(v->name, "pritimer")) {
11486 #ifdef PRI_GETSET_TIMERS
11487 char *timerc, *c;
11488 int timer, timeridx;
11489 c = v->value;
11490 timerc = strsep(&c, ",");
11491 if (timerc) {
11492 timer = atoi(c);
11493 if (!timer)
11494 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
11495 else {
11496 if ((timeridx = pri_timer2idx(timerc)) >= 0)
11497 pritimers[timeridx] = timer;
11498 else
11499 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
11501 } else
11502 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
11504 } else if (!strcasecmp(v->name, "facilityenable")) {
11505 confp->pri.facilityenable = ast_true(v->value);
11506 #endif /* PRI_GETSET_TIMERS */
11507 #endif /* HAVE_PRI */
11508 } else if (!strcasecmp(v->name, "cadence")) {
11509 /* setup to scan our argument */
11510 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11511 int i;
11512 struct dahdi_ring_cadence new_cadence;
11513 int cid_location = -1;
11514 int firstcadencepos = 0;
11515 char original_args[80];
11516 int cadence_is_ok = 1;
11518 ast_copy_string(original_args, v->value, sizeof(original_args));
11519 /* 16 cadences allowed (8 pairs) */
11520 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]);
11522 /* Cadence must be even (on/off) */
11523 if (element_count % 2 == 1) {
11524 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11525 cadence_is_ok = 0;
11528 /* Ring cadences cannot be negative */
11529 for (i = 0; i < element_count; i++) {
11530 if (c[i] == 0) {
11531 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11532 cadence_is_ok = 0;
11533 break;
11534 } else if (c[i] < 0) {
11535 if (i % 2 == 1) {
11536 /* Silence duration, negative possibly okay */
11537 if (cid_location == -1) {
11538 cid_location = i;
11539 c[i] *= -1;
11540 } else {
11541 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11542 cadence_is_ok = 0;
11543 break;
11545 } else {
11546 if (firstcadencepos == 0) {
11547 firstcadencepos = i; /* only recorded to avoid duplicate specification */
11548 /* duration will be passed negative to the DAHDI driver */
11549 } else {
11550 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11551 cadence_is_ok = 0;
11552 break;
11558 /* Substitute our scanned cadence */
11559 for (i = 0; i < 16; i++) {
11560 new_cadence.ringcadence[i] = c[i];
11563 if (cadence_is_ok) {
11564 /* ---we scanned it without getting annoyed; now some sanity checks--- */
11565 if (element_count < 2) {
11566 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11567 } else {
11568 if (cid_location == -1) {
11569 /* user didn't say; default to first pause */
11570 cid_location = 1;
11571 } else {
11572 /* convert element_index to cidrings value */
11573 cid_location = (cid_location + 1) / 2;
11575 /* ---we like their cadence; try to install it--- */
11576 if (!user_has_defined_cadences++)
11577 /* this is the first user-defined cadence; clear the default user cadences */
11578 num_cadence = 0;
11579 if ((num_cadence+1) >= NUM_CADENCE_MAX)
11580 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11581 else {
11582 cadences[num_cadence] = new_cadence;
11583 cidrings[num_cadence++] = cid_location;
11584 if (option_verbose > 2)
11585 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11589 } else if (!strcasecmp(v->name, "ringtimeout")) {
11590 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11591 } else if (!strcasecmp(v->name, "prewink")) {
11592 confp->timing.prewinktime = atoi(v->value);
11593 } else if (!strcasecmp(v->name, "preflash")) {
11594 confp->timing.preflashtime = atoi(v->value);
11595 } else if (!strcasecmp(v->name, "wink")) {
11596 confp->timing.winktime = atoi(v->value);
11597 } else if (!strcasecmp(v->name, "flash")) {
11598 confp->timing.flashtime = atoi(v->value);
11599 } else if (!strcasecmp(v->name, "start")) {
11600 confp->timing.starttime = atoi(v->value);
11601 } else if (!strcasecmp(v->name, "rxwink")) {
11602 confp->timing.rxwinktime = atoi(v->value);
11603 } else if (!strcasecmp(v->name, "rxflash")) {
11604 confp->timing.rxflashtime = atoi(v->value);
11605 } else if (!strcasecmp(v->name, "debounce")) {
11606 confp->timing.debouncetime = atoi(v->value);
11607 } else if (!strcasecmp(v->name, "toneduration")) {
11608 int toneduration;
11609 int ctlfd;
11610 int res;
11611 struct dahdi_dialparams dps;
11613 #ifdef HAVE_ZAPTEL
11614 ctlfd = open("/dev/zap/ctl", O_RDWR);
11615 #else
11616 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
11617 #endif
11619 if (ctlfd == -1) {
11620 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
11621 return -1;
11624 toneduration = atoi(v->value);
11625 if (toneduration > -1) {
11626 memset(&dps, 0, sizeof(dps));
11628 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
11629 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
11630 if (res < 0) {
11631 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
11632 return -1;
11635 close(ctlfd);
11636 } else if (!strcasecmp(v->name, "defaultcic")) {
11637 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
11638 } else if (!strcasecmp(v->name, "defaultozz")) {
11639 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
11641 } else if (!skipchannels)
11642 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
11644 if (dahdichan[0]) {
11645 /* The user has set 'dahdichan' */
11646 /*< \todo pass proper line number instead of 0 */
11647 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
11648 return -1;
11651 /*< \todo why check for the pseudo in the per-channel section.
11652 * Any actual use for manual setup of the pseudo channel? */
11653 if (!found_pseudo && reload == 0) {
11654 /* use the default configuration for a channel, so
11655 that any settings from real configured channels
11656 don't "leak" into the pseudo channel config
11658 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11660 tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
11662 if (tmp) {
11663 if (option_verbose > 2)
11664 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
11665 } else {
11666 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
11669 return 0;
11672 static int setup_dahdi(int reload)
11674 struct ast_config *cfg;
11675 struct ast_variable *v;
11676 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
11677 int res;
11679 #ifdef HAVE_PRI
11680 char *c;
11681 int spanno;
11682 int i, x;
11683 int logicalspan;
11684 int trunkgroup;
11685 int dchannels[NUM_DCHANS];
11686 #endif
11688 #ifdef HAVE_ZAPTEL
11689 int load_from_zapata_conf = 1;
11690 #else
11691 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
11692 #endif
11694 if (load_from_zapata_conf) {
11695 if (!(cfg = ast_config_load("zapata.conf"))) {
11696 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
11697 return 0;
11699 } else {
11700 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
11701 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
11702 return 0;
11706 /* It's a little silly to lock it, but we mind as well just to be sure */
11707 ast_mutex_lock(&iflock);
11708 #ifdef HAVE_PRI
11709 if (reload != 1) {
11710 /* Process trunkgroups first */
11711 v = ast_variable_browse(cfg, "trunkgroups");
11712 while (v) {
11713 if (!strcasecmp(v->name, "trunkgroup")) {
11714 trunkgroup = atoi(v->value);
11715 if (trunkgroup > 0) {
11716 if ((c = strchr(v->value, ','))) {
11717 i = 0;
11718 memset(dchannels, 0, sizeof(dchannels));
11719 while (c && (i < NUM_DCHANS)) {
11720 dchannels[i] = atoi(c + 1);
11721 if (dchannels[i] < 0) {
11722 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);
11723 } else
11724 i++;
11725 c = strchr(c + 1, ',');
11727 if (i) {
11728 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
11729 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);
11730 } else if (option_verbose > 1)
11731 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");
11732 } else
11733 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11734 } else
11735 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
11736 } else
11737 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
11738 } else if (!strcasecmp(v->name, "spanmap")) {
11739 spanno = atoi(v->value);
11740 if (spanno > 0) {
11741 if ((c = strchr(v->value, ','))) {
11742 trunkgroup = atoi(c + 1);
11743 if (trunkgroup > 0) {
11744 if ((c = strchr(c + 1, ',')))
11745 logicalspan = atoi(c + 1);
11746 else
11747 logicalspan = 0;
11748 if (logicalspan >= 0) {
11749 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
11750 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11751 } else if (option_verbose > 1)
11752 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
11753 } else
11754 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);
11755 } else
11756 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
11757 } else
11758 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
11759 } else
11760 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
11761 } else {
11762 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
11764 v = v->next;
11767 #endif
11769 /* Copy the default jb config over global_jbconf */
11770 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
11772 v = ast_variable_browse(cfg, "channels");
11773 res = process_dahdi(&conf, "", v, reload, 0);
11774 ast_mutex_unlock(&iflock);
11775 ast_config_destroy(cfg);
11776 if (res)
11777 return res;
11778 cfg = ast_config_load("users.conf");
11779 if (cfg) {
11780 char *cat;
11781 const char *chans;
11782 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
11783 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
11784 if (!strcasecmp(cat, "general"))
11785 continue;
11786 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
11787 if (!ast_strlen_zero(chans)) {
11788 struct dahdi_chan_conf sect_conf;
11789 memcpy(&sect_conf, &conf, sizeof(sect_conf));
11791 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
11794 ast_config_destroy(cfg);
11796 #ifdef HAVE_PRI
11797 if (reload != 1) {
11798 for (x = 0; x < NUM_SPANS; x++) {
11799 if (pris[x].pvts[0]) {
11800 if (start_pri(pris + x)) {
11801 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
11802 return -1;
11803 } else if (option_verbose > 1)
11804 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
11808 #endif
11809 /* And start the monitor for the first time */
11810 restart_monitor();
11811 return 0;
11814 #define local_astman_register(a, b, c, d) do { \
11815 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
11816 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
11818 ast_manager_register("Zap" a, b, zap_ ## c, d); \
11819 } while (0)
11821 static int load_module(void)
11823 int res;
11825 #ifdef HAVE_PRI
11826 int y,i;
11827 memset(pris, 0, sizeof(pris));
11828 for (y = 0; y < NUM_SPANS; y++) {
11829 ast_mutex_init(&pris[y].lock);
11830 pris[y].offset = -1;
11831 pris[y].master = AST_PTHREADT_NULL;
11832 for (i = 0; i < NUM_DCHANS; i++)
11833 pris[y].fds[i] = -1;
11835 pri_set_error(dahdi_pri_error);
11836 pri_set_message(dahdi_pri_message);
11837 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11838 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
11839 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
11841 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
11842 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
11843 #endif
11844 if ((res = setup_dahdi(0))) {
11845 return AST_MODULE_LOAD_DECLINE;
11847 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11848 chan_tech = &dahdi_tech;
11849 } else {
11850 chan_tech = &zap_tech;
11852 if (ast_channel_register(chan_tech)) {
11853 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
11854 __unload_module();
11855 return -1;
11857 #ifdef HAVE_PRI
11858 ast_string_field_init(&inuse, 16);
11859 ast_string_field_set(&inuse, name, "GR-303InUse");
11860 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11861 #endif
11862 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11864 memset(round_robin, 0, sizeof(round_robin));
11865 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
11866 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
11867 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
11868 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
11869 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
11870 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
11871 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
11873 ast_cond_init(&ss_thread_complete, NULL);
11875 return res;
11878 static int dahdi_sendtext(struct ast_channel *c, const char *text)
11880 #define END_SILENCE_LEN 400
11881 #define HEADER_MS 50
11882 #define TRAILER_MS 5
11883 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
11884 #define ASCII_BYTES_PER_CHAR 80
11886 unsigned char *buf,*mybuf;
11887 struct dahdi_pvt *p = c->tech_pvt;
11888 struct pollfd fds[1];
11889 int size,res,fd,len,x;
11890 int bytes=0;
11891 /* Initial carrier (imaginary) */
11892 float cr = 1.0;
11893 float ci = 0.0;
11894 float scont = 0.0;
11895 int index;
11897 index = dahdi_get_index(c, p, 0);
11898 if (index < 0) {
11899 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
11900 return -1;
11902 if (!text[0]) return(0); /* if nothing to send, dont */
11903 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
11904 if (p->mate)
11905 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
11906 else
11907 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
11908 if (!buf)
11909 return -1;
11910 mybuf = buf;
11911 if (p->mate) {
11912 int codec = AST_LAW(p);
11913 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
11914 PUT_CLID_MARKMS;
11916 /* Put actual message */
11917 for (x = 0; text[x]; x++) {
11918 PUT_CLID(text[x]);
11920 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
11921 PUT_CLID_MARKMS;
11923 len = bytes;
11924 buf = mybuf;
11925 } else {
11926 len = tdd_generate(p->tdd, buf, text);
11927 if (len < 1) {
11928 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
11929 free(mybuf);
11930 return -1;
11933 memset(buf + len, 0x7f, END_SILENCE_LEN);
11934 len += END_SILENCE_LEN;
11935 fd = p->subs[index].dfd;
11936 while (len) {
11937 if (ast_check_hangup(c)) {
11938 free(mybuf);
11939 return -1;
11941 size = len;
11942 if (size > READ_SIZE)
11943 size = READ_SIZE;
11944 fds[0].fd = fd;
11945 fds[0].events = POLLOUT | POLLPRI;
11946 fds[0].revents = 0;
11947 res = poll(fds, 1, -1);
11948 if (!res) {
11949 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
11950 continue;
11952 /* if got exception */
11953 if (fds[0].revents & POLLPRI) {
11954 ast_free(mybuf);
11955 return -1;
11957 if (!(fds[0].revents & POLLOUT)) {
11958 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
11959 continue;
11961 res = write(fd, buf, size);
11962 if (res != size) {
11963 if (res == -1) {
11964 free(mybuf);
11965 return -1;
11967 if (option_debug)
11968 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
11969 break;
11971 len -= size;
11972 buf += size;
11974 free(mybuf);
11975 return(0);
11979 static int reload(void)
11981 int res = 0;
11983 res = setup_dahdi(1);
11984 if (res) {
11985 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
11986 return -1;
11988 return 0;
11991 /* This is a workaround so that menuselect displays a proper description
11992 * AST_MODULE_INFO(, , "DAHDI Telephony"
11995 #ifdef DAHDI_PRI
11996 #define tdesc "DAHDI Telephony w/PRI"
11997 #else
11998 #define tdesc "DAHDI Telephony"
11999 #endif
12001 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
12002 .load = load_module,
12003 .unload = unload_module,
12004 .reload = reload,