Remove a separate case for 0 gain on digital channels
[asterisk-bristuff.git] / channels / chan_dahdi.c
blob35c4e4e5ce8b0a8b76aa625b04f7c8d96c650e19
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 * Copyright (C) 2003-2006 Junghanns.NET GmbH
15 * Klaus-Peter Junghanns <kpj@junghanns.net>
18 * This program is free software, distributed under the terms of
19 * the GNU General Public License Version 2. See the LICENSE file
20 * at the top of the source tree.
23 /*! \file
25 * \brief DAHDI Pseudo TDM interface
27 * \author Mark Spencer <markster@digium.com>
29 * Connects to the DAHDI telephony library as well as
30 * libpri. Libpri is optional and needed only if you are
31 * going to use ISDN connections.
33 * You need to install libraries before you attempt to compile
34 * and install the DAHDI channel.
36 * \par See also
37 * \arg \ref Config_dahdi
39 * \ingroup channel_drivers
41 * \todo Deprecate the "musiconhold" configuration option post 1.4
44 /*** MODULEINFO
45 <depend>res_smdi</depend>
46 <depend>dahdi</depend>
47 <depend>tonezone</depend>
48 <depend>res_features</depend>
49 <use>pri</use>
50 ***/
52 #include "asterisk.h"
54 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
56 #include <stdio.h>
57 #include <string.h>
58 #ifdef __NetBSD__
59 #include <pthread.h>
60 #include <signal.h>
61 #else
62 #include <sys/signal.h>
63 #endif
64 #include <errno.h>
65 #include <stdlib.h>
66 #if !defined(SOLARIS) && !defined(__FreeBSD__)
67 #include <stdint.h>
68 #endif
69 #include <unistd.h>
70 #include <sys/ioctl.h>
71 #include <math.h>
72 #include <ctype.h>
74 #ifdef HAVE_PRI
75 #include <libpri.h>
76 #endif
77 #ifdef HAVE_GSMAT
78 #include <libgsmat.h>
79 #endif
81 #include "asterisk/lock.h"
82 #include "asterisk/channel.h"
83 #include "asterisk/config.h"
84 #include "asterisk/logger.h"
85 #include "asterisk/module.h"
86 #include "asterisk/pbx.h"
87 #include "asterisk/options.h"
88 #include "asterisk/file.h"
89 #include "asterisk/ulaw.h"
90 #include "asterisk/alaw.h"
91 #include "asterisk/callerid.h"
92 #include "asterisk/adsi.h"
93 #include "asterisk/cli.h"
94 #include "asterisk/cdr.h"
95 #include "asterisk/features.h"
96 #include "asterisk/musiconhold.h"
97 #include "asterisk/say.h"
98 #include "asterisk/tdd.h"
99 #include "asterisk/app.h"
100 #include "asterisk/dsp.h"
101 #include "asterisk/astdb.h"
102 #include "asterisk/manager.h"
103 #include "asterisk/causes.h"
104 #include "asterisk/term.h"
105 #include "asterisk/utils.h"
106 #include "asterisk/transcap.h"
107 #include "asterisk/stringfields.h"
108 #include "asterisk/abstract_jb.h"
109 #include "asterisk/smdi.h"
110 #include "asterisk/astobj.h"
111 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
113 #include "asterisk/dahdi_compat.h"
114 #include "asterisk/tonezone_compat.h"
116 /*! Global jitterbuffer configuration - by default, jb is disabled */
117 static struct ast_jb_conf default_jbconf =
119 .flags = 0,
120 .max_size = -1,
121 .resync_threshold = -1,
122 .impl = ""
124 static struct ast_jb_conf global_jbconf;
126 #ifndef DAHDI_TONEDETECT
127 /* Work around older code with no tone detect */
128 #define DAHDI_EVENT_DTMFDOWN 0
129 #define DAHDI_EVENT_DTMFUP 0
130 #endif
132 /* define this to send PRI user-user information elements */
133 #undef SUPPORT_USERUSER
135 /*!
136 * \note Define ZHONE_HACK to cause us to go off hook and then back on hook when
137 * the user hangs up to reset the state machine so ring works properly.
138 * This is used to be able to support kewlstart by putting the zhone in
139 * groundstart mode since their forward disconnect supervision is entirely
140 * broken even though their documentation says it isn't and their support
141 * is entirely unwilling to provide any assistance with their channel banks
142 * even though their web site says they support their products for life.
144 /* #define ZHONE_HACK */
146 /*! \note
147 * Define if you want to check the hook state for an FXO (FXS signalled) interface
148 * before dialing on it. Certain FXO interfaces always think they're out of
149 * service with this method however.
151 /* #define DAHDI_CHECK_HOOKSTATE */
153 /*! \brief Typically, how many rings before we should send Caller*ID */
154 #define DEFAULT_CIDRINGS 1
156 #define CHANNEL_PSEUDO -12
158 #define AST_LAW(p) (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
160 /*! \brief Signaling types that need to use MF detection should be placed in this macro */
161 #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))
163 static const char tdesc[] = "DAHDI Telephony Driver"
164 #ifdef HAVE_PRI
165 " w/PRI"
166 #endif
169 #define SIG_EM DAHDI_SIG_EM
170 #define SIG_EMWINK (0x0100000 | DAHDI_SIG_EM)
171 #define SIG_FEATD (0x0200000 | DAHDI_SIG_EM)
172 #define SIG_FEATDMF (0x0400000 | DAHDI_SIG_EM)
173 #define SIG_FEATB (0x0800000 | DAHDI_SIG_EM)
174 #define SIG_E911 (0x1000000 | DAHDI_SIG_EM)
175 #define SIG_FEATDMF_TA (0x2000000 | DAHDI_SIG_EM)
176 #define SIG_FGC_CAMA (0x4000000 | DAHDI_SIG_EM)
177 #define SIG_FGC_CAMAMF (0x8000000 | DAHDI_SIG_EM)
178 #define SIG_FXSLS DAHDI_SIG_FXSLS
179 #define SIG_FXSGS DAHDI_SIG_FXSGS
180 #define SIG_FXSKS DAHDI_SIG_FXSKS
181 #define SIG_FXOLS DAHDI_SIG_FXOLS
182 #define SIG_FXOGS DAHDI_SIG_FXOGS
183 #define SIG_FXOKS DAHDI_SIG_FXOKS
184 #define SIG_PRI DAHDI_SIG_CLEAR
185 #define SIG_GSM (0x100000 | DAHDI_SIG_CLEAR)
186 #define SIG_SF DAHDI_SIG_SF
187 #define SIG_SFWINK (0x0100000 | DAHDI_SIG_SF)
188 #define SIG_SF_FEATD (0x0200000 | DAHDI_SIG_SF)
189 #define SIG_SF_FEATDMF (0x0400000 | DAHDI_SIG_SF)
190 #define SIG_SF_FEATB (0x0800000 | DAHDI_SIG_SF)
191 #define SIG_EM_E1 DAHDI_SIG_EM_E1
192 #define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
193 #define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
195 #define NUM_SPANS DAHDI_MAX_SPANS /*!< no. of spans: DAHDI limitation */
196 #define NUM_DCHANS 4 /*!< No more than 4 d-channels */
197 #define MAX_CHANNELS 672 /*!< No more than a DS3 per trunk group */
199 #define CHAN_PSEUDO -2
201 #define DCHAN_PROVISIONED (1 << 0)
202 #define DCHAN_NOTINALARM (1 << 1)
203 #define DCHAN_UP (1 << 2)
205 #define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
207 static char defaultcic[64] = "";
208 static char defaultozz[64] = "";
210 static char progzone[10] = "";
212 static int distinctiveringaftercid = 0;
214 static int numbufs = 4;
216 #ifdef HAVE_PRI
217 static struct ast_channel inuse;
218 #ifdef PRI_GETSET_TIMERS
219 static int pritimers[PRI_MAX_TIMERS];
220 #endif
221 #endif
223 /*! \brief Wait up to 16 seconds for first digit (FXO logic) */
224 static int firstdigittimeout = 16000;
226 /*! \brief How long to wait for following digits (FXO logic) */
227 static int gendigittimeout = 8000;
229 /*! \brief How long to wait for an extra digit, if there is an ambiguous match */
230 static int matchdigittimeout = 3000;
232 /*! \brief Protect the interface list (of dahdi_pvt's) */
233 AST_MUTEX_DEFINE_STATIC(iflock);
235 static char gsm_modem_pin[20];
236 static char gsm_modem_exten[AST_MAX_EXTENSION];
238 static int ifcount = 0;
240 /*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
241 when it's doing something critical. */
242 AST_MUTEX_DEFINE_STATIC(monlock);
244 /*! \brief This is the thread for the monitor which checks for input on the channels
245 which are not currently in use. */
246 static pthread_t monitor_thread = AST_PTHREADT_NULL;
247 static ast_cond_t ss_thread_complete;
248 AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
249 AST_MUTEX_DEFINE_STATIC(restart_lock);
250 static int ss_thread_count = 0;
251 static int num_restart_pending = 0;
253 static int restart_monitor(void);
255 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);
257 static int dahdi_sendtext(struct ast_channel *c, const char *text);
259 static int dahdi_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
261 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
262 static inline int dahdi_get_event(int fd)
264 int j;
265 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
266 return -1;
267 return j;
270 /*! \brief Avoid the silly dahdi_waitevent which ignores a bunch of events */
271 static inline int dahdi_wait_event(int fd)
273 int i, j = 0;
274 i = DAHDI_IOMUX_SIGEVENT;
275 if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
276 return -1;
277 if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
278 return -1;
279 return j;
282 /*! Chunk size to read -- we use 20ms chunks to make things happy. */
283 #define READ_SIZE 160
285 #define MASK_AVAIL (1 << 0) /*!< Channel available for PRI use */
286 #define MASK_INUSE (1 << 1) /*!< Channel currently in use */
288 #define CALLWAITING_SILENT_SAMPLES ( (300 * 8) / READ_SIZE) /*!< 300 ms */
289 #define CALLWAITING_REPEAT_SAMPLES ( (10000 * 8) / READ_SIZE) /*!< 10,000 ms */
290 #define CIDCW_EXPIRE_SAMPLES ( (500 * 8) / READ_SIZE) /*!< 500 ms */
291 #define MIN_MS_SINCE_FLASH ( (2000) ) /*!< 2000 ms */
292 #define DEFAULT_RINGT ( (8000 * 8) / READ_SIZE) /*!< 8,000 ms */
294 struct dahdi_pvt;
296 static int ringt_base = DEFAULT_RINGT;
298 #ifdef HAVE_PRI
300 #define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
301 #define PRI_CHANNEL(p) ((p) & 0xff)
302 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
303 #define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
305 struct dahdi_suspended_call {
306 ast_mutex_t lock; /* Mutex */
307 char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
308 char callid[10]; /* the callID provided by the user */
309 int parked_at; /* extension in the call parking context */
310 struct dahdi_suspended_call *next;
313 struct dahdi_holded_call {
314 ast_mutex_t lock; /* Mutex */
315 char msn[AST_MAX_EXTENSION]; /* the MSN to which this parked call belongs */
316 char uniqueid[AST_MAX_EXTENSION]; /* unique id of the onhold channel */
317 int tei;
318 int cref;
319 int alreadyhungup;
320 struct ast_channel *channel;
321 struct ast_channel *bridge;
322 q931_call *call; /* this also covers tei mumbojumbo */
323 struct dahdi_holded_call *next;
326 struct dahdi_pri {
327 pthread_t master; /*!< Thread of master */
328 ast_mutex_t lock; /*!< Mutex */
329 char idleext[AST_MAX_EXTENSION]; /*!< Where to idle extra calls */
330 char idlecontext[AST_MAX_CONTEXT]; /*!< What context to use for idle */
331 char idledial[AST_MAX_EXTENSION]; /*!< What to dial before dumping */
332 int minunused; /*!< Min # of channels to keep empty */
333 int minidle; /*!< Min # of "idling" calls to keep active */
334 int nodetype; /*!< Node type */
335 int switchtype; /*!< Type of switch to emulate */
336 int nsf; /*!< Network-Specific Facilities */
337 int dialplan; /*!< Dialing plan */
338 int localdialplan; /*!< Local dialing plan */
339 char nocid[AST_MAX_EXTENSION]; /*!< CallerID string to use if none provided */
340 char withheldcid[AST_MAX_EXTENSION]; /*!< CallerID string to use if CallerID is withheld */
341 char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
342 char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
343 char localprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
344 char privateprefix[20]; /*!< for private dialplans */
345 char unknownprefix[20]; /*!< for unknown dialplans */
346 int dchannels[NUM_DCHANS]; /*!< What channel are the dchannels on */
347 int trunkgroup; /*!< What our trunkgroup is */
348 int mastertrunkgroup; /*!< What trunk group is our master */
349 int prilogicalspan; /*!< Logical span number within trunk group */
350 int numchans; /*!< Num of channels we represent */
351 int overlapdial; /*!< In overlap dialing mode */
352 int facilityenable; /*!< Enable facility IEs */
353 struct pri *dchans[NUM_DCHANS]; /*!< Actual d-channels */
354 int dchanavail[NUM_DCHANS]; /*!< Whether each channel is available */
355 struct pri *pri; /*!< Currently active D-channel */
356 int debug;
357 int fds[NUM_DCHANS]; /*!< FD's for d-channels */
358 int offset;
359 int span;
360 int resetting;
361 int resetpos;
362 #ifdef HAVE_PRI_INBANDDISCONNECT
363 unsigned int inbanddisconnect:1; /*!< Should we support inband audio after receiving DISCONNECT? */
364 #endif
365 time_t lastreset; /*!< time when unused channels were last reset */
366 long resetinterval; /*!< Interval (in seconds) for resetting unused channels */
367 struct dahdi_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
368 struct dahdi_pvt *crvs; /*!< Member CRV structs */
369 struct dahdi_pvt *crvend; /*!< Pointer to end of CRV structs */
370 struct dahdi_suspended_call *suspended_calls; /* Calls parked with SUSPEND messages */
371 struct dahdi_holded_call *holded_calls; /* Calls on hold */
372 int debugfd;
375 #ifdef HAVE_GSMAT
376 struct dahdi_gsm {
377 pthread_t master;
378 ast_mutex_t lock; /* Mutex */
379 int fd;
380 int span;
381 struct gsm_modul *modul;
382 char pin[256];
383 int available;
384 char exten[AST_MAX_EXTENSION]; /* Where to idle extra calls */
385 struct dahdi_pvt *pvt;
387 #endif
389 static struct dahdi_pri pris[NUM_SPANS];
391 #if 0
392 #define DEFAULT_PRI_DEBUG (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_STATE)
393 #else
394 #define DEFAULT_PRI_DEBUG 0
395 #endif
397 static inline void pri_rel(struct dahdi_pri *pri)
399 ast_mutex_unlock(&pri->lock);
402 #else
403 /*! Shut up the compiler */
404 struct dahdi_pri;
405 #endif
407 #define SUB_REAL 0 /*!< Active call */
408 #define SUB_CALLWAIT 1 /*!< Call-Waiting call on hold */
409 #define SUB_THREEWAY 2 /*!< Three-way call */
411 /* Polarity states */
412 #define POLARITY_IDLE 0
413 #define POLARITY_REV 1
416 static struct dahdi_distRings drings;
418 struct distRingData {
419 int ring[3];
421 struct ringContextData {
422 char contextData[AST_MAX_CONTEXT];
424 struct dahdi_distRings {
425 struct distRingData ringnum[3];
426 struct ringContextData ringContext[3];
429 static char *subnames[] = {
430 "Real",
431 "Callwait",
432 "Threeway"
435 struct dahdi_subchannel {
436 int dfd;
437 struct ast_channel *owner;
438 int chan;
439 short buffer[AST_FRIENDLY_OFFSET/2 + READ_SIZE];
440 struct ast_frame f; /*!< One frame for each channel. How did this ever work before? */
441 unsigned int needringing:1;
442 unsigned int needbusy:1;
443 unsigned int needcongestion:1;
444 unsigned int needcallerid:1;
445 unsigned int needanswer:1;
446 unsigned int needflash:1;
447 unsigned int needhold:1;
448 unsigned int needunhold:1;
449 unsigned int linear:1;
450 unsigned int inthreeway:1;
451 struct dahdi_confinfo curconf;
454 #define CONF_USER_REAL (1 << 0)
455 #define CONF_USER_THIRDCALL (1 << 1)
457 #define MAX_SLAVES 4
459 static struct dahdi_pvt {
460 ast_mutex_t lock;
461 struct ast_channel *owner; /*!< Our current active owner (if applicable) */
462 /*!< Up to three channels can be associated with this call */
464 struct dahdi_subchannel sub_unused; /*!< Just a safety precaution */
465 struct dahdi_subchannel subs[3]; /*!< Sub-channels */
466 struct dahdi_confinfo saveconf; /*!< Saved conference info */
468 struct dahdi_pvt *slaves[MAX_SLAVES]; /*!< Slave to us (follows our conferencing) */
469 struct dahdi_pvt *master; /*!< Master to us (we follow their conferencing) */
470 int inconference; /*!< If our real should be in the conference */
472 int buf_no; /*!< Number of buffers */
473 int buf_policy; /*!< Buffer policy */
474 int sig; /*!< Signalling style */
475 int radio; /*!< radio type */
476 int outsigmod; /*!< Outbound Signalling style (modifier) */
477 int oprmode; /*!< "Operator Services" mode */
478 struct dahdi_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
479 float rxgain;
480 float txgain;
481 int tonezone; /*!< tone zone for this chan, or -1 for default */
482 struct dahdi_pvt *next; /*!< Next channel in list */
483 struct dahdi_pvt *prev; /*!< Prev channel in list */
485 /* flags */
486 unsigned int adsi:1;
487 unsigned int answeronpolarityswitch:1;
488 unsigned int busydetect:1;
489 unsigned int callreturn:1;
490 unsigned int callwaiting:1;
491 unsigned int callwaitingcallerid:1;
492 unsigned int cancallforward:1;
493 unsigned int canpark:1;
494 unsigned int confirmanswer:1; /*!< Wait for '#' to confirm answer */
495 unsigned int destroy:1;
496 unsigned int didtdd:1; /*!< flag to say its done it once */
497 unsigned int dialednone:1;
498 unsigned int dialing:1;
499 unsigned int digital:1;
500 unsigned int dnd:1;
501 unsigned int echobreak:1;
502 unsigned int echocanbridged:1;
503 unsigned int echocanon:1;
504 unsigned int faxhandled:1; /*!< Has a fax tone already been handled? */
505 /*!< KPJ: i will abuse this flag to implement a zapata option for dialing out
506 on a zap channel with EC to be off no matter what happens. */
507 unsigned int firstradio:1;
508 unsigned int hanguponpolarityswitch:1;
509 unsigned int hardwaredtmf:1;
510 unsigned int hidecallerid:1;
511 unsigned int hidecalleridname:1; /*!< Hide just the name not the number for legacy PBX use */
512 unsigned int ignoredtmf:1;
513 unsigned int immediate:1; /*!< Answer before getting digits? */
514 unsigned int inalarm:1;
515 unsigned int unknown_alarm:1;
516 unsigned int mate:1; /*!< flag to say its in MATE mode */
517 unsigned int outgoing:1;
518 unsigned int overlapdial:1;
519 unsigned int permcallwaiting:1;
520 unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
521 unsigned int priindication_oob:2;
522 unsigned int pritransfer:2;
523 unsigned int priexclusive:1;
524 unsigned int pulse:1;
525 unsigned int pulsedial:1; /*!< whether a pulse dial phone is detected */
526 unsigned int restartpending:1; /*!< flag to ensure counted only once for restart */
527 unsigned int restrictcid:1; /*!< Whether restrict the callerid -> only send ANI */
528 unsigned int threewaycalling:1;
529 unsigned int transfer:1;
530 unsigned int use_callerid:1; /*!< Whether or not to use caller id on this channel */
531 unsigned int use_callingpres:1; /*!< Whether to use the callingpres the calling switch sends */
532 unsigned int usedistinctiveringdetection:1;
533 unsigned int dahditrcallerid:1; /*!< should we use the callerid from incoming call on dahdi transfer or not */
534 unsigned int transfertobusy:1; /*!< allow flash-transfers to busy channels */
535 #if defined(HAVE_PRI)
536 unsigned int alerting:1;
537 unsigned int alreadyhungup:1;
538 unsigned int isidlecall:1;
539 unsigned int proceeding:1;
540 unsigned int progress:1;
541 unsigned int resetting:1;
542 unsigned int setup_ack:1;
543 #endif
544 unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
545 struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
547 struct dahdi_distRings drings;
549 char context[AST_MAX_CONTEXT];
550 char defcontext[AST_MAX_CONTEXT];
551 char exten[AST_MAX_EXTENSION];
552 char language[MAX_LANGUAGE];
553 char mohinterpret[MAX_MUSICCLASS];
554 char mohsuggest[MAX_MUSICCLASS];
555 #ifdef PRI_ANI
556 char cid_ani[AST_MAX_EXTENSION];
557 #endif
558 char cid_num[AST_MAX_EXTENSION];
559 int cid_ton; /*!< Type Of Number (TON) */
560 int cid_pres; /*!< Calling Presentation */
561 char cid_name[AST_MAX_EXTENSION];
562 char lastcid_num[AST_MAX_EXTENSION];
563 char lastcid_name[AST_MAX_EXTENSION];
564 char *origcid_num; /*!< malloced original callerid */
565 char *origcid_name; /*!< malloced original callerid */
566 char callwait_num[AST_MAX_EXTENSION];
567 char callwait_name[AST_MAX_EXTENSION];
568 char rdnis[AST_MAX_EXTENSION];
569 char dnid[AST_MAX_EXTENSION];
570 ast_group_t group;
571 int law;
572 int confno; /*!< Our conference */
573 int confusers; /*!< Who is using our conference */
574 int propconfno; /*!< Propagated conference number */
575 ast_group_t callgroup;
576 ast_group_t pickupgroup;
577 int channel; /*!< Channel Number or CRV */
578 int span; /*!< Span number */
579 time_t guardtime; /*!< Must wait this much time before using for new call */
580 int cid_signalling; /*!< CID signalling type bell202 or v23 */
581 int cid_start; /*!< CID start indicator, polarity or ring */
582 int callingpres; /*!< The value of callling presentation that we're going to use when placing a PRI call */
583 int callwaitingrepeat; /*!< How many samples to wait before repeating call waiting */
584 int cidcwexpire; /*!< When to expire our muting for CID/CW */
585 unsigned char *cidspill;
586 int cidpos;
587 int cidlen;
588 int ringt;
589 int ringt_base;
590 int stripmsd;
591 int callwaitcas;
592 int callwaitrings;
593 int echocancel;
594 int echotraining;
595 char echorest[20];
596 int busycount;
597 int busy_tonelength;
598 int busy_quietlength;
599 int callprogress;
600 struct timeval flashtime; /*!< Last flash-hook time */
601 struct ast_dsp *dsp;
602 int cref; /*!< Call reference number */
603 struct dahdi_dialoperation dop;
604 int whichwink; /*!< SIG_FEATDMF_TA Which wink are we on? */
605 char finaldial[64];
606 char accountcode[AST_MAX_ACCOUNT_CODE]; /*!< Account code */
607 int amaflags; /*!< AMA Flags */
608 struct tdd_state *tdd; /*!< TDD flag */
609 char call_forward[AST_MAX_EXTENSION];
610 char mailbox[AST_MAX_EXTENSION];
611 char dialdest[256];
612 int onhooktime;
613 int msgstate;
614 int distinctivering; /*!< Which distinctivering to use */
615 int cidrings; /*!< Which ring to deliver CID on */
616 int dtmfrelax; /*!< whether to run in relaxed DTMF mode */
617 int fake_event;
618 int polarityonanswerdelay;
619 struct timeval polaritydelaytv;
620 int sendcalleridafter;
621 #ifdef HAVE_PRI
622 struct dahdi_pri *pri;
623 struct dahdi_pvt *bearer;
624 struct dahdi_pvt *realcall;
625 q931_call *call;
626 int tei; /* channel in use by this tei */
627 q931_call *holdedcall;
628 int prioffset;
629 int logicalspan;
630 #endif
631 #ifdef HAVE_GSMAT
632 struct dahdi_gsm gsm;
633 #endif
634 int polarity;
635 int dsp_features;
636 char begindigit;
637 } *iflist = NULL, *ifend = NULL;
639 /*! \brief Channel configuration from chan_dahdi.conf .
640 * This struct is used for parsing the [channels] section of chan_dahdi.conf.
641 * Generally there is a field here for every possible configuration item.
643 * The state of fields is saved along the parsing and whenever a 'channel'
644 * statement is reached, the current dahdi_chan_conf is used to configure the
645 * channel (struct dahdi_pvt)
647 * @seealso dahdi_chan_init for the default values.
649 struct dahdi_chan_conf {
650 struct dahdi_pvt chan;
651 #ifdef HAVE_PRI
652 struct dahdi_pri pri;
653 #endif
654 struct dahdi_params timing;
656 char smdi_port[SMDI_MAX_FILENAME_LEN];
659 /** returns a new dahdi_chan_conf with default values (by-value) */
660 static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
661 /* recall that if a field is not included here it is initialized
662 * to 0 or equivalent
664 struct dahdi_chan_conf conf = {
665 #ifdef HAVE_PRI
666 .pri = {
667 .nsf = PRI_NSF_NONE,
668 .switchtype = PRI_SWITCH_NI2,
669 .dialplan = PRI_NATIONAL_ISDN + 1,
670 .localdialplan = PRI_NATIONAL_ISDN + 1,
671 .nodetype = PRI_CPE,
673 .minunused = 2,
674 .idleext = "",
675 .idledial = "",
676 .nocid = "No CID available",
677 .withheldcid = "CID withheld",
678 .internationalprefix = "",
679 .nationalprefix = "",
680 .localprefix = "",
681 .privateprefix = "",
682 .unknownprefix = "",
684 .resetinterval = 3600
686 #endif
687 .chan = {
688 .context = "default",
689 .cid_num = "",
690 .cid_name = "",
691 .mohinterpret = "default",
692 .mohsuggest = "",
693 .transfertobusy = 1,
694 .priindication_oob = 0,
695 .pritransfer = 0,
697 .cid_signalling = CID_SIG_BELL,
698 .cid_start = CID_START_RING,
699 .dahditrcallerid = 0,
700 .use_callerid = 1,
701 .sig = -1,
702 .outsigmod = -1,
704 .tonezone = -1,
706 .echocancel = 1,
708 .busycount = 3,
710 .accountcode = "",
712 .mailbox = "",
715 .polarityonanswerdelay = 600,
717 .sendcalleridafter = DEFAULT_CIDRINGS,
719 .buf_policy = DAHDI_POLICY_IMMEDIATE,
720 .buf_no = numbufs
722 .timing = {
723 .prewinktime = -1,
724 .preflashtime = -1,
725 .winktime = -1,
726 .flashtime = -1,
727 .starttime = -1,
728 .rxwinktime = -1,
729 .rxflashtime = -1,
730 .debouncetime = -1
732 .smdi_port = "/dev/ttyS0",
735 return conf;
739 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause);
740 static int dahdi_digit_begin(struct ast_channel *ast, char digit);
741 static int dahdi_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
742 static int dahdi_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu);
743 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout);
744 static int dahdi_hangup(struct ast_channel *ast);
745 static int dahdi_answer(struct ast_channel *ast);
746 static struct ast_frame *dahdi_read(struct ast_channel *ast);
747 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame);
748 static struct ast_frame *dahdi_exception(struct ast_channel *ast);
749 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen);
750 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
751 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
752 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len);
753 static void enable_dtmf_detect(struct dahdi_pvt *p);
754 static void disable_dtmf_detect(struct dahdi_pvt *p);
755 static int dahdi_setlaw(int dfd, int law);
757 /* a workaround for unused bristuff interface changes */
758 #define pri_hangup(pri, call, cause) pri_hangup(pri, call, cause, -1)
760 static const struct ast_channel_tech dahdi_tech = {
761 .type = "DAHDI",
762 .description = tdesc,
763 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
764 .requester = dahdi_request,
765 .send_digit_begin = dahdi_digit_begin,
766 .send_digit_end = dahdi_digit_end,
767 .send_text = dahdi_sendtext,
768 .send_message = dahdi_sendmessage,
769 .call = dahdi_call,
770 .hangup = dahdi_hangup,
771 .answer = dahdi_answer,
772 .read = dahdi_read,
773 .write = dahdi_write,
774 .bridge = dahdi_bridge,
775 .exception = dahdi_exception,
776 .indicate = dahdi_indicate,
777 .fixup = dahdi_fixup,
778 .setoption = dahdi_setoption,
779 .func_channel_read = dahdi_func_read,
782 static const struct ast_channel_tech zap_tech = {
783 .type = "Zap",
784 .description = tdesc,
785 .capabilities = AST_FORMAT_SLINEAR | AST_FORMAT_ULAW | AST_FORMAT_ALAW,
786 .requester = dahdi_request,
787 .send_digit_begin = dahdi_digit_begin,
788 .send_digit_end = dahdi_digit_end,
789 .send_text = dahdi_sendtext,
790 .send_message = dahdi_sendmessage,
791 .call = dahdi_call,
792 .hangup = dahdi_hangup,
793 .answer = dahdi_answer,
794 .read = dahdi_read,
795 .write = dahdi_write,
796 .bridge = dahdi_bridge,
797 .exception = dahdi_exception,
798 .indicate = dahdi_indicate,
799 .fixup = dahdi_fixup,
800 .setoption = dahdi_setoption,
801 .func_channel_read = dahdi_func_read,
804 static const struct ast_channel_tech *chan_tech;
806 #ifdef HAVE_PRI
807 #define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
808 #else
809 #define GET_CHANNEL(p) ((p)->channel)
810 #endif
812 struct dahdi_pvt *round_robin[32];
814 #ifdef HAVE_PRI
815 struct app_tmp {
816 char app[256];
817 char data[256];
818 struct ast_channel *chan;
819 pthread_t t;
822 static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
824 int res;
825 /* Grab the lock first */
826 do {
827 res = ast_mutex_trylock(&pri->lock);
828 if (res) {
829 DEADLOCK_AVOIDANCE(&pvt->lock);
831 } while (res);
832 /* Then break the poll */
833 if (pri->master != AST_PTHREADT_NULL)
834 pthread_kill(pri->master, SIGURG);
835 return 0;
837 #endif
839 static void handle_aoc_e(struct dahdi_pri *pri, pri_event *e, int chanpos)
841 struct dahdi_pvt *chan;
842 if (e->hangup.aoc_units <= -1)
843 return;
845 chan = pri->pvts[chanpos];
846 if (chan->owner) {
847 char tmpstr[256];
848 snprintf(tmpstr, sizeof(tmpstr), "%d", (int)e->hangup.aoc_units);
849 pbx_builtin_setvar_helper(chan->owner, "AOCEUNITS", tmpstr);
851 if (option_verbose > 2)
852 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
853 chan->logicalspan, chan->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
855 #define NUM_CADENCE_MAX 25
856 static int num_cadence = 4;
857 static int user_has_defined_cadences = 0;
859 static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
860 { { 125, 125, 2000, 4000 } }, /*!< Quick chirp followed by normal ring */
861 { { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
862 { { 125, 125, 125, 125, 125, 4000 } }, /*!< Three short bursts */
863 { { 1000, 500, 2500, 5000 } }, /*!< Long ring */
866 /*! \brief cidrings says in which pause to transmit the cid information, where the first pause
867 * is 1, the second pause is 2 and so on.
870 static int cidrings[NUM_CADENCE_MAX] = {
871 2, /*!< Right after first long ring */
872 4, /*!< Right after long part */
873 3, /*!< After third chirp */
874 2, /*!< Second spell */
877 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
878 (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
880 #define CANBUSYDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
881 #define CANPROGRESSDETECT(p) (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
883 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
885 int res;
886 if (p->subs[SUB_REAL].owner == ast)
887 res = 0;
888 else if (p->subs[SUB_CALLWAIT].owner == ast)
889 res = 1;
890 else if (p->subs[SUB_THREEWAY].owner == ast)
891 res = 2;
892 else {
893 res = -1;
894 if (!nullok)
895 ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
897 return res;
900 #ifdef HAVE_PRI
901 static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
902 #else
903 static void wakeup_sub(struct dahdi_pvt *p, int a, void *pri)
904 #endif
906 #ifdef HAVE_PRI
907 if (pri)
908 ast_mutex_unlock(&pri->lock);
909 #endif
910 for (;;) {
911 if (p->subs[a].owner) {
912 if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
913 DEADLOCK_AVOIDANCE(&p->lock);
914 } else {
915 ast_queue_frame(p->subs[a].owner, &ast_null_frame);
916 ast_mutex_unlock(&p->subs[a].owner->lock);
917 break;
919 } else
920 break;
922 #ifdef HAVE_PRI
923 if (pri)
924 ast_mutex_lock(&pri->lock);
925 #endif
928 #ifdef HAVE_PRI
929 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
930 #else
931 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *pri)
932 #endif
934 /* We must unlock the PRI to avoid the possibility of a deadlock */
935 #ifdef HAVE_PRI
936 if (pri)
937 ast_mutex_unlock(&pri->lock);
938 #endif
939 for (;;) {
940 if (p->owner) {
941 if (ast_mutex_trylock(&p->owner->lock)) {
942 DEADLOCK_AVOIDANCE(&p->lock);
943 } else {
944 ast_queue_frame(p->owner, f);
945 ast_mutex_unlock(&p->owner->lock);
946 break;
948 } else
949 break;
951 #ifdef HAVE_PRI
952 if (pri)
953 ast_mutex_lock(&pri->lock);
954 #endif
957 static int restore_gains(struct dahdi_pvt *p);
959 static void swap_subs(struct dahdi_pvt *p, int a, int b)
961 int tchan;
962 int tinthreeway;
963 struct ast_channel *towner;
965 ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
967 tchan = p->subs[a].chan;
968 towner = p->subs[a].owner;
969 tinthreeway = p->subs[a].inthreeway;
971 p->subs[a].chan = p->subs[b].chan;
972 p->subs[a].owner = p->subs[b].owner;
973 p->subs[a].inthreeway = p->subs[b].inthreeway;
975 p->subs[b].chan = tchan;
976 p->subs[b].owner = towner;
977 p->subs[b].inthreeway = tinthreeway;
979 if (p->subs[a].owner)
980 p->subs[a].owner->fds[0] = p->subs[a].dfd;
981 if (p->subs[b].owner)
982 p->subs[b].owner->fds[0] = p->subs[b].dfd;
983 wakeup_sub(p, a, NULL);
984 wakeup_sub(p, b, NULL);
987 static int dahdi_open(char *fn)
989 int fd;
990 int isnum;
991 int chan = 0;
992 int bs;
993 int x;
994 isnum = 1;
995 for (x = 0; x < strlen(fn); x++) {
996 if (!isdigit(fn[x])) {
997 isnum = 0;
998 break;
1001 if (isnum) {
1002 chan = atoi(fn);
1003 if (chan < 1) {
1004 ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
1005 return -1;
1007 #ifdef HAVE_ZAPTEL
1008 fn = "/dev/zap/channel";
1009 #else
1010 fn = "/dev/dahdi/channel";
1011 #endif
1013 fd = open(fn, O_RDWR | O_NONBLOCK);
1014 if (fd < 0) {
1015 ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
1016 return -1;
1018 if (chan) {
1019 if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
1020 x = errno;
1021 close(fd);
1022 errno = x;
1023 ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
1024 return -1;
1027 bs = READ_SIZE;
1028 if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
1029 ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs, strerror(errno));
1030 x = errno;
1031 close(fd);
1032 errno = x;
1033 return -1;
1035 return fd;
1038 static void dahdi_close(int fd)
1040 if (fd > 0)
1041 close(fd);
1044 static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
1046 dahdi_close(chan_pvt->subs[sub_num].dfd);
1047 chan_pvt->subs[sub_num].dfd = -1;
1050 #ifdef HAVE_PRI
1051 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
1053 dahdi_close(pri->fds[fd_num]);
1054 pri->fds[fd_num] = -1;
1056 #endif
1058 static int dahdi_setlinear(int dfd, int linear)
1060 int res;
1061 res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
1062 if (res)
1063 return res;
1064 return 0;
1068 static int alloc_sub(struct dahdi_pvt *p, int x)
1070 struct dahdi_bufferinfo bi;
1071 int res;
1072 if (p->subs[x].dfd < 0) {
1073 #ifdef HAVE_ZAPTEL
1074 p->subs[x].dfd = dahdi_open("/dev/zap/pseudo");
1075 #else
1076 p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
1077 #endif
1078 if (p->subs[x].dfd > -1) {
1079 res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
1080 if (!res) {
1081 bi.txbufpolicy = p->buf_policy;
1082 bi.rxbufpolicy = p->buf_policy;
1083 bi.numbufs = p->buf_no;
1084 res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
1085 if (res < 0) {
1086 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
1088 } else
1089 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
1090 if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
1091 ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
1092 dahdi_close_sub(p, x);
1093 return -1;
1095 if (option_debug)
1096 ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
1097 return 0;
1098 } else
1099 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
1100 return -1;
1102 ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
1103 return -1;
1106 static int unalloc_sub(struct dahdi_pvt *p, int x)
1108 if (!x) {
1109 ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
1110 return -1;
1112 ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
1113 dahdi_close_sub(p, x);
1114 p->subs[x].linear = 0;
1115 p->subs[x].chan = 0;
1116 p->subs[x].owner = NULL;
1117 p->subs[x].inthreeway = 0;
1118 p->polarity = POLARITY_IDLE;
1119 memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
1120 return 0;
1123 static int digit_to_dtmfindex(char digit)
1125 if (isdigit(digit))
1126 return DAHDI_TONE_DTMF_BASE + (digit - '0');
1127 else if (digit >= 'A' && digit <= 'D')
1128 return DAHDI_TONE_DTMF_A + (digit - 'A');
1129 else if (digit >= 'a' && digit <= 'd')
1130 return DAHDI_TONE_DTMF_A + (digit - 'a');
1131 else if (digit == '*')
1132 return DAHDI_TONE_DTMF_s;
1133 else if (digit == '#')
1134 return DAHDI_TONE_DTMF_p;
1135 else
1136 return -1;
1139 static int dahdi_digit_begin(struct ast_channel *chan, char digit)
1141 struct dahdi_pvt *pvt;
1142 int index;
1143 int dtmf = -1;
1145 pvt = chan->tech_pvt;
1147 ast_mutex_lock(&pvt->lock);
1149 index = dahdi_get_index(chan, pvt, 0);
1151 if ((index != SUB_REAL) || !pvt->owner)
1152 goto out;
1154 #ifdef HAVE_PRI
1155 if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
1156 if (pvt->setup_ack) {
1157 if (!pri_grab(pvt, pvt->pri)) {
1158 pri_information(pvt->pri->pri, pvt->call, digit);
1159 pri_rel(pvt->pri);
1160 } else
1161 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
1162 } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
1163 int res;
1164 ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
1165 res = strlen(pvt->dialdest);
1166 pvt->dialdest[res++] = digit;
1167 pvt->dialdest[res] = '\0';
1169 goto out;
1171 #endif
1172 if ((dtmf = digit_to_dtmfindex(digit)) == -1)
1173 goto out;
1175 if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
1176 int res;
1177 struct dahdi_dialoperation zo = {
1178 .op = DAHDI_DIAL_OP_APPEND,
1179 .dialstr[0] = 'T',
1180 .dialstr[1] = digit,
1181 .dialstr[2] = 0,
1183 if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
1184 ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
1185 else
1186 pvt->dialing = 1;
1187 } else {
1188 ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
1189 pvt->dialing = 1;
1190 pvt->begindigit = digit;
1193 out:
1194 ast_mutex_unlock(&pvt->lock);
1196 return 0;
1199 static int dahdi_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
1201 struct dahdi_pvt *pvt;
1202 int res = 0;
1203 int index;
1204 int x;
1206 pvt = chan->tech_pvt;
1208 ast_mutex_lock(&pvt->lock);
1210 index = dahdi_get_index(chan, pvt, 0);
1212 if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
1213 goto out;
1215 #ifdef HAVE_PRI
1216 /* This means that the digit was already sent via PRI signalling */
1217 if (pvt->sig == SIG_PRI && !pvt->begindigit)
1218 goto out;
1219 #endif
1221 if (pvt->begindigit) {
1222 x = -1;
1223 ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
1224 res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
1225 pvt->dialing = 0;
1226 pvt->begindigit = 0;
1229 out:
1230 ast_mutex_unlock(&pvt->lock);
1232 return res;
1235 static char *events[] = {
1236 "No event",
1237 "On hook",
1238 "Ring/Answered",
1239 "Wink/Flash",
1240 "Alarm",
1241 "No more alarm",
1242 "HDLC Abort",
1243 "HDLC Overrun",
1244 "HDLC Bad FCS",
1245 "Dial Complete",
1246 "Ringer On",
1247 "Ringer Off",
1248 "Hook Transition Complete",
1249 "Bits Changed",
1250 "Pulse Start",
1251 "Timer Expired",
1252 "Timer Ping",
1253 "Polarity Reversal",
1254 "Ring Begin",
1257 static struct {
1258 int alarm;
1259 char *name;
1260 } alarms[] = {
1261 { DAHDI_ALARM_RED, "Red Alarm" },
1262 { DAHDI_ALARM_YELLOW, "Yellow Alarm" },
1263 { DAHDI_ALARM_BLUE, "Blue Alarm" },
1264 { DAHDI_ALARM_RECOVER, "Recovering" },
1265 { DAHDI_ALARM_LOOPBACK, "Loopback" },
1266 { DAHDI_ALARM_NOTOPEN, "Not Open" },
1267 { DAHDI_ALARM_NONE, "None" },
1270 static char *alarm2str(int alarm)
1272 int x;
1273 for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
1274 if (alarms[x].alarm & alarm)
1275 return alarms[x].name;
1277 return alarm ? "Unknown Alarm" : "No Alarm";
1280 static char *event2str(int event)
1282 static char buf[256];
1283 if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
1284 return events[event];
1285 sprintf(buf, "Event %d", event); /* safe */
1286 return buf;
1289 #ifdef HAVE_PRI
1290 static char *dialplan2str(int dialplan)
1292 if (dialplan == -1) {
1293 return("Dynamically set dialplan in ISDN");
1295 return (pri_plan2str(dialplan));
1297 #endif
1299 static char *dahdi_sig2str(int sig)
1301 static char buf[256];
1302 switch (sig) {
1303 case SIG_EM:
1304 return "E & M Immediate";
1305 case SIG_EMWINK:
1306 return "E & M Wink";
1307 case SIG_EM_E1:
1308 return "E & M E1";
1309 case SIG_FEATD:
1310 return "Feature Group D (DTMF)";
1311 case SIG_FEATDMF:
1312 return "Feature Group D (MF)";
1313 case SIG_FEATDMF_TA:
1314 return "Feature Groud D (MF) Tandem Access";
1315 case SIG_FEATB:
1316 return "Feature Group B (MF)";
1317 case SIG_E911:
1318 return "E911 (MF)";
1319 case SIG_FGC_CAMA:
1320 return "FGC/CAMA (Dialpulse)";
1321 case SIG_FGC_CAMAMF:
1322 return "FGC/CAMA (MF)";
1323 case SIG_FXSLS:
1324 return "FXS Loopstart";
1325 case SIG_FXSGS:
1326 return "FXS Groundstart";
1327 case SIG_FXSKS:
1328 return "FXS Kewlstart";
1329 case SIG_FXOLS:
1330 return "FXO Loopstart";
1331 case SIG_FXOGS:
1332 return "FXO Groundstart";
1333 case SIG_FXOKS:
1334 return "FXO Kewlstart";
1335 case SIG_PRI:
1336 return "ISDN PRI";
1337 case SIG_SF:
1338 return "SF (Tone) Immediate";
1339 case SIG_SFWINK:
1340 return "SF (Tone) Wink";
1341 case SIG_SF_FEATD:
1342 return "SF (Tone) with Feature Group D (DTMF)";
1343 case SIG_SF_FEATDMF:
1344 return "SF (Tone) with Feature Group D (MF)";
1345 case SIG_SF_FEATB:
1346 return "SF (Tone) with Feature Group B (MF)";
1347 case SIG_GR303FXOKS:
1348 return "GR-303 with FXOKS";
1349 case SIG_GR303FXSKS:
1350 return "GR-303 with FXSKS";
1351 case SIG_GSM:
1352 return "GSM";
1353 case 0:
1354 return "Pseudo";
1355 default:
1356 snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
1357 return buf;
1361 #define sig2str dahdi_sig2str
1363 static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
1365 /* If the conference already exists, and we're already in it
1366 don't bother doing anything */
1367 struct dahdi_confinfo zi;
1369 memset(&zi, 0, sizeof(zi));
1370 zi.chan = 0;
1372 if (slavechannel > 0) {
1373 /* If we have only one slave, do a digital mon */
1374 zi.confmode = DAHDI_CONF_DIGITALMON;
1375 zi.confno = slavechannel;
1376 } else {
1377 if (!index) {
1378 /* Real-side and pseudo-side both participate in conference */
1379 zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
1380 DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
1381 } else
1382 zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
1383 zi.confno = p->confno;
1385 if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
1386 return 0;
1387 if (c->dfd < 0)
1388 return 0;
1389 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1390 ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
1391 return -1;
1393 if (slavechannel < 1) {
1394 p->confno = zi.confno;
1396 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1397 ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1398 return 0;
1401 static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
1403 /* If they're listening to our channel, they're ours */
1404 if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
1405 return 1;
1406 /* If they're a talker on our (allocated) conference, they're ours */
1407 if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
1408 return 1;
1409 return 0;
1412 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
1414 struct dahdi_confinfo zi;
1415 if (/* Can't delete if there's no dfd */
1416 (c->dfd < 0) ||
1417 /* Don't delete from the conference if it's not our conference */
1418 !isourconf(p, c)
1419 /* Don't delete if we don't think it's conferenced at all (implied) */
1420 ) return 0;
1421 memset(&zi, 0, sizeof(zi));
1422 zi.chan = 0;
1423 zi.confno = 0;
1424 zi.confmode = 0;
1425 if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
1426 ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
1427 return -1;
1429 ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
1430 memcpy(&c->curconf, &zi, sizeof(c->curconf));
1431 return 0;
1434 static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
1436 int x;
1437 int useslavenative;
1438 struct dahdi_pvt *slave = NULL;
1439 /* Start out optimistic */
1440 useslavenative = 1;
1441 /* Update conference state in a stateless fashion */
1442 for (x = 0; x < 3; x++) {
1443 /* Any three-way calling makes slave native mode *definitely* out
1444 of the question */
1445 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
1446 useslavenative = 0;
1448 /* If we don't have any 3-way calls, check to see if we have
1449 precisely one slave */
1450 if (useslavenative) {
1451 for (x = 0; x < MAX_SLAVES; x++) {
1452 if (p->slaves[x]) {
1453 if (slave) {
1454 /* Whoops already have a slave! No
1455 slave native and stop right away */
1456 slave = NULL;
1457 useslavenative = 0;
1458 break;
1459 } else {
1460 /* We have one slave so far */
1461 slave = p->slaves[x];
1466 /* If no slave, slave native definitely out */
1467 if (!slave)
1468 useslavenative = 0;
1469 else if (slave->law != p->law) {
1470 useslavenative = 0;
1471 slave = NULL;
1473 if (out)
1474 *out = slave;
1475 return useslavenative;
1478 static int reset_conf(struct dahdi_pvt *p)
1480 struct dahdi_confinfo zi;
1481 memset(&zi, 0, sizeof(zi));
1482 p->confno = -1;
1483 memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
1484 if (p->subs[SUB_REAL].dfd > -1) {
1485 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
1486 ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
1488 return 0;
1491 static int update_conf(struct dahdi_pvt *p)
1493 int needconf = 0;
1494 int x;
1495 int useslavenative;
1496 struct dahdi_pvt *slave = NULL;
1498 useslavenative = isslavenative(p, &slave);
1499 /* Start with the obvious, general stuff */
1500 for (x = 0; x < 3; x++) {
1501 /* Look for three way calls */
1502 if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
1503 conf_add(p, &p->subs[x], x, 0);
1504 needconf++;
1505 } else {
1506 conf_del(p, &p->subs[x], x);
1509 /* If we have a slave, add him to our conference now. or DAX
1510 if this is slave native */
1511 for (x = 0; x < MAX_SLAVES; x++) {
1512 if (p->slaves[x]) {
1513 if (useslavenative)
1514 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
1515 else {
1516 conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
1517 needconf++;
1521 /* If we're supposed to be in there, do so now */
1522 if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
1523 if (useslavenative)
1524 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
1525 else {
1526 conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
1527 needconf++;
1530 /* If we have a master, add ourselves to his conference */
1531 if (p->master) {
1532 if (isslavenative(p->master, NULL)) {
1533 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
1534 } else {
1535 conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
1538 if (!needconf) {
1539 /* Nobody is left (or should be left) in our conference.
1540 Kill it. */
1541 p->confno = -1;
1543 if (option_debug)
1544 ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
1545 return 0;
1548 static void dahdi_enable_ec(struct dahdi_pvt *p)
1550 int x;
1551 int res;
1552 if (!p)
1553 return;
1554 if (p->faxhandled) {
1555 ast_log(LOG_DEBUG, "Not enabling echo cancellation on a fax/modem call\n");
1556 return;
1558 if (p->echocanon) {
1559 ast_log(LOG_DEBUG, "Echo cancellation already on\n");
1560 return;
1562 if (p->digital) {
1563 ast_log(LOG_DEBUG, "Echo cancellation does not make any sense on digital connections!\n");
1564 return;
1566 if (p->echocancel) {
1567 if (p->sig == SIG_PRI) {
1568 x = 1;
1569 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
1570 if (res)
1571 ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
1573 x = p->echocancel;
1574 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1575 if (res)
1576 ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
1577 else {
1578 p->echocanon = 1;
1579 if (option_debug)
1580 ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
1582 } else if (option_debug)
1583 ast_log(LOG_DEBUG, "No echo cancellation requested\n");
1586 static void dahdi_train_ec(struct dahdi_pvt *p)
1588 int x;
1589 int res;
1590 if (p && p->echocancel && p->echotraining && (!p->digital) && (!p->faxhandled)) {
1591 x = p->echotraining;
1592 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
1593 if (res)
1594 ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
1595 else {
1596 ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
1598 } else
1599 ast_log(LOG_DEBUG, "No echo training requested\n");
1602 static void dahdi_disable_ec(struct dahdi_pvt *p)
1604 int x;
1605 int res;
1606 if (p->echocancel) {
1607 x = 0;
1608 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
1609 if (res)
1610 ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
1611 else if (option_debug)
1612 ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
1614 p->echocanon = 0;
1617 static void fill_txgain(struct dahdi_gains *g, float gain, int law)
1619 int j;
1620 int k;
1621 float linear_gain = pow(10.0, gain / 20.0);
1623 switch (law) {
1624 case DAHDI_LAW_ALAW:
1625 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1626 if (gain) {
1627 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1628 if (k > 32767) k = 32767;
1629 if (k < -32767) k = -32767;
1630 g->txgain[j] = AST_LIN2A(k);
1631 } else {
1632 g->txgain[j] = j;
1635 break;
1636 case DAHDI_LAW_MULAW:
1637 for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
1638 if (gain) {
1639 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1640 if (k > 32767) k = 32767;
1641 if (k < -32767) k = -32767;
1642 g->txgain[j] = AST_LIN2MU(k);
1643 } else {
1644 g->txgain[j] = j;
1647 break;
1651 static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
1653 int j;
1654 int k;
1655 float linear_gain = pow(10.0, gain / 20.0);
1657 switch (law) {
1658 case DAHDI_LAW_ALAW:
1659 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1660 if (gain) {
1661 k = (int) (((float) AST_ALAW(j)) * linear_gain);
1662 if (k > 32767) k = 32767;
1663 if (k < -32767) k = -32767;
1664 g->rxgain[j] = AST_LIN2A(k);
1665 } else {
1666 g->rxgain[j] = j;
1669 break;
1670 case DAHDI_LAW_MULAW:
1671 for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
1672 if (gain) {
1673 k = (int) (((float) AST_MULAW(j)) * linear_gain);
1674 if (k > 32767) k = 32767;
1675 if (k < -32767) k = -32767;
1676 g->rxgain[j] = AST_LIN2MU(k);
1677 } else {
1678 g->rxgain[j] = j;
1681 break;
1685 static int set_actual_txgain(int fd, int chan, float gain, int law)
1687 struct dahdi_gains g;
1688 int res;
1690 memset(&g, 0, sizeof(g));
1691 g.chan = chan;
1692 res = ioctl(fd, DAHDI_GETGAINS, &g);
1693 if (res) {
1694 if (option_debug)
1695 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1696 return res;
1699 fill_txgain(&g, gain, law);
1701 return ioctl(fd, DAHDI_SETGAINS, &g);
1704 static int set_actual_rxgain(int fd, int chan, float gain, int law)
1706 struct dahdi_gains g;
1707 int res;
1709 memset(&g, 0, sizeof(g));
1710 g.chan = chan;
1711 res = ioctl(fd, DAHDI_GETGAINS, &g);
1712 if (res) {
1713 ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
1714 return res;
1717 fill_rxgain(&g, gain, law);
1719 return ioctl(fd, DAHDI_SETGAINS, &g);
1722 static int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
1724 return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
1727 static int bump_gains(struct dahdi_pvt *p)
1729 int res;
1731 /* Bump receive gain by 5.0db */
1732 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
1733 if (res) {
1734 ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
1735 return -1;
1738 return 0;
1741 static int restore_gains(struct dahdi_pvt *p)
1743 int res;
1745 res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1746 if (res) {
1747 ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
1748 return -1;
1751 return 0;
1754 static inline int dahdi_set_hook(int fd, int hs)
1756 int x, res;
1758 x = hs;
1759 res = ioctl(fd, DAHDI_HOOK, &x);
1761 if (res < 0) {
1762 if (errno == EINPROGRESS)
1763 return 0;
1764 ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
1765 /* will expectedly fail if phone is off hook during operation, such as during a restart */
1768 return res;
1771 static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
1773 int x, y, res;
1774 x = muted;
1775 if ((p->sig == SIG_PRI) || (p->sig == SIG_GSM)) {
1776 y = 1;
1777 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
1778 if (res)
1779 ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
1781 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
1782 if (res < 0)
1783 ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
1784 return res;
1787 static int save_conference(struct dahdi_pvt *p)
1789 struct dahdi_confinfo c;
1790 int res;
1791 if (p->saveconf.confmode) {
1792 ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
1793 return -1;
1795 p->saveconf.chan = 0;
1796 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
1797 if (res) {
1798 ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
1799 p->saveconf.confmode = 0;
1800 return -1;
1802 c.chan = 0;
1803 c.confno = 0;
1804 c.confmode = DAHDI_CONF_NORMAL;
1805 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
1806 if (res) {
1807 ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
1808 return -1;
1810 if (option_debug)
1811 ast_log(LOG_DEBUG, "Disabled conferencing\n");
1812 return 0;
1815 static int restore_conference(struct dahdi_pvt *p)
1817 int res;
1818 if (p->saveconf.confmode) {
1819 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
1820 p->saveconf.confmode = 0;
1821 if (res) {
1822 ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
1823 return -1;
1826 if (option_debug)
1827 ast_log(LOG_DEBUG, "Restored conferencing\n");
1828 return 0;
1831 static int send_callerid(struct dahdi_pvt *p);
1833 static int send_cwcidspill(struct dahdi_pvt *p)
1835 p->callwaitcas = 0;
1836 p->cidcwexpire = 0;
1837 if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
1838 return -1;
1839 p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
1840 /* Make sure we account for the end */
1841 p->cidlen += READ_SIZE * 4;
1842 p->cidpos = 0;
1843 send_callerid(p);
1844 if (option_verbose > 2)
1845 ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
1846 return 0;
1849 static int has_voicemail(struct dahdi_pvt *p)
1852 return ast_app_has_voicemail(p->mailbox, NULL);
1855 static int send_callerid(struct dahdi_pvt *p)
1857 /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
1858 int res;
1859 /* Take out of linear mode if necessary */
1860 if (p->subs[SUB_REAL].linear) {
1861 p->subs[SUB_REAL].linear = 0;
1862 dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
1864 while (p->cidpos < p->cidlen) {
1865 res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
1866 if (res < 0) {
1867 if (errno == EAGAIN)
1868 return 0;
1869 else {
1870 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
1871 return -1;
1874 if (!res)
1875 return 0;
1876 p->cidpos += res;
1878 free(p->cidspill);
1879 p->cidspill = NULL;
1880 if (p->callwaitcas) {
1881 /* Wait for CID/CW to expire */
1882 p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
1883 } else
1884 restore_conference(p);
1885 return 0;
1888 static int dahdi_callwait(struct ast_channel *ast)
1890 struct dahdi_pvt *p = ast->tech_pvt;
1891 p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
1892 if (p->cidspill) {
1893 ast_log(LOG_WARNING, "Spill already exists?!?\n");
1894 free(p->cidspill);
1896 if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
1897 return -1;
1898 save_conference(p);
1899 /* Silence */
1900 memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
1901 if (!p->callwaitrings && p->callwaitingcallerid) {
1902 ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
1903 p->callwaitcas = 1;
1904 p->cidlen = 2400 + 680 + READ_SIZE * 4;
1905 } else {
1906 ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
1907 p->callwaitcas = 0;
1908 p->cidlen = 2400 + READ_SIZE * 4;
1910 p->cidpos = 0;
1911 send_callerid(p);
1913 return 0;
1916 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
1918 struct dahdi_pvt *p = ast->tech_pvt;
1919 int x, res, index,mysig;
1920 char *c, *n, *l;
1921 #ifdef HAVE_PRI
1922 char *s = NULL;
1923 #endif
1924 char dest[256]; /* must be same length as p->dialdest */
1925 ast_mutex_lock(&p->lock);
1926 ast_copy_string(dest, rdest, sizeof(dest));
1927 ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
1928 if ((ast->_state == AST_STATE_BUSY)) {
1929 p->subs[SUB_REAL].needbusy = 1;
1930 ast_mutex_unlock(&p->lock);
1931 return 0;
1933 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
1934 ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
1935 ast_mutex_unlock(&p->lock);
1936 return -1;
1938 p->dialednone = 0;
1939 if ((p->radio || (p->oprmode < 0))) /* if a radio channel, up immediately */
1941 /* Special pseudo -- automatically up */
1942 ast_setstate(ast, AST_STATE_UP);
1943 ast_mutex_unlock(&p->lock);
1944 return 0;
1946 x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
1947 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
1948 if (res)
1949 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
1950 p->outgoing = 1;
1952 set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
1954 mysig = p->sig;
1955 if (p->outsigmod > -1)
1956 mysig = p->outsigmod;
1958 switch (mysig) {
1959 case SIG_FXOLS:
1960 case SIG_FXOGS:
1961 case SIG_FXOKS:
1962 if (p->owner == ast) {
1963 /* Normal ring, on hook */
1965 /* Don't send audio while on hook, until the call is answered */
1966 p->dialing = 1;
1967 if (p->use_callerid) {
1968 /* Generate the Caller-ID spill if desired */
1969 if (p->cidspill) {
1970 ast_log(LOG_WARNING, "cidspill already exists??\n");
1971 free(p->cidspill);
1973 p->callwaitcas = 0;
1974 if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
1975 p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
1976 p->cidpos = 0;
1977 send_callerid(p);
1980 /* Choose proper cadence */
1981 if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
1982 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
1983 ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
1984 p->cidrings = cidrings[p->distinctivering - 1];
1985 } else {
1986 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
1987 ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
1988 p->cidrings = p->sendcalleridafter;
1991 /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
1992 c = strchr(dest, '/');
1993 if (c)
1994 c++;
1995 if (c && (strlen(c) < p->stripmsd)) {
1996 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1997 c = NULL;
1999 if (c) {
2000 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2001 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
2002 ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
2003 } else {
2004 p->dop.dialstr[0] = '\0';
2006 x = DAHDI_RING;
2007 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
2008 ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
2009 ast_mutex_unlock(&p->lock);
2010 return -1;
2012 p->dialing = 1;
2013 } else {
2014 /* Call waiting call */
2015 p->callwaitrings = 0;
2016 if (ast->cid.cid_num)
2017 ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
2018 else
2019 p->callwait_num[0] = '\0';
2020 if (ast->cid.cid_name)
2021 ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
2022 else
2023 p->callwait_name[0] = '\0';
2024 /* Call waiting tone instead */
2025 if (dahdi_callwait(ast)) {
2026 ast_mutex_unlock(&p->lock);
2027 return -1;
2029 /* Make ring-back */
2030 if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
2031 ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
2034 n = ast->cid.cid_name;
2035 l = ast->cid.cid_num;
2036 if (l)
2037 ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
2038 else
2039 p->lastcid_num[0] = '\0';
2040 if (n)
2041 ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
2042 else
2043 p->lastcid_name[0] = '\0';
2044 ast_setstate(ast, AST_STATE_RINGING);
2045 index = dahdi_get_index(ast, p, 0);
2046 if (index > -1) {
2047 p->subs[index].needringing = 1;
2049 break;
2050 case SIG_FXSLS:
2051 case SIG_FXSGS:
2052 case SIG_FXSKS:
2053 case SIG_EMWINK:
2054 case SIG_EM:
2055 case SIG_EM_E1:
2056 case SIG_FEATD:
2057 case SIG_FEATDMF:
2058 case SIG_E911:
2059 case SIG_FGC_CAMA:
2060 case SIG_FGC_CAMAMF:
2061 case SIG_FEATB:
2062 case SIG_SFWINK:
2063 case SIG_SF:
2064 case SIG_SF_FEATD:
2065 case SIG_SF_FEATDMF:
2066 case SIG_FEATDMF_TA:
2067 case SIG_SF_FEATB:
2068 c = strchr(dest, '/');
2069 if (c)
2070 c++;
2071 else
2072 c = "";
2073 if (strlen(c) < p->stripmsd) {
2074 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2075 ast_mutex_unlock(&p->lock);
2076 return -1;
2078 #ifdef HAVE_PRI
2079 /* Start the trunk, if not GR-303 */
2080 if (!p->pri) {
2081 #endif
2082 x = DAHDI_START;
2083 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2084 if (res < 0) {
2085 if (errno != EINPROGRESS) {
2086 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
2087 ast_mutex_unlock(&p->lock);
2088 return -1;
2091 #ifdef HAVE_PRI
2093 #endif
2094 ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
2095 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2097 c += p->stripmsd;
2099 switch (mysig) {
2100 case SIG_FEATD:
2101 l = ast->cid.cid_num;
2102 if (l)
2103 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
2104 else
2105 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
2106 break;
2107 case SIG_FEATDMF:
2108 l = ast->cid.cid_num;
2109 if (l)
2110 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
2111 else
2112 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
2113 break;
2114 case SIG_FEATDMF_TA:
2116 const char *cic, *ozz;
2118 /* If you have to go through a Tandem Access point you need to use this */
2119 ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
2120 if (!ozz)
2121 ozz = defaultozz;
2122 cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
2123 if (!cic)
2124 cic = defaultcic;
2125 if (!ozz || !cic) {
2126 ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
2127 ast_mutex_unlock(&p->lock);
2128 return -1;
2130 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
2131 snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
2132 p->whichwink = 0;
2134 break;
2135 case SIG_E911:
2136 ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
2137 break;
2138 case SIG_FGC_CAMA:
2139 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
2140 break;
2141 case SIG_FGC_CAMAMF:
2142 case SIG_FEATB:
2143 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
2144 break;
2145 default:
2146 if (p->pulse)
2147 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
2148 else
2149 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
2150 break;
2153 if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
2154 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
2155 strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
2156 p->echorest[sizeof(p->echorest) - 1] = '\0';
2157 p->echobreak = 1;
2158 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
2159 } else
2160 p->echobreak = 0;
2161 if (!res) {
2162 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
2163 int saveerr = errno;
2165 x = DAHDI_ONHOOK;
2166 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
2167 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
2168 ast_mutex_unlock(&p->lock);
2169 return -1;
2171 } else
2172 ast_log(LOG_DEBUG, "Deferring dialing...\n");
2173 p->dialing = 1;
2174 if (ast_strlen_zero(c))
2175 p->dialednone = 1;
2176 ast_setstate(ast, AST_STATE_DIALING);
2177 break;
2178 case 0:
2179 /* Special pseudo -- automatically up*/
2180 ast_setstate(ast, AST_STATE_UP);
2181 break;
2182 case SIG_PRI:
2183 /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
2184 p->dialdest[0] = '\0';
2185 disable_dtmf_detect(p);
2186 break;
2187 case SIG_GSM:
2188 #ifdef HAVE_GSMAT
2189 if (p->gsm.modul) {
2190 c = strchr(dest, '/');
2191 if (c)
2192 c++;
2193 else
2194 c = dest;
2195 ast_mutex_lock(&p->gsm.lock);
2196 if (gsm_dial(p->gsm.modul, p->use_callingpres ? ast->cid.cid_pres : 0, c)) {
2197 ast_log(LOG_WARNING, "dialing failed on channel %d\n", p->channel);
2198 ast_mutex_unlock(&p->gsm.lock);
2199 ast_mutex_unlock(&p->lock);
2200 return -1;
2202 ast_mutex_unlock(&p->gsm.lock);
2204 #endif
2205 break;
2206 default:
2207 ast_log(LOG_DEBUG, "not yet implemented\n");
2208 ast_mutex_unlock(&p->lock);
2209 return -1;
2211 #ifdef HAVE_PRI
2212 if (p->pri) {
2213 struct pri_sr *sr;
2214 #ifdef SUPPORT_USERUSER
2215 const char *useruser;
2216 #endif
2217 int pridialplan;
2218 int dp_strip;
2219 int prilocaldialplan;
2220 int ldp_strip;
2221 int exclusive;
2222 const char *rr_str;
2223 int redirect_reason;
2225 if ((p->pri->nodetype == BRI_NETWORK_PTMP) || (p->pri->nodetype == BRI_NETWORK)) {
2226 // pass NO audio when ringing an isdn phone
2227 p->dialing = 1;
2228 // maybe we could allow passing audio when calling a p2p PBX, but well... ;-)
2231 c = strchr(dest, '/');
2232 if (c)
2233 c++;
2234 else
2235 c = dest;
2237 l = NULL;
2238 n = NULL;
2240 if (!p->hidecallerid) {
2241 l = ast->cid.cid_num;
2242 if (!p->hidecalleridname) {
2243 n = ast->cid.cid_name;
2248 if (strlen(c) < p->stripmsd) {
2249 ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2250 ast_mutex_unlock(&p->lock);
2251 return -1;
2253 ast_copy_string(p->dnid, (c + p->stripmsd), sizeof(p->dnid));
2254 if (mysig != SIG_FXSKS) {
2255 p->dop.op = DAHDI_DIAL_OP_REPLACE;
2256 s = strchr(c + p->stripmsd, 'w');
2257 if (s) {
2258 if (strlen(s) > 1)
2259 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
2260 else
2261 p->dop.dialstr[0] = '\0';
2262 *s = '\0';
2263 } else {
2264 p->dop.dialstr[0] = '\0';
2267 if (pri_grab(p, p->pri)) {
2268 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
2269 ast_mutex_unlock(&p->lock);
2270 return -1;
2272 if (!(p->call = pri_new_call(p->pri->pri))) {
2273 ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
2274 pri_rel(p->pri);
2275 ast_mutex_unlock(&p->lock);
2276 return -1;
2277 } else {
2278 // ast_log(LOG_NOTICE, "call %d\n", p->call);
2280 if (!(sr = pri_sr_new())) {
2281 ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
2282 pri_destroycall(p->pri->pri, p->call);
2283 p->call = NULL;
2284 pri_rel(p->pri);
2285 ast_mutex_unlock(&p->lock);
2286 return -1;
2288 if (p->bearer || (mysig == SIG_FXSKS)) {
2289 if (p->bearer) {
2290 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);
2291 p->bearer->call = p->call;
2292 } else
2293 ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
2294 pri_set_crv(p->pri->pri, p->call, p->channel, 0);
2296 p->digital = IS_DIGITAL(ast->transfercapability);
2297 /* Add support for exclusive override */
2298 if (p->priexclusive)
2299 exclusive = 1;
2300 else {
2301 /* otherwise, traditional behavior */
2302 if (p->pri->nodetype == PRI_NETWORK)
2303 exclusive = 0;
2304 else
2305 exclusive = 1;
2308 pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
2309 pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
2310 (p->digital ? -1 :
2311 ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)), ast->lowlayercompat);
2312 if (p->pri->facilityenable)
2313 pri_facility_enable(p->pri->pri);
2315 if (option_verbose > 2)
2316 ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
2317 dp_strip = 0;
2318 pridialplan = p->pri->dialplan - 1;
2319 if (pridialplan == -2) { /* compute dynamically */
2320 if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2321 dp_strip = strlen(p->pri->internationalprefix);
2322 pridialplan = PRI_INTERNATIONAL_ISDN;
2323 } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2324 dp_strip = strlen(p->pri->nationalprefix);
2325 pridialplan = PRI_NATIONAL_ISDN;
2326 } else {
2327 pridialplan = PRI_LOCAL_ISDN;
2330 pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
2332 ldp_strip = 0;
2333 prilocaldialplan = p->pri->localdialplan - 1;
2334 if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
2335 if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
2336 ldp_strip = strlen(p->pri->internationalprefix);
2337 prilocaldialplan = PRI_INTERNATIONAL_ISDN;
2338 } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
2339 ldp_strip = strlen(p->pri->nationalprefix);
2340 prilocaldialplan = PRI_NATIONAL_ISDN;
2341 } else {
2342 prilocaldialplan = PRI_LOCAL_ISDN;
2345 pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
2346 p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
2347 if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
2348 if (!strcasecmp(rr_str, "UNKNOWN"))
2349 redirect_reason = 0;
2350 else if (!strcasecmp(rr_str, "BUSY"))
2351 redirect_reason = 1;
2352 else if (!strcasecmp(rr_str, "NO_REPLY"))
2353 redirect_reason = 2;
2354 else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
2355 redirect_reason = 15;
2356 else
2357 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2358 } else
2359 redirect_reason = PRI_REDIR_UNCONDITIONAL;
2360 pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
2362 #ifdef SUPPORT_USERUSER
2363 /* User-user info */
2364 useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
2366 if (useruser)
2367 pri_sr_set_useruser(sr, useruser);
2368 #endif
2370 if (pri_setup(p->pri->pri, p->call, sr)) {
2371 ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
2372 c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
2373 pri_rel(p->pri);
2374 ast_mutex_unlock(&p->lock);
2375 pri_sr_free(sr);
2376 return -1;
2378 pri_sr_free(sr);
2379 ast_setstate(ast, AST_STATE_DIALING);
2380 pri_rel(p->pri);
2382 #endif
2383 ast_mutex_unlock(&p->lock);
2384 return 0;
2387 static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
2389 struct dahdi_pvt *p = *pvt;
2390 /* Remove channel from the list */
2391 if (p->prev)
2392 p->prev->next = p->next;
2393 if (p->next)
2394 p->next->prev = p->prev;
2395 if (p->use_smdi)
2396 ast_smdi_interface_unref(p->smdi_iface);
2397 ast_mutex_destroy(&p->lock);
2398 dahdi_close_sub(p, SUB_REAL);
2399 if (p->owner)
2400 p->owner->tech_pvt = NULL;
2401 free(p);
2402 *pvt = NULL;
2405 static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
2407 int owned = 0;
2408 int i = 0;
2410 if (!now) {
2411 if (cur->owner) {
2412 owned = 1;
2415 for (i = 0; i < 3; i++) {
2416 if (cur->subs[i].owner) {
2417 owned = 1;
2420 if (!owned) {
2421 if (prev) {
2422 prev->next = cur->next;
2423 if (prev->next)
2424 prev->next->prev = prev;
2425 else
2426 ifend = prev;
2427 } else {
2428 iflist = cur->next;
2429 if (iflist)
2430 iflist->prev = NULL;
2431 else
2432 ifend = NULL;
2434 destroy_dahdi_pvt(&cur);
2436 } else {
2437 if (prev) {
2438 prev->next = cur->next;
2439 if (prev->next)
2440 prev->next->prev = prev;
2441 else
2442 ifend = prev;
2443 } else {
2444 iflist = cur->next;
2445 if (iflist)
2446 iflist->prev = NULL;
2447 else
2448 ifend = NULL;
2450 destroy_dahdi_pvt(&cur);
2452 return 0;
2455 static void destroy_all_channels(void)
2457 int x;
2458 struct dahdi_pvt *p, *pl;
2460 while (num_restart_pending) {
2461 usleep(1);
2464 ast_mutex_lock(&iflock);
2465 /* Destroy all the interfaces and free their memory */
2466 p = iflist;
2467 while (p) {
2468 /* Free any callerid */
2469 if (p->cidspill)
2470 ast_free(p->cidspill);
2471 pl = p;
2472 p = p->next;
2473 x = pl->channel;
2474 /* Free associated memory */
2475 if (pl)
2476 destroy_dahdi_pvt(&pl);
2477 if (option_verbose > 2)
2478 ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
2480 iflist = NULL;
2481 ifcount = 0;
2482 ast_mutex_unlock(&iflock);
2485 #ifdef HAVE_PRI
2486 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
2487 static char *zap_send_keypad_facility_app = "ZapSendKeypadFacility";
2489 static char *dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2490 static char *zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI";
2492 static char *dahdi_send_keypad_facility_descrip =
2493 " DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2494 " IE over the current channel.\n";
2495 static char *zap_send_keypad_facility_descrip =
2496 " ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
2497 " IE over the current channel.\n";
2499 static int send_keypad_facility_exec(struct ast_channel *chan, void *data)
2501 /* Data will be our digit string */
2502 struct dahdi_pvt *p;
2503 char *digits = (char *) data;
2505 if (ast_strlen_zero(digits)) {
2506 ast_log(LOG_DEBUG, "No digit string sent to application!\n");
2507 return -1;
2510 p = (struct dahdi_pvt *)chan->tech_pvt;
2512 if (!p) {
2513 ast_log(LOG_DEBUG, "Unable to find technology private\n");
2514 return -1;
2517 ast_mutex_lock(&p->lock);
2519 if (!p->pri || !p->call) {
2520 ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
2521 ast_mutex_unlock(&p->lock);
2522 return -1;
2525 if (!pri_grab(p, p->pri)) {
2526 pri_keypad_facility(p->pri->pri, p->call, digits);
2527 pri_rel(p->pri);
2528 } else {
2529 ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
2530 ast_mutex_unlock(&p->lock);
2531 return -1;
2534 ast_mutex_unlock(&p->lock);
2536 return 0;
2539 static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2541 return send_keypad_facility_exec(chan, data);
2544 static int zap_send_keypad_facility_exec(struct ast_channel *chan, void *data)
2546 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);
2547 return send_keypad_facility_exec(chan, data);
2550 static int pri_is_up(struct dahdi_pri *pri)
2552 int x;
2553 for (x = 0; x < NUM_DCHANS; x++) {
2554 if (pri->dchanavail[x] == DCHAN_AVAILABLE)
2555 return 1;
2557 return 0;
2560 static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
2562 bearer->owner = &inuse;
2563 bearer->realcall = crv;
2564 crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
2565 if (crv->subs[SUB_REAL].owner)
2566 crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
2567 crv->bearer = bearer;
2568 crv->call = bearer->call;
2569 crv->pri = pri;
2570 return 0;
2573 static char *pri_order(int level)
2575 switch (level) {
2576 case 0:
2577 return "Primary";
2578 case 1:
2579 return "Secondary";
2580 case 2:
2581 return "Tertiary";
2582 case 3:
2583 return "Quaternary";
2584 default:
2585 return "<Unknown>";
2589 /* Returns fd of the active dchan */
2590 static int pri_active_dchan_fd(struct dahdi_pri *pri)
2592 int x = -1;
2594 for (x = 0; x < NUM_DCHANS; x++) {
2595 if ((pri->dchans[x] == pri->pri))
2596 break;
2599 return pri->fds[x];
2602 static int pri_find_dchan(struct dahdi_pri *pri)
2604 int oldslot = -1;
2605 struct pri *old;
2606 int newslot = -1;
2607 int x;
2608 old = pri->pri;
2609 for (x = 0; x < NUM_DCHANS; x++) {
2610 if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
2611 newslot = x;
2612 if (pri->dchans[x] == old) {
2613 oldslot = x;
2616 if (newslot < 0) {
2617 newslot = 0;
2618 if (pri->nodetype != BRI_CPE_PTMP) {
2619 ast_log(LOG_WARNING, "No D-channels available! Using Primary channel %d as D-channel anyway!\n",
2620 pri->dchannels[newslot]);
2623 if (old && (oldslot != newslot))
2624 ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
2625 pri->dchannels[oldslot], pri->dchannels[newslot]);
2626 pri->pri = pri->dchans[newslot];
2627 return 0;
2629 #endif
2631 static int dahdi_hangup(struct ast_channel *ast)
2633 int res;
2634 int index,x, law;
2635 /*static int restore_gains(struct dahdi_pvt *p);*/
2636 struct dahdi_pvt *p = ast->tech_pvt;
2637 struct dahdi_pvt *tmp = NULL;
2638 struct dahdi_pvt *prev = NULL;
2639 struct dahdi_params par;
2641 if (option_debug)
2642 ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
2643 if (!ast->tech_pvt) {
2644 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2645 return 0;
2648 ast_mutex_lock(&p->lock);
2650 index = dahdi_get_index(ast, p, 1);
2652 if (p->sig == SIG_PRI) {
2653 x = 1;
2654 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2657 x = 0;
2658 dahdi_confmute(p, 0);
2659 restore_gains(p);
2660 if (p->origcid_num) {
2661 ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
2662 free(p->origcid_num);
2663 p->origcid_num = NULL;
2665 if (p->origcid_name) {
2666 ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
2667 free(p->origcid_name);
2668 p->origcid_name = NULL;
2670 if (p->dsp)
2671 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
2672 if (p->exten)
2673 p->exten[0] = '\0';
2675 if (option_debug)
2676 ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
2677 p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
2678 p->ignoredtmf = 0;
2680 if (index > -1) {
2681 /* Real channel, do some fixup */
2682 p->subs[index].owner = NULL;
2683 p->subs[index].needanswer = 0;
2684 p->subs[index].needflash = 0;
2685 p->subs[index].needringing = 0;
2686 p->subs[index].needbusy = 0;
2687 p->subs[index].needcongestion = 0;
2688 p->subs[index].linear = 0;
2689 p->subs[index].needcallerid = 0;
2690 p->polarity = POLARITY_IDLE;
2691 dahdi_setlinear(p->subs[index].dfd, 0);
2692 if (index == SUB_REAL) {
2693 if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
2694 ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
2695 if (p->subs[SUB_CALLWAIT].inthreeway) {
2696 /* We had flipped over to answer a callwait and now it's gone */
2697 ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
2698 /* Move to the call-wait, but un-own us until they flip back. */
2699 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2700 unalloc_sub(p, SUB_CALLWAIT);
2701 p->owner = NULL;
2702 } else {
2703 /* The three way hung up, but we still have a call wait */
2704 ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
2705 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2706 unalloc_sub(p, SUB_THREEWAY);
2707 if (p->subs[SUB_REAL].inthreeway) {
2708 /* This was part of a three way call. Immediately make way for
2709 another call */
2710 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2711 p->owner = p->subs[SUB_REAL].owner;
2712 } else {
2713 /* This call hasn't been completed yet... Set owner to NULL */
2714 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2715 p->owner = NULL;
2717 p->subs[SUB_REAL].inthreeway = 0;
2719 } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
2720 /* Move to the call-wait and switch back to them. */
2721 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
2722 unalloc_sub(p, SUB_CALLWAIT);
2723 p->owner = p->subs[SUB_REAL].owner;
2724 if (p->owner->_state != AST_STATE_UP)
2725 p->subs[SUB_REAL].needanswer = 1;
2726 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
2727 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
2728 } else if (p->subs[SUB_THREEWAY].dfd > -1) {
2729 swap_subs(p, SUB_THREEWAY, SUB_REAL);
2730 unalloc_sub(p, SUB_THREEWAY);
2731 if (p->subs[SUB_REAL].inthreeway) {
2732 /* This was part of a three way call. Immediately make way for
2733 another call */
2734 ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
2735 p->owner = p->subs[SUB_REAL].owner;
2736 } else {
2737 /* This call hasn't been completed yet... Set owner to NULL */
2738 ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
2739 p->owner = NULL;
2741 p->subs[SUB_REAL].inthreeway = 0;
2743 } else if (index == SUB_CALLWAIT) {
2744 /* Ditch the holding callwait call, and immediately make it availabe */
2745 if (p->subs[SUB_CALLWAIT].inthreeway) {
2746 /* This is actually part of a three way, placed on hold. Place the third part
2747 on music on hold now */
2748 if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
2749 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
2750 S_OR(p->mohsuggest, NULL),
2751 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2753 p->subs[SUB_THREEWAY].inthreeway = 0;
2754 /* Make it the call wait now */
2755 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
2756 unalloc_sub(p, SUB_THREEWAY);
2757 } else
2758 unalloc_sub(p, SUB_CALLWAIT);
2759 } else if (index == SUB_THREEWAY) {
2760 if (p->subs[SUB_CALLWAIT].inthreeway) {
2761 /* The other party of the three way call is currently in a call-wait state.
2762 Start music on hold for them, and take the main guy out of the third call */
2763 if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
2764 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
2765 S_OR(p->mohsuggest, NULL),
2766 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
2768 p->subs[SUB_CALLWAIT].inthreeway = 0;
2770 p->subs[SUB_REAL].inthreeway = 0;
2771 /* If this was part of a three way call index, let us make
2772 another three way call */
2773 unalloc_sub(p, SUB_THREEWAY);
2774 } else {
2775 /* This wasn't any sort of call, but how are we an index? */
2776 ast_log(LOG_WARNING, "Index found but not any type of call?\n");
2780 if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
2781 int outgoing = p->outgoing;
2782 p->owner = NULL;
2783 p->ringt = 0;
2784 p->distinctivering = 0;
2785 p->confirmanswer = 0;
2786 p->cidrings = 1;
2787 p->outgoing = 0;
2788 p->digital = 0;
2789 p->faxhandled = 0;
2790 p->pulsedial = 0;
2791 p->onhooktime = time(NULL);
2792 #ifdef HAVE_PRI
2793 p->proceeding = 0;
2794 p->progress = 0;
2795 p->alerting = 0;
2796 p->setup_ack = 0;
2797 #endif
2798 if (p->dsp) {
2799 ast_dsp_free(p->dsp);
2800 p->dsp = NULL;
2803 law = DAHDI_LAW_DEFAULT;
2804 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
2805 if (res < 0)
2806 ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
2807 /* Perform low level hangup if no owner left */
2808 #ifdef HAVE_PRI
2809 if (p->pri) {
2810 #ifdef SUPPORT_USERUSER
2811 const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
2812 #endif
2814 /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
2815 if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
2816 if (!pri_grab(p, p->pri)) {
2817 if (p->alreadyhungup) {
2818 ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
2820 #ifdef SUPPORT_USERUSER
2821 pri_call_set_useruser(p->call, useruser);
2822 #endif
2824 pri_hangup(p->pri->pri, p->call, -1);
2825 p->call = NULL;
2826 if (p->bearer)
2827 p->bearer->call = NULL;
2828 } else {
2829 const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
2830 int icause = ast->hangupcause ? ast->hangupcause : -1;
2831 ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
2833 #ifdef SUPPORT_USERUSER
2834 pri_call_set_useruser(p->call, useruser);
2835 #endif
2837 p->alreadyhungup = 1;
2838 if (p->bearer)
2839 p->bearer->alreadyhungup = 1;
2840 if (cause) {
2841 if (atoi(cause))
2842 icause = atoi(cause);
2845 pri_hangup(p->pri->pri, p->call, icause);
2847 /* if we send a rel9999ease complete we wont ge no hangup event, so clear the call here */
2848 if (icause == 34 || icause == 44 || icause == 82 || icause == 1 || icause == 81 || icause == 17) {
2849 if ((ast->_state == AST_STATE_RING) || (ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING) || (ast->_state == AST_STATE_RESERVED)) {
2850 p->call = NULL;
2851 } else {
2852 ast_log(LOG_ERROR, "What is wrong with you? You cannot use cause %d number when in state %d!\n", icause, ast->_state);
2853 icause = 16; /* Note, in pri_hangup() libpri will already override the cause */
2857 if (p->pri->nodetype == BRI_NETWORK_PTMP) {
2858 if ((icause == 16 || icause == -1) && (ast->_state != AST_STATE_UP)) {
2859 if (outgoing) {
2860 p->call = NULL;
2867 if (res < 0)
2868 ast_log(LOG_WARNING, "pri_disconnect failed\n");
2869 pri_rel(p->pri);
2870 } else {
2871 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
2872 res = -1;
2874 } else {
2875 if (p->bearer)
2876 ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
2877 p->call = NULL;
2878 res = 0;
2881 #endif
2882 #ifdef HAVE_GSMAT
2883 if (p->gsm.modul) {
2884 if (!p->alreadyhungup)
2885 gsm_hangup(p->gsm.modul);
2887 #endif
2888 if (p->sig && (p->sig != SIG_PRI) && (p->sig != SIG_GSM))
2889 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
2890 if (res < 0) {
2891 ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
2893 switch (p->sig) {
2894 case SIG_FXOGS:
2895 case SIG_FXOLS:
2896 case SIG_FXOKS:
2897 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
2898 if (!res) {
2899 #if 0
2900 ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
2901 #endif
2902 /* If they're off hook, try playing congestion */
2903 if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
2904 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
2905 else
2906 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2908 break;
2909 case SIG_FXSGS:
2910 case SIG_FXSLS:
2911 case SIG_FXSKS:
2912 /* Make sure we're not made available for at least two seconds assuming
2913 we were actually used for an inbound or outbound call. */
2914 if (ast->_state != AST_STATE_RESERVED) {
2915 time(&p->guardtime);
2916 p->guardtime += 2;
2918 break;
2919 default:
2920 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
2922 if (p->cidspill)
2923 free(p->cidspill);
2924 if (p->sig)
2925 dahdi_disable_ec(p);
2926 x = 0;
2927 ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
2928 ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
2929 p->didtdd = 0;
2930 p->cidspill = NULL;
2931 p->callwaitcas = 0;
2932 p->callwaiting = p->permcallwaiting;
2933 p->hidecallerid = p->permhidecallerid;
2934 p->dialing = 0;
2935 p->rdnis[0] = '\0';
2936 update_conf(p);
2937 reset_conf(p);
2938 /* Restore data mode */
2939 if (p->sig == SIG_PRI) {
2940 x = 0;
2941 ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
2943 #ifdef HAVE_PRI
2944 if (p->bearer) {
2945 ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
2946 /* Free up the bearer channel as well, and
2947 don't use its file descriptor anymore */
2948 update_conf(p->bearer);
2949 reset_conf(p->bearer);
2950 p->bearer->owner = NULL;
2951 p->bearer->realcall = NULL;
2952 p->bearer = NULL;
2953 p->subs[SUB_REAL].dfd = -1;
2954 p->pri = NULL;
2956 #endif
2957 if (num_restart_pending == 0)
2958 restart_monitor();
2961 p->callwaitingrepeat = 0;
2962 p->cidcwexpire = 0;
2963 p->oprmode = 0;
2964 ast->tech_pvt = NULL;
2965 ast_mutex_unlock(&p->lock);
2966 ast_module_unref(ast_module_info->self);
2967 if (option_verbose > 2)
2968 ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
2970 ast_mutex_lock(&iflock);
2972 if (p->restartpending) {
2973 num_restart_pending--;
2976 tmp = iflist;
2977 prev = NULL;
2978 if (p->destroy) {
2979 while (tmp) {
2980 if (tmp == p) {
2981 destroy_channel(prev, tmp, 0);
2982 break;
2983 } else {
2984 prev = tmp;
2985 tmp = tmp->next;
2989 ast_mutex_unlock(&iflock);
2990 return 0;
2993 static int dahdi_answer(struct ast_channel *ast)
2995 struct dahdi_pvt *p = ast->tech_pvt;
2996 int res = 0;
2997 int index;
2998 int oldstate = ast->_state;
2999 ast_setstate(ast, AST_STATE_UP);
3000 ast_mutex_lock(&p->lock);
3001 index = dahdi_get_index(ast, p, 0);
3002 if (index < 0)
3003 index = SUB_REAL;
3004 /* nothing to do if a radio channel */
3005 if ((p->radio || (p->oprmode < 0))) {
3006 ast_mutex_unlock(&p->lock);
3007 return 0;
3009 switch (p->sig) {
3010 case SIG_FXSLS:
3011 case SIG_FXSGS:
3012 case SIG_FXSKS:
3013 p->ringt = 0;
3014 /* Fall through */
3015 case SIG_EM:
3016 case SIG_EM_E1:
3017 case SIG_EMWINK:
3018 case SIG_FEATD:
3019 case SIG_FEATDMF:
3020 case SIG_FEATDMF_TA:
3021 case SIG_E911:
3022 case SIG_FGC_CAMA:
3023 case SIG_FGC_CAMAMF:
3024 case SIG_FEATB:
3025 case SIG_SF:
3026 case SIG_SFWINK:
3027 case SIG_SF_FEATD:
3028 case SIG_SF_FEATDMF:
3029 case SIG_SF_FEATB:
3030 case SIG_FXOLS:
3031 case SIG_FXOGS:
3032 case SIG_FXOKS:
3033 /* Pick up the line */
3034 ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
3035 if (p->hanguponpolarityswitch) {
3036 gettimeofday(&p->polaritydelaytv, NULL);
3038 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
3039 tone_zone_play_tone(p->subs[index].dfd, -1);
3040 p->dialing = 0;
3041 if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
3042 if (oldstate == AST_STATE_RINGING) {
3043 ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
3044 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
3045 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3046 p->owner = p->subs[SUB_REAL].owner;
3049 if (p->sig & __DAHDI_SIG_FXS) {
3050 dahdi_enable_ec(p);
3051 dahdi_train_ec(p);
3053 break;
3054 #ifdef HAVE_PRI
3055 case SIG_PRI:
3056 /* Send a pri acknowledge */
3057 if (!pri_grab(p, p->pri)) {
3058 p->proceeding = 1;
3059 res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
3060 pri_rel(p->pri);
3061 /* stop ignoring inband dtmf */
3062 enable_dtmf_detect(p);
3063 } else {
3064 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
3065 res = -1;
3067 /* the audio path is complete now, train the echo canceler */
3068 dahdi_train_ec(p);
3069 break;
3070 #endif
3071 #ifdef HAVE_GSMAT
3072 case SIG_GSM:
3073 if (p->gsm.modul) {
3074 gsm_answer(p->gsm.modul);
3076 break;
3077 #endif
3078 case 0:
3079 ast_mutex_unlock(&p->lock);
3080 return 0;
3081 default:
3082 ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
3083 res = -1;
3085 ast_mutex_unlock(&p->lock);
3086 return res;
3089 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen)
3091 char *cp;
3092 signed char *scp;
3093 int x;
3094 int index;
3095 struct dahdi_pvt *p = chan->tech_pvt, *pp;
3096 struct oprmode *oprmode;
3099 /* all supported options require data */
3100 if (!data || (datalen < 1)) {
3101 errno = EINVAL;
3102 return -1;
3105 switch (option) {
3106 case AST_OPTION_TXGAIN:
3107 scp = (signed char *) data;
3108 index = dahdi_get_index(chan, p, 0);
3109 if (index < 0) {
3110 ast_log(LOG_WARNING, "No index in TXGAIN?\n");
3111 return -1;
3113 if (option_debug)
3114 ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
3115 return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
3116 case AST_OPTION_RXGAIN:
3117 scp = (signed char *) data;
3118 index = dahdi_get_index(chan, p, 0);
3119 if (index < 0) {
3120 ast_log(LOG_WARNING, "No index in RXGAIN?\n");
3121 return -1;
3123 if (option_debug)
3124 ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
3125 return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
3126 case AST_OPTION_TONE_VERIFY:
3127 if (!p->dsp)
3128 break;
3129 cp = (char *) data;
3130 switch (*cp) {
3131 case 1:
3132 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
3133 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
3134 break;
3135 case 2:
3136 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
3137 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
3138 break;
3139 default:
3140 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
3141 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
3142 break;
3144 break;
3145 case AST_OPTION_TDD:
3146 /* turn on or off TDD */
3147 cp = (char *) data;
3148 p->mate = 0;
3149 if (!*cp) { /* turn it off */
3150 if (option_debug)
3151 ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
3152 if (p->tdd)
3153 tdd_free(p->tdd);
3154 p->tdd = 0;
3155 break;
3157 ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
3158 (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
3159 dahdi_disable_ec(p);
3160 /* otherwise, turn it on */
3161 if (!p->didtdd) { /* if havent done it yet */
3162 unsigned char mybuf[41000], *buf;
3163 int size, res, fd, len;
3164 struct pollfd fds[1];
3166 buf = mybuf;
3167 memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
3168 ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
3169 len = 40000;
3170 index = dahdi_get_index(chan, p, 0);
3171 if (index < 0) {
3172 ast_log(LOG_WARNING, "No index in TDD?\n");
3173 return -1;
3175 fd = p->subs[index].dfd;
3176 while (len) {
3177 if (ast_check_hangup(chan))
3178 return -1;
3179 size = len;
3180 if (size > READ_SIZE)
3181 size = READ_SIZE;
3182 fds[0].fd = fd;
3183 fds[0].events = POLLPRI | POLLOUT;
3184 fds[0].revents = 0;
3185 res = poll(fds, 1, -1);
3186 if (!res) {
3187 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
3188 continue;
3190 /* if got exception */
3191 if (fds[0].revents & POLLPRI)
3192 return -1;
3193 if (!(fds[0].revents & POLLOUT)) {
3194 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
3195 continue;
3197 res = write(fd, buf, size);
3198 if (res != size) {
3199 if (res == -1) return -1;
3200 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
3201 break;
3203 len -= size;
3204 buf += size;
3206 p->didtdd = 1; /* set to have done it now */
3208 if (*cp == 2) { /* Mate mode */
3209 if (p->tdd)
3210 tdd_free(p->tdd);
3211 p->tdd = 0;
3212 p->mate = 1;
3213 break;
3215 if (!p->tdd) { /* if we dont have one yet */
3216 p->tdd = tdd_new(); /* allocate one */
3218 break;
3219 case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
3220 if (!p->dsp)
3221 break;
3222 cp = (char *) data;
3223 ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
3224 *cp ? "ON" : "OFF", (int) *cp, chan->name);
3225 p->dtmfrelax = 0;
3226 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
3227 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
3228 break;
3229 case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
3230 cp = (char *) data;
3231 if (!*cp) {
3232 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
3233 x = 0;
3234 dahdi_disable_ec(p);
3235 } else {
3236 ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
3237 x = 1;
3239 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
3240 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
3241 break;
3242 case AST_OPTION_OPRMODE: /* Operator services mode */
3243 oprmode = (struct oprmode *) data;
3244 pp = oprmode->peer->tech_pvt;
3245 p->oprmode = pp->oprmode = 0;
3246 /* setup peers */
3247 p->oprpeer = pp;
3248 pp->oprpeer = p;
3249 /* setup modes, if any */
3250 if (oprmode->mode)
3252 pp->oprmode = oprmode->mode;
3253 p->oprmode = -oprmode->mode;
3255 ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
3256 oprmode->mode, chan->name,oprmode->peer->name);;
3257 break;
3258 case AST_OPTION_ECHOCAN:
3259 cp = (char *) data;
3260 if (*cp) {
3261 ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
3262 dahdi_enable_ec(p);
3263 } else {
3264 ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
3265 dahdi_disable_ec(p);
3267 break;
3269 errno = 0;
3271 return 0;
3274 static int dahdi_func_read(struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
3276 struct dahdi_pvt *p = chan->tech_pvt;
3278 if (!strcasecmp(data, "rxgain")) {
3279 ast_mutex_lock(&p->lock);
3280 snprintf(buf, len, "%f", p->rxgain);
3281 ast_mutex_unlock(&p->lock);
3282 } else if (!strcasecmp(data, "txgain")) {
3283 ast_mutex_lock(&p->lock);
3284 snprintf(buf, len, "%f", p->txgain);
3285 ast_mutex_unlock(&p->lock);
3286 } else {
3287 ast_copy_string(buf, "", len);
3289 return 0;
3293 static void dahdi_unlink(struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
3295 /* Unlink a specific slave or all slaves/masters from a given master */
3296 int x;
3297 int hasslaves;
3298 if (!master)
3299 return;
3300 if (needlock) {
3301 ast_mutex_lock(&master->lock);
3302 if (slave) {
3303 while (ast_mutex_trylock(&slave->lock)) {
3304 DEADLOCK_AVOIDANCE(&master->lock);
3308 hasslaves = 0;
3309 for (x = 0; x < MAX_SLAVES; x++) {
3310 if (master->slaves[x]) {
3311 if (!slave || (master->slaves[x] == slave)) {
3312 /* Take slave out of the conference */
3313 ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
3314 conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
3315 conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
3316 master->slaves[x]->master = NULL;
3317 master->slaves[x] = NULL;
3318 } else
3319 hasslaves = 1;
3321 if (!hasslaves)
3322 master->inconference = 0;
3324 if (!slave) {
3325 if (master->master) {
3326 /* Take master out of the conference */
3327 conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
3328 conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
3329 hasslaves = 0;
3330 for (x = 0; x < MAX_SLAVES; x++) {
3331 if (master->master->slaves[x] == master)
3332 master->master->slaves[x] = NULL;
3333 else if (master->master->slaves[x])
3334 hasslaves = 1;
3336 if (!hasslaves)
3337 master->master->inconference = 0;
3339 master->master = NULL;
3341 update_conf(master);
3342 if (needlock) {
3343 if (slave)
3344 ast_mutex_unlock(&slave->lock);
3345 ast_mutex_unlock(&master->lock);
3349 static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
3350 int x;
3351 if (!slave || !master) {
3352 ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
3353 return;
3355 for (x = 0; x < MAX_SLAVES; x++) {
3356 if (!master->slaves[x]) {
3357 master->slaves[x] = slave;
3358 break;
3361 if (x >= MAX_SLAVES) {
3362 ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
3363 master->slaves[MAX_SLAVES - 1] = slave;
3365 if (slave->master)
3366 ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
3367 slave->master = master;
3369 ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
3372 static void disable_dtmf_detect(struct dahdi_pvt *p)
3374 #ifdef DAHDI_TONEDETECT
3375 int val;
3376 #endif
3378 p->ignoredtmf = 1;
3380 #ifdef DAHDI_TONEDETECT
3381 val = 0;
3382 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3383 #endif
3384 if (!p->hardwaredtmf && p->dsp) {
3385 p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
3386 ast_dsp_set_features(p->dsp, p->dsp_features);
3390 static void enable_dtmf_detect(struct dahdi_pvt *p)
3392 #ifdef DAHDI_TONEDETECT
3393 int val;
3394 #endif
3396 if (p->channel == CHAN_PSEUDO)
3397 return;
3399 p->ignoredtmf = 0;
3401 #ifdef DAHDI_TONEDETECT
3402 val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
3403 ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
3404 #endif
3405 if (!p->hardwaredtmf && p->dsp) {
3406 p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
3407 ast_dsp_set_features(p->dsp, p->dsp_features);
3411 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)
3413 struct ast_channel *who;
3414 struct dahdi_pvt *p0, *p1, *op0, *op1;
3415 struct dahdi_pvt *master = NULL, *slave = NULL;
3416 struct ast_frame *f;
3417 int inconf = 0;
3418 int nothingok = 1;
3419 int ofd0, ofd1;
3420 int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
3421 int os0 = -1, os1 = -1;
3422 int priority = 0;
3423 struct ast_channel *oc0, *oc1;
3424 enum ast_bridge_result res;
3426 #ifdef PRI_2BCT
3427 int triedtopribridge = 0;
3428 q931_call *q931c0 = NULL, *q931c1 = NULL;
3429 #endif
3431 /* For now, don't attempt to native bridge if either channel needs DTMF detection.
3432 There is code below to handle it properly until DTMF is actually seen,
3433 but due to currently unresolved issues it's ignored...
3436 if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
3437 return AST_BRIDGE_FAILED_NOWARN;
3439 ast_mutex_lock(&c0->lock);
3440 while (ast_mutex_trylock(&c1->lock)) {
3441 DEADLOCK_AVOIDANCE(&c0->lock);
3444 p0 = c0->tech_pvt;
3445 p1 = c1->tech_pvt;
3446 /* cant do pseudo-channels here */
3447 if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
3448 ast_mutex_unlock(&c0->lock);
3449 ast_mutex_unlock(&c1->lock);
3450 return AST_BRIDGE_FAILED_NOWARN;
3453 oi0 = dahdi_get_index(c0, p0, 0);
3454 oi1 = dahdi_get_index(c1, p1, 0);
3455 if ((oi0 < 0) || (oi1 < 0)) {
3456 ast_mutex_unlock(&c0->lock);
3457 ast_mutex_unlock(&c1->lock);
3458 return AST_BRIDGE_FAILED;
3461 op0 = p0 = c0->tech_pvt;
3462 op1 = p1 = c1->tech_pvt;
3463 ofd0 = c0->fds[0];
3464 ofd1 = c1->fds[0];
3465 oc0 = p0->owner;
3466 oc1 = p1->owner;
3468 if (ast_mutex_trylock(&p0->lock)) {
3469 /* Don't block, due to potential for deadlock */
3470 ast_mutex_unlock(&c0->lock);
3471 ast_mutex_unlock(&c1->lock);
3472 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3473 return AST_BRIDGE_RETRY;
3475 if (ast_mutex_trylock(&p1->lock)) {
3476 /* Don't block, due to potential for deadlock */
3477 ast_mutex_unlock(&p0->lock);
3478 ast_mutex_unlock(&c0->lock);
3479 ast_mutex_unlock(&c1->lock);
3480 ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
3481 return AST_BRIDGE_RETRY;
3484 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3485 if (p0->owner && p1->owner) {
3486 /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
3487 if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
3488 master = p0;
3489 slave = p1;
3490 inconf = 1;
3491 } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
3492 master = p1;
3493 slave = p0;
3494 inconf = 1;
3495 } else {
3496 ast_log(LOG_WARNING, "Huh? Both calls are callwaits or 3-ways? That's clever...?\n");
3497 ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
3498 p0->channel,
3499 oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3500 p0->subs[SUB_REAL].inthreeway, p0->channel,
3501 oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
3502 p1->subs[SUB_REAL].inthreeway);
3504 nothingok = 0;
3506 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
3507 if (p1->subs[SUB_THREEWAY].inthreeway) {
3508 master = p1;
3509 slave = p0;
3510 nothingok = 0;
3512 } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
3513 if (p0->subs[SUB_THREEWAY].inthreeway) {
3514 master = p0;
3515 slave = p1;
3516 nothingok = 0;
3518 } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
3519 /* We have a real and a call wait. If we're in a three way call, put us in it, otherwise,
3520 don't put us in anything */
3521 if (p1->subs[SUB_CALLWAIT].inthreeway) {
3522 master = p1;
3523 slave = p0;
3524 nothingok = 0;
3526 } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
3527 /* Same as previous */
3528 if (p0->subs[SUB_CALLWAIT].inthreeway) {
3529 master = p0;
3530 slave = p1;
3531 nothingok = 0;
3534 ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
3535 master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
3536 if (master && slave) {
3537 /* Stop any tones, or play ringtone as appropriate. If they're bridged
3538 in an active threeway call with a channel that is ringing, we should
3539 indicate ringing. */
3540 if ((oi1 == SUB_THREEWAY) &&
3541 p1->subs[SUB_THREEWAY].inthreeway &&
3542 p1->subs[SUB_REAL].owner &&
3543 p1->subs[SUB_REAL].inthreeway &&
3544 (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3545 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
3546 tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
3547 os1 = p1->subs[SUB_REAL].owner->_state;
3548 } else {
3549 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
3550 tone_zone_play_tone(p0->subs[oi0].dfd, -1);
3552 if ((oi0 == SUB_THREEWAY) &&
3553 p0->subs[SUB_THREEWAY].inthreeway &&
3554 p0->subs[SUB_REAL].owner &&
3555 p0->subs[SUB_REAL].inthreeway &&
3556 (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
3557 ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
3558 tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
3559 os0 = p0->subs[SUB_REAL].owner->_state;
3560 } else {
3561 ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
3562 tone_zone_play_tone(p1->subs[oi0].dfd, -1);
3564 if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
3565 if (!p0->echocanbridged || !p1->echocanbridged) {
3566 /* Disable echo cancellation if appropriate */
3567 dahdi_disable_ec(p0);
3568 dahdi_disable_ec(p1);
3571 dahdi_link(slave, master);
3572 master->inconference = inconf;
3573 } else if (!nothingok)
3574 ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
3576 update_conf(p0);
3577 update_conf(p1);
3578 t0 = p0->subs[SUB_REAL].inthreeway;
3579 t1 = p1->subs[SUB_REAL].inthreeway;
3581 ast_mutex_unlock(&p0->lock);
3582 ast_mutex_unlock(&p1->lock);
3584 ast_mutex_unlock(&c0->lock);
3585 ast_mutex_unlock(&c1->lock);
3587 /* Native bridge failed */
3588 if ((!master || !slave) && !nothingok) {
3589 dahdi_enable_ec(p0);
3590 dahdi_enable_ec(p1);
3591 return AST_BRIDGE_FAILED;
3594 if (option_verbose > 2)
3595 ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
3597 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3598 disable_dtmf_detect(op0);
3600 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3601 disable_dtmf_detect(op1);
3603 for (;;) {
3604 struct ast_channel *c0_priority[2] = {c0, c1};
3605 struct ast_channel *c1_priority[2] = {c1, c0};
3607 /* Here's our main loop... Start by locking things, looking for private parts,
3608 and then balking if anything is wrong */
3609 ast_mutex_lock(&c0->lock);
3610 while (ast_mutex_trylock(&c1->lock)) {
3611 DEADLOCK_AVOIDANCE(&c0->lock);
3614 p0 = c0->tech_pvt;
3615 p1 = c1->tech_pvt;
3617 if (op0 == p0)
3618 i0 = dahdi_get_index(c0, p0, 1);
3619 if (op1 == p1)
3620 i1 = dahdi_get_index(c1, p1, 1);
3621 ast_mutex_unlock(&c0->lock);
3622 ast_mutex_unlock(&c1->lock);
3624 if (!timeoutms ||
3625 (op0 != p0) ||
3626 (op1 != p1) ||
3627 (ofd0 != c0->fds[0]) ||
3628 (ofd1 != c1->fds[0]) ||
3629 (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
3630 (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
3631 (oc0 != p0->owner) ||
3632 (oc1 != p1->owner) ||
3633 (t0 != p0->subs[SUB_REAL].inthreeway) ||
3634 (t1 != p1->subs[SUB_REAL].inthreeway) ||
3635 (oi0 != i0) ||
3636 (oi1 != i1)) {
3637 ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
3638 op0->channel, oi0, op1->channel, oi1);
3639 res = AST_BRIDGE_RETRY;
3640 goto return_from_bridge;
3643 #ifdef PRI_2BCT
3644 q931c0 = p0->call;
3645 q931c1 = p1->call;
3646 if (p0->transfer && p1->transfer
3647 && q931c0 && q931c1
3648 && !triedtopribridge) {
3649 pri_channel_bridge(q931c0, q931c1);
3650 triedtopribridge = 1;
3652 #endif
3654 who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
3655 if (!who) {
3656 ast_log(LOG_DEBUG, "Ooh, empty read...\n");
3657 continue;
3659 f = ast_read(who);
3660 if (!f || (f->frametype == AST_FRAME_CONTROL)) {
3661 *fo = f;
3662 *rc = who;
3663 res = AST_BRIDGE_COMPLETE;
3664 goto return_from_bridge;
3666 if (f->frametype == AST_FRAME_DTMF) {
3667 if ((who == c0) && p0->pulsedial) {
3668 ast_write(c1, f);
3669 } else if ((who == c1) && p1->pulsedial) {
3670 ast_write(c0, f);
3671 } else {
3672 *fo = f;
3673 *rc = who;
3674 res = AST_BRIDGE_COMPLETE;
3675 goto return_from_bridge;
3678 ast_frfree(f);
3680 /* Swap who gets priority */
3681 priority = !priority;
3684 return_from_bridge:
3685 if (op0 == p0)
3686 dahdi_enable_ec(p0);
3688 if (op1 == p1)
3689 dahdi_enable_ec(p1);
3691 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
3692 enable_dtmf_detect(op0);
3694 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
3695 enable_dtmf_detect(op1);
3697 dahdi_unlink(slave, master, 1);
3699 return res;
3702 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
3704 struct dahdi_pvt *p;
3705 int x;
3706 if (!newchan || !newchan->tech_pvt) {
3707 if (newchan) {
3708 ast_log(LOG_ERROR, "channel %s has no tech_pvt structure\n", newchan->name);
3710 return 0;
3712 p = newchan->tech_pvt;
3713 ast_mutex_lock(&p->lock);
3714 ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
3715 if (p->owner == oldchan) {
3716 p->owner = newchan;
3718 for (x = 0; x < 3; x++)
3719 if (p->subs[x].owner == oldchan) {
3720 if (!x)
3721 dahdi_unlink(NULL, p, 0);
3722 p->subs[x].owner = newchan;
3724 if (newchan->_state == AST_STATE_RINGING)
3725 dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
3726 update_conf(p);
3727 ast_mutex_unlock(&p->lock);
3728 return 0;
3731 static int dahdi_ring_phone(struct dahdi_pvt *p)
3733 int x;
3734 int res;
3735 /* Make sure our transmit state is on hook */
3736 x = 0;
3737 x = DAHDI_ONHOOK;
3738 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3739 do {
3740 x = DAHDI_RING;
3741 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
3742 if (res) {
3743 switch (errno) {
3744 case EBUSY:
3745 case EINTR:
3746 /* Wait just in case */
3747 usleep(10000);
3748 continue;
3749 case EINPROGRESS:
3750 res = 0;
3751 break;
3752 default:
3753 ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
3754 res = 0;
3757 } while (res);
3758 return res;
3761 static void *ss_thread(void *data);
3763 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
3765 static int attempt_transfer(struct dahdi_pvt *p)
3767 /* In order to transfer, we need at least one of the channels to
3768 actually be in a call bridge. We can't conference two applications
3769 together (but then, why would we want to?) */
3770 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
3771 /* The three-way person we're about to transfer to could still be in MOH, so
3772 stop if now if appropriate */
3773 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
3774 ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
3775 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
3776 ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
3778 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
3779 tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
3781 if (p->subs[SUB_REAL].owner->cdr) {
3782 /* Move CDR from second channel to current one */
3783 p->subs[SUB_THREEWAY].owner->cdr =
3784 ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr);
3785 p->subs[SUB_REAL].owner->cdr = NULL;
3787 if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) {
3788 /* Move CDR from second channel's bridge to current one */
3789 p->subs[SUB_THREEWAY].owner->cdr =
3790 ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr);
3791 ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL;
3793 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
3794 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3795 ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
3796 return -1;
3798 /* Orphan the channel after releasing the lock */
3799 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
3800 unalloc_sub(p, SUB_THREEWAY);
3801 } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
3802 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
3803 if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
3804 ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
3806 if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
3807 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
3809 if (p->subs[SUB_THREEWAY].owner->cdr) {
3810 /* Move CDR from second channel to current one */
3811 p->subs[SUB_REAL].owner->cdr =
3812 ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr);
3813 p->subs[SUB_THREEWAY].owner->cdr = NULL;
3815 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) {
3816 /* Move CDR from second channel's bridge to current one */
3817 p->subs[SUB_REAL].owner->cdr =
3818 ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr);
3819 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL;
3821 if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
3822 ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
3823 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
3824 return -1;
3826 /* Three-way is now the REAL */
3827 swap_subs(p, SUB_THREEWAY, SUB_REAL);
3828 ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
3829 unalloc_sub(p, SUB_THREEWAY);
3830 /* Tell the caller not to hangup */
3831 return 1;
3832 } else {
3833 ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
3834 p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
3835 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
3836 return -1;
3838 return 0;
3841 static int check_for_conference(struct dahdi_pvt *p)
3843 struct dahdi_confinfo ci;
3844 /* Fine if we already have a master, etc */
3845 if (p->master || (p->confno > -1))
3846 return 0;
3847 memset(&ci, 0, sizeof(ci));
3848 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
3849 ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
3850 return 0;
3852 /* If we have no master and don't have a confno, then
3853 if we're in a conference, it's probably a MeetMe room or
3854 some such, so don't let us 3-way out! */
3855 if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
3856 if (option_verbose > 2)
3857 ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
3858 return 1;
3860 return 0;
3863 static int get_alarms(struct dahdi_pvt *p)
3865 int res;
3866 struct dahdi_spaninfo zi;
3867 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3869 * The conditional compilation is needed only in asterisk-1.4 for
3870 * backward compatibility with old zaptel drivers that don't have
3871 * a DAHDI_PARAMS.chan_alarms field.
3873 struct dahdi_params params;
3874 #endif
3876 memset(&zi, 0, sizeof(zi));
3877 zi.spanno = p->span;
3879 /* First check for span alarms */
3880 if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
3881 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
3882 return 0;
3884 if (zi.alarms != DAHDI_ALARM_NONE)
3885 return zi.alarms;
3886 #if defined(HAVE_DAHDI) || defined(HAVE_ZAPTEL_CHANALARMS)
3887 /* No alarms on the span. Check for channel alarms. */
3888 if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
3889 return params.chan_alarms;
3890 /* ioctl failed */
3891 ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
3892 #endif
3893 return DAHDI_ALARM_NONE;
3896 static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
3898 struct dahdi_pvt *p = ast->tech_pvt;
3899 struct ast_frame *f = *dest;
3901 if (option_debug)
3902 ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
3904 if (p->confirmanswer) {
3905 if (option_debug)
3906 ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
3907 /* Upon receiving a DTMF digit, consider this an answer confirmation instead
3908 of a DTMF digit */
3909 p->subs[index].f.frametype = AST_FRAME_CONTROL;
3910 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
3911 *dest = &p->subs[index].f;
3912 /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
3913 p->confirmanswer = 0;
3914 } else if (p->callwaitcas) {
3915 if ((f->subclass == 'A') || (f->subclass == 'D')) {
3916 if (option_debug)
3917 ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
3918 if (p->cidspill)
3919 free(p->cidspill);
3920 send_cwcidspill(p);
3922 if ((f->subclass != 'm') && (f->subclass != 'u'))
3923 p->callwaitcas = 0;
3924 p->subs[index].f.frametype = AST_FRAME_NULL;
3925 p->subs[index].f.subclass = 0;
3926 *dest = &p->subs[index].f;
3927 } else if (f->subclass == 'f') {
3928 /* Fax tone -- Handle and return NULL */
3929 if ((p->callprogress & 0x6) && !p->faxhandled) {
3930 p->faxhandled++;
3931 if (strcmp(ast->exten, "fax")) {
3932 const char *target_context = S_OR(ast->macrocontext, ast->context);
3934 if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
3935 if (option_verbose > 2)
3936 ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
3937 /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
3938 pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
3939 if (ast_async_goto(ast, target_context, "fax", 1))
3940 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
3941 } else {
3942 if (option_verbose > 2)
3943 ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
3945 } else if (option_debug)
3946 ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
3947 } else if (option_debug)
3948 ast_log(LOG_DEBUG, "Fax already handled\n");
3949 dahdi_confmute(p, 0);
3950 p->subs[index].f.frametype = AST_FRAME_NULL;
3951 p->subs[index].f.subclass = 0;
3952 *dest = &p->subs[index].f;
3953 } else if (f->subclass == 'm') {
3954 /* Confmute request */
3955 dahdi_confmute(p, 1);
3956 p->subs[index].f.frametype = AST_FRAME_NULL;
3957 p->subs[index].f.subclass = 0;
3958 *dest = &p->subs[index].f;
3959 } else if (f->subclass == 'u') {
3960 /* Unmute */
3961 dahdi_confmute(p, 0);
3962 p->subs[index].f.frametype = AST_FRAME_NULL;
3963 p->subs[index].f.subclass = 0;
3964 *dest = &p->subs[index].f;
3965 } else
3966 dahdi_confmute(p, 0);
3969 static void handle_alarms(struct dahdi_pvt *p, int alarms)
3971 const char *alarm_str = alarm2str(alarms);
3973 /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
3974 * doesn't know what to do with it. Don't confuse users with log messages. */
3975 if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
3976 p->unknown_alarm = 1;
3977 return;
3978 } else {
3979 p->unknown_alarm = 0;
3981 #ifdef HAVE_PRI
3982 if ((p->pri->nodetype == BRI_CPE_PTMP) || (p->pri->nodetype == BRI_CPE)) {
3983 /* Dont annoy BRI TE mode users with layer2layer alarms */
3984 /*! \todo Is this right? */
3985 if (option_debug)
3986 ast_log(LOG_DEBUG, "Ignoring detected alarm on BRI channel %d: %s\n",
3987 p->channel, alarm_str);
3988 return;
3990 #endif
3991 ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
3992 manager_event(EVENT_FLAG_SYSTEM, "Alarm",
3993 "Alarm: %s\r\n"
3994 "Channel: %d\r\n",
3995 alarm_str, p->channel);
3998 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
4000 int res, x;
4001 int index, mysig;
4002 char *c;
4003 struct dahdi_pvt *p = ast->tech_pvt;
4004 pthread_t threadid;
4005 pthread_attr_t attr;
4006 struct ast_channel *chan;
4007 struct ast_frame *f;
4009 index = dahdi_get_index(ast, p, 0);
4010 mysig = p->sig;
4011 if (p->outsigmod > -1)
4012 mysig = p->outsigmod;
4013 p->subs[index].f.frametype = AST_FRAME_NULL;
4014 p->subs[index].f.subclass = 0;
4015 p->subs[index].f.datalen = 0;
4016 p->subs[index].f.samples = 0;
4017 p->subs[index].f.mallocd = 0;
4018 p->subs[index].f.offset = 0;
4019 p->subs[index].f.src = "dahdi_handle_event";
4020 p->subs[index].f.data = NULL;
4021 f = &p->subs[index].f;
4023 if (index < 0)
4024 return &p->subs[index].f;
4025 if (p->fake_event) {
4026 res = p->fake_event;
4027 p->fake_event = 0;
4028 } else
4029 res = dahdi_get_event(p->subs[index].dfd);
4031 if (option_debug)
4032 ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
4034 if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
4035 p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
4037 ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
4038 #ifdef HAVE_PRI
4039 if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
4040 /* absorb event */
4041 } else {
4042 #endif
4043 p->subs[index].f.frametype = AST_FRAME_DTMF_END;
4044 p->subs[index].f.subclass = res & 0xff;
4045 #ifdef HAVE_PRI
4047 #endif
4048 dahdi_handle_dtmfup(ast, index, &f);
4049 return f;
4052 if (res & DAHDI_EVENT_DTMFDOWN) {
4053 if (option_debug)
4054 ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
4055 /* Mute conference */
4056 dahdi_confmute(p, 1);
4057 p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
4058 p->subs[index].f.subclass = res & 0xff;
4059 return &p->subs[index].f;
4062 switch (res) {
4063 #ifdef DAHDI_EVENT_EC_DISABLED
4064 case DAHDI_EVENT_EC_DISABLED:
4065 if (option_verbose > 2)
4066 ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
4067 p->echocanon = 0;
4068 break;
4069 #endif
4070 case DAHDI_EVENT_BITSCHANGED:
4071 ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
4072 case DAHDI_EVENT_PULSE_START:
4073 /* Stop tone if there's a pulse start and the PBX isn't started */
4074 if (!ast->pbx)
4075 tone_zone_play_tone(p->subs[index].dfd, -1);
4076 break;
4077 case DAHDI_EVENT_DIALCOMPLETE:
4078 if (p->inalarm) break;
4079 if ((p->radio || (p->oprmode < 0))) break;
4080 if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
4081 ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
4082 return NULL;
4084 if (!x) { /* if not still dialing in driver */
4085 dahdi_enable_ec(p);
4086 if (p->echobreak) {
4087 dahdi_train_ec(p);
4088 ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
4089 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4090 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4091 p->echobreak = 0;
4092 } else {
4093 p->dialing = 0;
4094 if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
4095 /* if thru with dialing after offhook */
4096 if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
4097 ast_setstate(ast, AST_STATE_UP);
4098 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4099 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4100 break;
4101 } else { /* if to state wait for offhook to dial rest */
4102 /* we now wait for off hook */
4103 ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
4106 if (ast->_state == AST_STATE_DIALING) {
4107 if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
4108 ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
4109 } 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)))) {
4110 ast_setstate(ast, AST_STATE_RINGING);
4111 } else if (!p->answeronpolarityswitch) {
4112 ast_setstate(ast, AST_STATE_UP);
4113 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4114 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4115 /* If aops=0 and hops=1, this is necessary */
4116 p->polarity = POLARITY_REV;
4117 } else {
4118 /* Start clean, so we can catch the change to REV polarity when party answers */
4119 p->polarity = POLARITY_IDLE;
4124 break;
4125 case DAHDI_EVENT_ALARM:
4126 #ifdef HAVE_PRI
4127 if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
4128 /* T309 is not enabled : hangup calls when alarm occurs */
4129 if (p->call) {
4130 if (p->pri && p->pri->pri) {
4131 if (!pri_grab(p, p->pri)) {
4132 pri_hangup(p->pri->pri, p->call, -1); /*! \fixme PRI_CAUSE_INTERWORKING? */
4133 pri_destroycall(p->pri->pri, p->call);
4134 p->call = NULL;
4135 pri_rel(p->pri);
4136 } else
4137 ast_log(LOG_WARNING, "Failed to grab PRI!\n");
4138 } else
4139 ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
4141 if (p->owner)
4142 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
4144 if (p->bearer)
4145 p->bearer->inalarm = 1;
4146 else
4147 #endif
4148 p->inalarm = 1;
4149 res = get_alarms(p);
4150 handle_alarms(p, res);
4151 #ifdef HAVE_LIBPRI
4152 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
4153 /* fall through intentionally */
4154 } else {
4155 break;
4157 #endif
4158 case DAHDI_EVENT_ONHOOK:
4159 if (p->radio) {
4160 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4161 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
4162 break;
4164 if (p->oprmode < 0)
4166 if (p->oprmode != -1) break;
4167 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4169 /* Make sure it starts ringing */
4170 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4171 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
4172 save_conference(p->oprpeer);
4173 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4175 break;
4177 switch (p->sig) {
4178 case SIG_FXOLS:
4179 case SIG_FXOGS:
4180 case SIG_FXOKS:
4181 p->onhooktime = time(NULL);
4182 p->msgstate = -1;
4183 /* Check for some special conditions regarding call waiting */
4184 if (index == SUB_REAL) {
4185 /* The normal line was hung up */
4186 if (p->subs[SUB_CALLWAIT].owner) {
4187 /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
4188 swap_subs(p, SUB_CALLWAIT, SUB_REAL);
4189 if (option_verbose > 2)
4190 ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
4191 unalloc_sub(p, SUB_CALLWAIT);
4192 #if 0
4193 p->subs[index].needanswer = 0;
4194 p->subs[index].needringing = 0;
4195 #endif
4196 p->callwaitingrepeat = 0;
4197 p->cidcwexpire = 0;
4198 p->owner = NULL;
4199 /* Don't start streaming audio yet if the incoming call isn't up yet */
4200 if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
4201 p->dialing = 1;
4202 dahdi_ring_phone(p);
4203 } else if (p->subs[SUB_THREEWAY].owner) {
4204 unsigned int mssinceflash;
4205 /* Here we have to retain the lock on both the main channel, the 3-way channel, and
4206 the private structure -- not especially easy or clean */
4207 while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
4208 /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
4209 ast_mutex_unlock(&p->lock);
4210 DEADLOCK_AVOIDANCE(&ast->lock);
4211 /* We can grab ast and p in that order, without worry. We should make sure
4212 nothing seriously bad has happened though like some sort of bizarre double
4213 masquerade! */
4214 ast_mutex_lock(&p->lock);
4215 if (p->owner != ast) {
4216 ast_log(LOG_WARNING, "This isn't good...\n");
4217 return NULL;
4220 if (!p->subs[SUB_THREEWAY].owner) {
4221 ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
4222 return NULL;
4224 mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
4225 ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
4226 if (mssinceflash < MIN_MS_SINCE_FLASH) {
4227 /* It hasn't been long enough since the last flashook. This is probably a bounce on
4228 hanging up. Hangup both channels now */
4229 if (p->subs[SUB_THREEWAY].owner)
4230 ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
4231 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4232 ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
4233 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4234 } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
4235 if (p->transfer) {
4236 /* In any case this isn't a threeway call anymore */
4237 p->subs[SUB_REAL].inthreeway = 0;
4238 p->subs[SUB_THREEWAY].inthreeway = 0;
4239 /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
4240 if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
4241 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4242 /* Swap subs and dis-own channel */
4243 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4244 p->owner = NULL;
4245 /* Ring the phone */
4246 dahdi_ring_phone(p);
4247 } else {
4248 if ((res = attempt_transfer(p)) < 0) {
4249 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4250 if (p->subs[SUB_THREEWAY].owner)
4251 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4252 } else if (res) {
4253 /* Don't actually hang up at this point */
4254 if (p->subs[SUB_THREEWAY].owner)
4255 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4256 break;
4259 } else {
4260 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4261 if (p->subs[SUB_THREEWAY].owner)
4262 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4264 } else {
4265 ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
4266 /* Swap subs and dis-own channel */
4267 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4268 p->owner = NULL;
4269 /* Ring the phone */
4270 dahdi_ring_phone(p);
4273 } else {
4274 ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
4276 /* Fall through */
4277 default:
4278 dahdi_disable_ec(p);
4279 return NULL;
4281 break;
4282 case DAHDI_EVENT_RINGOFFHOOK:
4283 if (p->inalarm) break;
4284 if (p->oprmode < 0)
4286 if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
4288 /* Make sure it stops ringing */
4289 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4290 tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
4291 restore_conference(p->oprpeer);
4293 break;
4295 if (p->radio)
4297 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4298 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
4299 break;
4301 /* for E911, its supposed to wait for offhook then dial
4302 the second half of the dial string */
4303 if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
4304 c = strchr(p->dialdest, '/');
4305 if (c)
4306 c++;
4307 else
4308 c = p->dialdest;
4309 if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
4310 else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
4311 if (strlen(p->dop.dialstr) > 4) {
4312 memset(p->echorest, 'w', sizeof(p->echorest) - 1);
4313 strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
4314 p->echorest[sizeof(p->echorest) - 1] = '\0';
4315 p->echobreak = 1;
4316 p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
4317 } else
4318 p->echobreak = 0;
4319 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
4320 int saveerr = errno;
4322 x = DAHDI_ONHOOK;
4323 ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
4324 ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
4325 return NULL;
4327 p->dialing = 1;
4328 return &p->subs[index].f;
4330 switch (p->sig) {
4331 case SIG_FXOLS:
4332 case SIG_FXOGS:
4333 case SIG_FXOKS:
4334 switch (ast->_state) {
4335 case AST_STATE_RINGING:
4336 dahdi_enable_ec(p);
4337 dahdi_train_ec(p);
4338 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4339 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4340 /* Make sure it stops ringing */
4341 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4342 ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
4343 if (p->cidspill) {
4344 /* Cancel any running CallerID spill */
4345 free(p->cidspill);
4346 p->cidspill = NULL;
4348 p->dialing = 0;
4349 p->callwaitcas = 0;
4350 if (p->confirmanswer) {
4351 /* Ignore answer if "confirm answer" is enabled */
4352 p->subs[index].f.frametype = AST_FRAME_NULL;
4353 p->subs[index].f.subclass = 0;
4354 } else if (!ast_strlen_zero(p->dop.dialstr)) {
4355 /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
4356 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4357 if (res < 0) {
4358 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4359 p->dop.dialstr[0] = '\0';
4360 return NULL;
4361 } else {
4362 ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
4363 p->subs[index].f.frametype = AST_FRAME_NULL;
4364 p->subs[index].f.subclass = 0;
4365 p->dialing = 1;
4367 p->dop.dialstr[0] = '\0';
4368 ast_setstate(ast, AST_STATE_DIALING);
4369 } else
4370 ast_setstate(ast, AST_STATE_UP);
4371 return &p->subs[index].f;
4372 case AST_STATE_DOWN:
4373 ast_setstate(ast, AST_STATE_RING);
4374 ast->rings = 1;
4375 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4376 p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
4377 ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
4378 return &p->subs[index].f;
4379 case AST_STATE_UP:
4380 /* Make sure it stops ringing */
4381 dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
4382 /* Okay -- probably call waiting*/
4383 if (ast_bridged_channel(p->owner))
4384 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4385 p->subs[index].needunhold = 1;
4386 break;
4387 case AST_STATE_RESERVED:
4388 /* Start up dialtone */
4389 if (has_voicemail(p))
4390 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
4391 else
4392 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
4393 break;
4394 default:
4395 ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
4397 break;
4398 case SIG_FXSLS:
4399 case SIG_FXSGS:
4400 case SIG_FXSKS:
4401 if (ast->_state == AST_STATE_RING) {
4402 p->ringt = p->ringt_base;
4405 /* Fall through */
4406 case SIG_EM:
4407 case SIG_EM_E1:
4408 case SIG_EMWINK:
4409 case SIG_FEATD:
4410 case SIG_FEATDMF:
4411 case SIG_FEATDMF_TA:
4412 case SIG_E911:
4413 case SIG_FGC_CAMA:
4414 case SIG_FGC_CAMAMF:
4415 case SIG_FEATB:
4416 case SIG_SF:
4417 case SIG_SFWINK:
4418 case SIG_SF_FEATD:
4419 case SIG_SF_FEATDMF:
4420 case SIG_SF_FEATB:
4421 if (ast->_state == AST_STATE_PRERING)
4422 ast_setstate(ast, AST_STATE_RING);
4423 if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
4424 if (option_debug)
4425 ast_log(LOG_DEBUG, "Ring detected\n");
4426 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4427 p->subs[index].f.subclass = AST_CONTROL_RING;
4428 } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
4429 if (option_debug)
4430 ast_log(LOG_DEBUG, "Line answered\n");
4431 if (p->confirmanswer) {
4432 p->subs[index].f.frametype = AST_FRAME_NULL;
4433 p->subs[index].f.subclass = 0;
4434 } else {
4435 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4436 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
4437 ast_setstate(ast, AST_STATE_UP);
4439 } else if (ast->_state != AST_STATE_RING)
4440 ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
4441 break;
4442 default:
4443 ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
4445 break;
4446 #ifdef DAHDI_EVENT_RINGBEGIN
4447 case DAHDI_EVENT_RINGBEGIN:
4448 switch (p->sig) {
4449 case SIG_FXSLS:
4450 case SIG_FXSGS:
4451 case SIG_FXSKS:
4452 if (ast->_state == AST_STATE_RING) {
4453 p->ringt = p->ringt_base;
4455 break;
4457 break;
4458 #endif
4459 case DAHDI_EVENT_RINGEROFF:
4460 if (p->inalarm) break;
4461 if ((p->radio || (p->oprmode < 0))) break;
4462 ast->rings++;
4463 if ((ast->rings > p->cidrings) && (p->cidspill)) {
4464 ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
4465 free(p->cidspill);
4466 p->cidspill = NULL;
4467 p->callwaitcas = 0;
4469 p->subs[index].f.frametype = AST_FRAME_CONTROL;
4470 p->subs[index].f.subclass = AST_CONTROL_RINGING;
4471 break;
4472 case DAHDI_EVENT_RINGERON:
4473 break;
4474 case DAHDI_EVENT_NOALARM:
4475 p->inalarm = 0;
4476 #ifdef HAVE_PRI
4477 /* Extremely unlikely but just in case */
4478 if (p->bearer)
4479 p->bearer->inalarm = 0;
4480 #endif
4481 if (!p->unknown_alarm) {
4482 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
4483 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
4484 "Channel: %d\r\n", p->channel);
4485 } else {
4486 p->unknown_alarm = 0;
4488 break;
4489 case DAHDI_EVENT_WINKFLASH:
4490 if (p->inalarm) break;
4491 if (p->radio) break;
4492 if (p->oprmode < 0) break;
4493 if (p->oprmode > 1)
4495 struct dahdi_params par;
4497 if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
4499 if (!par.rxisoffhook)
4501 /* Make sure it stops ringing */
4502 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
4503 dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
4504 save_conference(p);
4505 tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4508 break;
4510 /* Remember last time we got a flash-hook */
4511 gettimeofday(&p->flashtime, NULL);
4512 switch (mysig) {
4513 case SIG_FXOLS:
4514 case SIG_FXOGS:
4515 case SIG_FXOKS:
4516 ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
4517 index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
4518 p->callwaitcas = 0;
4520 if (index != SUB_REAL) {
4521 ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
4522 goto winkflashdone;
4525 if (p->subs[SUB_CALLWAIT].owner) {
4526 /* Swap to call-wait */
4527 swap_subs(p, SUB_REAL, SUB_CALLWAIT);
4528 tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
4529 p->owner = p->subs[SUB_REAL].owner;
4530 ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
4531 if (p->owner->_state == AST_STATE_RINGING) {
4532 ast_setstate(p->owner, AST_STATE_UP);
4533 p->subs[SUB_REAL].needanswer = 1;
4535 p->callwaitingrepeat = 0;
4536 p->cidcwexpire = 0;
4537 /* Start music on hold if appropriate */
4538 if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
4539 ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
4540 S_OR(p->mohsuggest, NULL),
4541 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4543 p->subs[SUB_CALLWAIT].needhold = 1;
4544 if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
4545 ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
4546 S_OR(p->mohsuggest, NULL),
4547 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4549 p->subs[SUB_REAL].needunhold = 1;
4550 } else if (!p->subs[SUB_THREEWAY].owner) {
4551 char cid_num[256];
4552 char cid_name[256];
4554 if (!p->threewaycalling) {
4555 /* Just send a flash if no 3-way calling */
4556 p->subs[SUB_REAL].needflash = 1;
4557 goto winkflashdone;
4558 } else if (!check_for_conference(p)) {
4559 if (p->dahditrcallerid && p->owner) {
4560 if (p->owner->cid.cid_num)
4561 ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
4562 if (p->owner->cid.cid_name)
4563 ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
4565 /* XXX This section needs much more error checking!!! XXX */
4566 /* Start a 3-way call if feasible */
4567 if (!((ast->pbx) ||
4568 (ast->_state == AST_STATE_UP) ||
4569 (ast->_state == AST_STATE_RING))) {
4570 ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
4571 goto winkflashdone;
4573 if (alloc_sub(p, SUB_THREEWAY)) {
4574 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
4575 goto winkflashdone;
4577 /* Make new channel */
4578 chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
4579 if (p->dahditrcallerid) {
4580 if (!p->origcid_num)
4581 p->origcid_num = ast_strdup(p->cid_num);
4582 if (!p->origcid_name)
4583 p->origcid_name = ast_strdup(p->cid_name);
4584 ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
4585 ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
4587 /* Swap things around between the three-way and real call */
4588 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4589 /* Disable echo canceller for better dialing */
4590 dahdi_disable_ec(p);
4591 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
4592 if (res)
4593 ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
4594 p->owner = chan;
4595 pthread_attr_init(&attr);
4596 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
4597 if (!chan) {
4598 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
4599 } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
4600 ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
4601 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
4602 dahdi_enable_ec(p);
4603 ast_hangup(chan);
4604 } else {
4605 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4606 int way3bridge = 0, cdr3way = 0;
4608 if (!other) {
4609 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4610 } else
4611 way3bridge = 1;
4613 if (p->subs[SUB_THREEWAY].owner->cdr)
4614 cdr3way = 1;
4616 if (option_verbose > 2)
4617 ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
4618 /* Start music on hold if appropriate */
4619 if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
4620 ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
4621 S_OR(p->mohsuggest, NULL),
4622 !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
4624 p->subs[SUB_THREEWAY].needhold = 1;
4626 pthread_attr_destroy(&attr);
4628 } else {
4629 /* Already have a 3 way call */
4630 if (p->subs[SUB_THREEWAY].inthreeway) {
4631 /* Call is already up, drop the last person */
4632 if (option_debug)
4633 ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
4634 /* If the primary call isn't answered yet, use it */
4635 if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
4636 /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
4637 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4638 p->owner = p->subs[SUB_REAL].owner;
4640 /* Drop the last call and stop the conference */
4641 if (option_verbose > 2)
4642 ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
4643 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4644 p->subs[SUB_REAL].inthreeway = 0;
4645 p->subs[SUB_THREEWAY].inthreeway = 0;
4646 } else {
4647 /* Lets see what we're up to */
4648 if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
4649 (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
4650 int otherindex = SUB_THREEWAY;
4651 struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
4652 int way3bridge = 0, cdr3way = 0;
4654 if (!other) {
4655 other = ast_bridged_channel(p->subs[SUB_REAL].owner);
4656 } else
4657 way3bridge = 1;
4659 if (p->subs[SUB_THREEWAY].owner->cdr)
4660 cdr3way = 1;
4662 if (option_verbose > 2)
4663 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);
4664 /* Put them in the threeway, and flip */
4665 p->subs[SUB_THREEWAY].inthreeway = 1;
4666 p->subs[SUB_REAL].inthreeway = 1;
4667 if (ast->_state == AST_STATE_UP) {
4668 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4669 otherindex = SUB_REAL;
4671 if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
4672 ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
4673 p->subs[otherindex].needunhold = 1;
4674 p->owner = p->subs[SUB_REAL].owner;
4675 if (ast->_state == AST_STATE_RINGING) {
4676 ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
4677 res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
4678 res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
4680 } else {
4681 if (option_verbose > 2)
4682 ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
4683 swap_subs(p, SUB_THREEWAY, SUB_REAL);
4684 p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
4685 p->owner = p->subs[SUB_REAL].owner;
4686 if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
4687 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
4688 p->subs[SUB_REAL].needunhold = 1;
4689 dahdi_enable_ec(p);
4694 winkflashdone:
4695 update_conf(p);
4696 break;
4697 case SIG_EM:
4698 case SIG_EM_E1:
4699 case SIG_EMWINK:
4700 case SIG_FEATD:
4701 case SIG_SF:
4702 case SIG_SFWINK:
4703 case SIG_SF_FEATD:
4704 case SIG_FXSLS:
4705 case SIG_FXSGS:
4706 if (p->dialing)
4707 ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
4708 else
4709 ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
4710 break;
4711 case SIG_FEATDMF_TA:
4712 switch (p->whichwink) {
4713 case 0:
4714 ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4715 snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
4716 break;
4717 case 1:
4718 ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
4719 break;
4720 case 2:
4721 ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
4722 return NULL;
4724 p->whichwink++;
4725 /* Fall through */
4726 case SIG_FEATDMF:
4727 case SIG_E911:
4728 case SIG_FGC_CAMAMF:
4729 case SIG_FGC_CAMA:
4730 case SIG_FEATB:
4731 case SIG_SF_FEATDMF:
4732 case SIG_SF_FEATB:
4733 /* FGD MF *Must* wait for wink */
4734 if (!ast_strlen_zero(p->dop.dialstr)) {
4735 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4736 if (res < 0) {
4737 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4738 p->dop.dialstr[0] = '\0';
4739 return NULL;
4740 } else
4741 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4743 p->dop.dialstr[0] = '\0';
4744 break;
4745 default:
4746 ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
4748 break;
4749 case DAHDI_EVENT_HOOKCOMPLETE:
4750 if (p->inalarm) break;
4751 if ((p->radio || (p->oprmode < 0))) break;
4752 switch (mysig) {
4753 case SIG_FXSLS: /* only interesting for FXS */
4754 case SIG_FXSGS:
4755 case SIG_FXSKS:
4756 case SIG_EM:
4757 case SIG_EM_E1:
4758 case SIG_EMWINK:
4759 case SIG_FEATD:
4760 case SIG_SF:
4761 case SIG_SFWINK:
4762 case SIG_SF_FEATD:
4763 if (!ast_strlen_zero(p->dop.dialstr)) {
4764 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
4765 if (res < 0) {
4766 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
4767 p->dop.dialstr[0] = '\0';
4768 return NULL;
4769 } else
4770 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
4772 p->dop.dialstr[0] = '\0';
4773 p->dop.op = DAHDI_DIAL_OP_REPLACE;
4774 break;
4775 case SIG_FEATDMF:
4776 case SIG_FEATDMF_TA:
4777 case SIG_E911:
4778 case SIG_FGC_CAMA:
4779 case SIG_FGC_CAMAMF:
4780 case SIG_FEATB:
4781 case SIG_SF_FEATDMF:
4782 case SIG_SF_FEATB:
4783 ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
4784 break;
4785 default:
4786 break;
4788 break;
4789 case DAHDI_EVENT_POLARITY:
4791 * If we get a Polarity Switch event, check to see
4792 * if we should change the polarity state and
4793 * mark the channel as UP or if this is an indication
4794 * of remote end disconnect.
4796 if (p->polarity == POLARITY_IDLE) {
4797 p->polarity = POLARITY_REV;
4798 if (p->answeronpolarityswitch &&
4799 ((ast->_state == AST_STATE_DIALING) ||
4800 (ast->_state == AST_STATE_RINGING))) {
4801 ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
4802 ast_setstate(p->owner, AST_STATE_UP);
4803 if (p->hanguponpolarityswitch) {
4804 gettimeofday(&p->polaritydelaytv, NULL);
4806 } else
4807 ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
4809 /* Removed else statement from here as it was preventing hangups from ever happening*/
4810 /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
4811 if (p->hanguponpolarityswitch &&
4812 (p->polarityonanswerdelay > 0) &&
4813 (p->polarity == POLARITY_REV) &&
4814 ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
4815 /* Added log_debug information below to provide a better indication of what is going on */
4816 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) );
4818 if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
4819 ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
4820 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
4821 p->polarity = POLARITY_IDLE;
4822 } else {
4823 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);
4825 } else {
4826 p->polarity = POLARITY_IDLE;
4827 ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
4829 /* Added more log_debug information below to provide a better indication of what is going on */
4830 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) );
4831 break;
4832 default:
4833 ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
4835 return &p->subs[index].f;
4838 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
4840 struct dahdi_pvt *p = ast->tech_pvt;
4841 int res;
4842 int usedindex=-1;
4843 int index;
4844 struct ast_frame *f;
4847 index = dahdi_get_index(ast, p, 1);
4849 p->subs[index].f.frametype = AST_FRAME_NULL;
4850 p->subs[index].f.datalen = 0;
4851 p->subs[index].f.samples = 0;
4852 p->subs[index].f.mallocd = 0;
4853 p->subs[index].f.offset = 0;
4854 p->subs[index].f.subclass = 0;
4855 p->subs[index].f.delivery = ast_tv(0,0);
4856 p->subs[index].f.src = "dahdi_exception";
4857 p->subs[index].f.data = NULL;
4860 if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
4861 /* If nobody owns us, absorb the event appropriately, otherwise
4862 we loop indefinitely. This occurs when, during call waiting, the
4863 other end hangs up our channel so that it no longer exists, but we
4864 have neither FLASH'd nor ONHOOK'd to signify our desire to
4865 change to the other channel. */
4866 if (p->fake_event) {
4867 res = p->fake_event;
4868 p->fake_event = 0;
4869 } else
4870 res = dahdi_get_event(p->subs[SUB_REAL].dfd);
4871 /* Switch to real if there is one and this isn't something really silly... */
4872 if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
4873 (res != DAHDI_EVENT_HOOKCOMPLETE)) {
4874 ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
4875 p->owner = p->subs[SUB_REAL].owner;
4876 if (p->owner && ast_bridged_channel(p->owner))
4877 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4878 p->subs[SUB_REAL].needunhold = 1;
4880 switch (res) {
4881 case DAHDI_EVENT_ONHOOK:
4882 dahdi_disable_ec(p);
4883 if (p->owner) {
4884 if (option_verbose > 2)
4885 ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
4886 dahdi_ring_phone(p);
4887 p->callwaitingrepeat = 0;
4888 p->cidcwexpire = 0;
4889 } else
4890 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4891 update_conf(p);
4892 break;
4893 case DAHDI_EVENT_RINGOFFHOOK:
4894 dahdi_enable_ec(p);
4895 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
4896 if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
4897 p->subs[SUB_REAL].needanswer = 1;
4898 p->dialing = 0;
4900 break;
4901 case DAHDI_EVENT_HOOKCOMPLETE:
4902 case DAHDI_EVENT_RINGERON:
4903 case DAHDI_EVENT_RINGEROFF:
4904 /* Do nothing */
4905 break;
4906 case DAHDI_EVENT_WINKFLASH:
4907 gettimeofday(&p->flashtime, NULL);
4908 if (p->owner) {
4909 if (option_verbose > 2)
4910 ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
4911 if (p->owner->_state != AST_STATE_UP) {
4912 /* Answer if necessary */
4913 usedindex = dahdi_get_index(p->owner, p, 0);
4914 if (usedindex > -1) {
4915 p->subs[usedindex].needanswer = 1;
4917 ast_setstate(p->owner, AST_STATE_UP);
4919 p->callwaitingrepeat = 0;
4920 p->cidcwexpire = 0;
4921 if (ast_bridged_channel(p->owner))
4922 ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
4923 p->subs[SUB_REAL].needunhold = 1;
4924 } else
4925 ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
4926 update_conf(p);
4927 break;
4928 default:
4929 ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
4931 f = &p->subs[index].f;
4932 return f;
4934 if (!(p->radio || (p->oprmode < 0)) && option_debug)
4935 ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
4936 /* If it's not us, return NULL immediately */
4937 if (ast != p->owner) {
4938 ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
4939 f = &p->subs[index].f;
4940 return f;
4942 f = dahdi_handle_event(ast);
4943 return f;
4946 static struct ast_frame *dahdi_exception(struct ast_channel *ast)
4948 struct dahdi_pvt *p = ast->tech_pvt;
4949 struct ast_frame *f;
4950 ast_mutex_lock(&p->lock);
4951 f = __dahdi_exception(ast);
4952 ast_mutex_unlock(&p->lock);
4953 return f;
4956 static struct ast_frame *dahdi_read(struct ast_channel *ast)
4958 struct dahdi_pvt *p = ast->tech_pvt;
4959 int res;
4960 int index;
4961 void *readbuf;
4962 struct ast_frame *f;
4964 while (ast_mutex_trylock(&p->lock)) {
4965 DEADLOCK_AVOIDANCE(&ast->lock);
4968 index = dahdi_get_index(ast, p, 0);
4970 /* Hang up if we don't really exist */
4971 if (index < 0) {
4972 ast_log(LOG_WARNING, "We dont exist?\n");
4973 ast_mutex_unlock(&p->lock);
4974 return NULL;
4977 if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
4979 p->subs[index].f.frametype = AST_FRAME_NULL;
4980 p->subs[index].f.datalen = 0;
4981 p->subs[index].f.samples = 0;
4982 p->subs[index].f.mallocd = 0;
4983 p->subs[index].f.offset = 0;
4984 p->subs[index].f.subclass = 0;
4985 p->subs[index].f.delivery = ast_tv(0,0);
4986 p->subs[index].f.src = "dahdi_read";
4987 p->subs[index].f.data = NULL;
4989 /* make sure it sends initial key state as first frame */
4990 if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
4992 struct dahdi_params ps;
4994 ps.channo = p->channel;
4995 if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
4996 ast_mutex_unlock(&p->lock);
4997 return NULL;
4999 p->firstradio = 1;
5000 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5001 if (ps.rxisoffhook)
5003 p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
5005 else
5007 p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
5009 ast_mutex_unlock(&p->lock);
5010 return &p->subs[index].f;
5012 if (p->ringt == 1) {
5013 ast_mutex_unlock(&p->lock);
5014 return NULL;
5016 else if (p->ringt > 0)
5017 p->ringt--;
5019 if (p->subs[index].needringing) {
5020 /* Send ringing frame if requested */
5021 p->subs[index].needringing = 0;
5022 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5023 p->subs[index].f.subclass = AST_CONTROL_RINGING;
5024 ast_setstate(ast, AST_STATE_RINGING);
5025 ast_mutex_unlock(&p->lock);
5026 return &p->subs[index].f;
5029 if (p->subs[index].needbusy) {
5030 /* Send busy frame if requested */
5031 p->subs[index].needbusy = 0;
5032 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5033 p->subs[index].f.subclass = AST_CONTROL_BUSY;
5034 ast_mutex_unlock(&p->lock);
5035 return &p->subs[index].f;
5038 if (p->subs[index].needcongestion) {
5039 /* Send congestion frame if requested */
5040 p->subs[index].needcongestion = 0;
5041 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5042 p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
5043 ast_mutex_unlock(&p->lock);
5044 return &p->subs[index].f;
5047 if (p->subs[index].needcallerid) {
5048 ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
5049 S_OR(p->lastcid_name, NULL),
5050 S_OR(p->lastcid_num, NULL)
5052 p->subs[index].needcallerid = 0;
5055 if (p->subs[index].needanswer) {
5056 /* Send answer frame if requested */
5057 p->subs[index].needanswer = 0;
5058 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5059 p->subs[index].f.subclass = AST_CONTROL_ANSWER;
5060 ast_mutex_unlock(&p->lock);
5061 return &p->subs[index].f;
5064 if (p->subs[index].needflash) {
5065 /* Send answer frame if requested */
5066 p->subs[index].needflash = 0;
5067 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5068 p->subs[index].f.subclass = AST_CONTROL_FLASH;
5069 ast_mutex_unlock(&p->lock);
5070 return &p->subs[index].f;
5073 if (p->subs[index].needhold) {
5074 /* Send answer frame if requested */
5075 p->subs[index].needhold = 0;
5076 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5077 p->subs[index].f.subclass = AST_CONTROL_HOLD;
5078 ast_mutex_unlock(&p->lock);
5079 ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
5080 return &p->subs[index].f;
5083 if (p->subs[index].needunhold) {
5084 /* Send answer frame if requested */
5085 p->subs[index].needunhold = 0;
5086 p->subs[index].f.frametype = AST_FRAME_CONTROL;
5087 p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
5088 ast_mutex_unlock(&p->lock);
5089 ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
5090 return &p->subs[index].f;
5093 if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
5094 if (!p->subs[index].linear) {
5095 p->subs[index].linear = 1;
5096 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5097 if (res)
5098 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
5100 } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
5101 (ast->rawreadformat == AST_FORMAT_ALAW)) {
5102 if (p->subs[index].linear) {
5103 p->subs[index].linear = 0;
5104 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5105 if (res)
5106 ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
5108 } else {
5109 ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
5110 ast_mutex_unlock(&p->lock);
5111 return NULL;
5113 readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
5114 CHECK_BLOCKING(ast);
5115 res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
5116 ast_clear_flag(ast, AST_FLAG_BLOCKING);
5117 /* Check for hangup */
5118 if (res < 0) {
5119 f = NULL;
5120 if (res == -1) {
5121 if (errno == EAGAIN) {
5122 /* Return "NULL" frame if there is nobody there */
5123 ast_mutex_unlock(&p->lock);
5124 return &p->subs[index].f;
5125 } else if (errno == ELAST) {
5126 f = __dahdi_exception(ast);
5127 } else
5128 ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
5130 ast_mutex_unlock(&p->lock);
5131 return f;
5133 if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
5134 ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
5135 f = __dahdi_exception(ast);
5136 ast_mutex_unlock(&p->lock);
5137 return f;
5139 if (p->tdd) { /* if in TDD mode, see if we receive that */
5140 int c;
5142 c = tdd_feed(p->tdd,readbuf,READ_SIZE);
5143 if (c < 0) {
5144 ast_log(LOG_DEBUG,"tdd_feed failed\n");
5145 ast_mutex_unlock(&p->lock);
5146 return NULL;
5148 if (c) { /* if a char to return */
5149 p->subs[index].f.subclass = 0;
5150 p->subs[index].f.frametype = AST_FRAME_TEXT;
5151 p->subs[index].f.mallocd = 0;
5152 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
5153 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
5154 p->subs[index].f.datalen = 1;
5155 *((char *) p->subs[index].f.data) = c;
5156 ast_mutex_unlock(&p->lock);
5157 return &p->subs[index].f;
5160 /* Ensure the CW timer decrements only on a single subchannel */
5161 if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
5162 p->callwaitingrepeat--;
5164 if (p->cidcwexpire)
5165 p->cidcwexpire--;
5166 /* Repeat callwaiting */
5167 if (p->callwaitingrepeat == 1) {
5168 p->callwaitrings++;
5169 dahdi_callwait(ast);
5171 /* Expire CID/CW */
5172 if (p->cidcwexpire == 1) {
5173 if (option_verbose > 2)
5174 ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
5175 restore_conference(p);
5177 if (p->subs[index].linear) {
5178 p->subs[index].f.datalen = READ_SIZE * 2;
5179 } else
5180 p->subs[index].f.datalen = READ_SIZE;
5182 /* Handle CallerID Transmission */
5183 if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
5184 send_callerid(p);
5187 p->subs[index].f.frametype = AST_FRAME_VOICE;
5188 p->subs[index].f.subclass = ast->rawreadformat;
5189 p->subs[index].f.samples = READ_SIZE;
5190 p->subs[index].f.mallocd = 0;
5191 p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
5192 p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
5193 #if 0
5194 ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
5195 #endif
5196 if (p->dialing || /* Transmitting something */
5197 (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
5198 ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
5200 /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
5201 don't send anything */
5202 p->subs[index].f.frametype = AST_FRAME_NULL;
5203 p->subs[index].f.subclass = 0;
5204 p->subs[index].f.samples = 0;
5205 p->subs[index].f.mallocd = 0;
5206 p->subs[index].f.offset = 0;
5207 p->subs[index].f.data = NULL;
5208 p->subs[index].f.datalen= 0;
5210 if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress) && !index) {
5211 /* Perform busy detection. etc on the dahdi line */
5212 f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
5213 if (f) {
5214 if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
5215 if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
5216 /* Treat this as a "hangup" instead of a "busy" on the assumption that
5217 a busy */
5218 f = NULL;
5220 } else if (f->frametype == AST_FRAME_DTMF) {
5221 #ifdef HAVE_PRI
5222 if (p->sig==SIG_PRI && p->pri && p->pri->overlapdial && p->ignoredtmf) {
5223 /* Don't accept in-band DTMF when in overlap dial mode
5224 or when in non-overlap overlapdialing mode ... */
5225 f->frametype = AST_FRAME_NULL;
5226 f->subclass = 0;
5228 #endif
5229 /* DSP clears us of being pulse */
5230 p->pulsedial = 0;
5233 } else
5234 f = &p->subs[index].f;
5236 if (f && (f->frametype == AST_FRAME_DTMF))
5237 dahdi_handle_dtmfup(ast, index, &f);
5239 /* If we have a fake_event, trigger exception to handle it */
5240 if (p->fake_event)
5241 ast_set_flag(ast, AST_FLAG_EXCEPTION);
5243 ast_mutex_unlock(&p->lock);
5244 return f;
5247 static int my_dahdi_write(struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
5249 int sent=0;
5250 int size;
5251 int res;
5252 int fd;
5253 fd = p->subs[index].dfd;
5254 while (len) {
5255 size = len;
5256 if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
5257 size = (linear ? READ_SIZE * 2 : READ_SIZE);
5258 res = write(fd, buf, size);
5259 if (res != size) {
5260 if (option_debug)
5261 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
5262 return sent;
5264 len -= size;
5265 buf += size;
5267 return sent;
5270 static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
5272 struct dahdi_pvt *p = ast->tech_pvt;
5273 int res;
5274 int index;
5275 index = dahdi_get_index(ast, p, 0);
5276 if (index < 0) {
5277 ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
5278 return -1;
5281 #if 0
5282 #ifdef HAVE_PRI
5283 ast_mutex_lock(&p->lock);
5284 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5285 if (p->pri->pri) {
5286 if (!pri_grab(p, p->pri)) {
5287 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5288 pri_rel(p->pri);
5289 } else
5290 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5292 p->proceeding=1;
5294 ast_mutex_unlock(&p->lock);
5295 #endif
5296 #endif
5297 /* Write a frame of (presumably voice) data */
5298 if (frame->frametype != AST_FRAME_VOICE) {
5299 if (frame->frametype == AST_FRAME_TEXT) {
5300 ast_log(LOG_NOTICE, "text\n");
5301 } else if (frame->frametype != AST_FRAME_IMAGE)
5302 ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
5303 return 0;
5305 if ((frame->subclass != AST_FORMAT_SLINEAR) &&
5306 (frame->subclass != AST_FORMAT_ULAW) &&
5307 (frame->subclass != AST_FORMAT_ALAW)) {
5308 ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
5309 return -1;
5311 if (p->dialing) {
5312 if (option_debug)
5313 ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
5314 return 0;
5316 if (!p->owner) {
5317 if (option_debug)
5318 ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
5319 return 0;
5321 if (p->cidspill) {
5322 if (option_debug)
5323 ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
5324 return 0;
5326 /* Return if it's not valid data */
5327 if (!frame->data || !frame->datalen)
5328 return 0;
5330 if (frame->subclass == AST_FORMAT_SLINEAR) {
5331 if (!p->subs[index].linear) {
5332 p->subs[index].linear = 1;
5333 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5334 if (res)
5335 ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
5337 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
5338 } else {
5339 /* x-law already */
5340 if (p->subs[index].linear) {
5341 p->subs[index].linear = 0;
5342 res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
5343 if (res)
5344 ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
5346 res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
5348 if (res < 0) {
5349 ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
5350 return -1;
5352 return 0;
5355 static int dahdi_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
5357 struct dahdi_pvt *p = chan->tech_pvt;
5358 int res=-1;
5359 int index;
5360 int func = DAHDI_FLASH;
5361 ast_mutex_lock(&p->lock);
5362 index = dahdi_get_index(chan, p, 0);
5363 if (option_debug)
5364 ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
5365 if (index == SUB_REAL) {
5366 switch (condition) {
5367 case AST_CONTROL_BUSY:
5368 #ifdef HAVE_PRI
5369 if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
5370 chan->hangupcause = AST_CAUSE_USER_BUSY;
5371 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5372 res = 0;
5373 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5374 if (p->pri->pri) {
5375 if (!pri_grab(p, p->pri)) {
5376 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5377 pri_rel(p->pri);
5379 else
5380 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5382 p->progress = 1;
5383 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5384 } else
5385 #endif
5386 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
5387 break;
5388 case AST_CONTROL_RINGING:
5389 #ifdef HAVE_PRI
5390 if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
5391 if (p->pri->pri) {
5392 if (!pri_grab(p, p->pri)) {
5393 pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5394 pri_rel(p->pri);
5396 else
5397 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5399 p->alerting = 1;
5401 #endif
5402 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
5403 if (chan->_state != AST_STATE_UP) {
5404 if ((chan->_state != AST_STATE_RING) ||
5405 ((p->sig != SIG_FXSKS) &&
5406 (p->sig != SIG_FXSLS) &&
5407 (p->sig != SIG_FXSGS)))
5408 ast_setstate(chan, AST_STATE_RINGING);
5410 break;
5411 case AST_CONTROL_PROCEEDING:
5412 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
5413 #ifdef HAVE_PRI
5414 if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5415 if (p->pri->pri) {
5416 if (!pri_grab(p, p->pri)) {
5417 pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
5418 pri_rel(p->pri);
5420 else
5421 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5423 p->proceeding = 1;
5425 #endif
5426 /* don't continue in ast_indicate */
5427 res = 0;
5428 break;
5429 case AST_CONTROL_PROGRESS:
5430 ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
5431 #ifdef HAVE_PRI
5432 p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
5433 if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5434 if (p->pri->pri) {
5435 if (!pri_grab(p, p->pri)) {
5436 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5437 pri_rel(p->pri);
5439 else
5440 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5442 p->progress = 1;
5444 #endif
5445 /* don't continue in ast_indicate */
5446 res = 0;
5447 break;
5448 case AST_CONTROL_CONGESTION:
5449 chan->hangupcause = AST_CAUSE_CONGESTION;
5450 #ifdef HAVE_PRI
5451 if ((p->priindication_oob == 1) && p->sig == SIG_PRI) {
5452 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
5453 chan->_softhangup |= AST_SOFTHANGUP_DEV;
5454 res = 0;
5455 } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
5456 if (p->pri) {
5457 if (!pri_grab(p, p->pri)) {
5458 pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
5459 pri_rel(p->pri);
5460 } else
5461 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5463 p->progress = 1;
5464 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5465 } else
5466 #endif
5467 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
5468 break;
5469 case AST_CONTROL_HOLD:
5470 #ifdef HAVE_PRI
5471 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5472 if (!pri_grab(p, p->pri)) {
5473 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
5474 pri_rel(p->pri);
5475 } else
5476 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5477 } else
5478 #endif
5479 ast_moh_start(chan, data, p->mohinterpret);
5480 break;
5481 case AST_CONTROL_UNHOLD:
5482 #ifdef HAVE_PRI
5483 if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
5484 if (!pri_grab(p, p->pri)) {
5485 res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
5486 pri_rel(p->pri);
5487 } else
5488 ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
5489 } else
5490 #endif
5491 ast_moh_stop(chan);
5492 break;
5493 case AST_CONTROL_RADIO_KEY:
5494 if (p->radio)
5495 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
5496 res = 0;
5497 break;
5498 case AST_CONTROL_RADIO_UNKEY:
5499 if (p->radio)
5500 res = dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
5501 res = 0;
5502 break;
5503 case AST_CONTROL_FLASH:
5504 /* flash hookswitch */
5505 if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
5506 /* Clear out the dial buffer */
5507 p->dop.dialstr[0] = '\0';
5508 if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
5509 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
5510 chan->name, strerror(errno));
5511 } else
5512 res = 0;
5513 } else
5514 res = 0;
5515 break;
5516 case AST_CONTROL_SRCUPDATE:
5517 res = 0;
5518 break;
5519 case -1:
5520 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5521 break;
5523 } else
5524 res = 0;
5525 ast_mutex_unlock(&p->lock);
5526 return res;
5529 static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpbx, int index, int law, int transfercapability)
5531 struct ast_channel *tmp;
5532 int deflaw;
5533 int res;
5534 int x,y;
5535 int features;
5536 char *b2 = NULL;
5537 struct dahdi_params ps;
5538 char chanprefix[*dahdi_chan_name_len + 4];
5540 if (i->subs[index].owner) {
5541 ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
5542 return NULL;
5544 y = 1;
5545 do {
5546 if (b2)
5547 free(b2);
5548 #ifdef HAVE_PRI
5549 if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
5550 b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
5551 else
5552 #endif
5553 if (i->channel == CHAN_PSEUDO)
5554 b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
5555 else
5556 b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
5557 for (x = 0; x < 3; x++) {
5558 if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
5559 break;
5561 y++;
5562 } while (x < 3);
5563 strcpy(chanprefix, dahdi_chan_name);
5564 strcat(chanprefix, "/%s");
5565 tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
5566 if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
5567 free(b2);
5568 if (!tmp)
5569 return NULL;
5570 tmp->tech = chan_tech;
5571 ps.channo = i->channel;
5572 res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
5573 if (res) {
5574 ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
5575 ps.curlaw = DAHDI_LAW_MULAW;
5577 if (ps.curlaw == DAHDI_LAW_ALAW)
5578 deflaw = AST_FORMAT_ALAW;
5579 else
5580 deflaw = AST_FORMAT_ULAW;
5581 if (law) {
5582 if (law == DAHDI_LAW_ALAW)
5583 deflaw = AST_FORMAT_ALAW;
5584 else
5585 deflaw = AST_FORMAT_ULAW;
5587 tmp->fds[0] = i->subs[index].dfd;
5588 tmp->nativeformats = AST_FORMAT_SLINEAR | deflaw;
5589 /* Start out assuming ulaw since it's smaller :) */
5590 tmp->rawreadformat = deflaw;
5591 tmp->readformat = deflaw;
5592 tmp->rawwriteformat = deflaw;
5593 tmp->writeformat = deflaw;
5594 i->subs[index].linear = 0;
5595 dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
5596 features = 0;
5597 if (index == SUB_REAL) {
5598 if (i->busydetect && CANBUSYDETECT(i))
5599 features |= DSP_FEATURE_BUSY_DETECT;
5600 if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
5601 features |= DSP_FEATURE_CALL_PROGRESS;
5602 if ((!i->outgoing && (i->callprogress & 4)) ||
5603 (i->outgoing && (i->callprogress & 2))) {
5604 features |= DSP_FEATURE_FAX_DETECT;
5606 #ifdef DAHDI_TONEDETECT
5607 x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
5608 if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
5609 #endif
5610 i->hardwaredtmf = 0;
5611 features |= DSP_FEATURE_DTMF_DETECT;
5612 #ifdef DAHDI_TONEDETECT
5613 } else if (NEED_MFDETECT(i)) {
5614 i->hardwaredtmf = 1;
5615 features |= DSP_FEATURE_DTMF_DETECT;
5617 #endif
5619 if (features) {
5620 if (i->dsp) {
5621 ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
5622 } else {
5623 if (i->channel != CHAN_PSEUDO)
5624 i->dsp = ast_dsp_new();
5625 else
5626 i->dsp = NULL;
5627 if (i->dsp) {
5628 i->dsp_features = features & ~DSP_PROGRESS_TALK;
5629 #ifdef HAVE_PRI
5630 /* We cannot do progress detection until receives PROGRESS message */
5631 if (i->outgoing && (i->sig == SIG_PRI)) {
5632 /* Remember requested DSP features, don't treat
5633 talking as ANSWER */
5634 features = 0;
5636 #endif
5637 ast_dsp_set_features(i->dsp, features);
5638 ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
5639 if (!ast_strlen_zero(progzone))
5640 ast_dsp_set_call_progress_zone(i->dsp, progzone);
5641 if (i->busydetect && CANBUSYDETECT(i)) {
5642 ast_dsp_set_busy_count(i->dsp, i->busycount);
5643 ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
5649 if (state == AST_STATE_RING)
5650 tmp->rings = 1;
5651 tmp->tech_pvt = i;
5652 #ifdef HAVE_PRI
5653 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS) || (i->sig == SIG_PRI)) {
5654 #else
5655 if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
5656 #endif
5657 /* Only FXO signalled stuff can be picked up */ /* i dont think so, mr. ulaw! we alaws like to pick up BRIs/PRIs */
5658 tmp->callgroup = i->callgroup;
5659 tmp->pickupgroup = i->pickupgroup;
5661 if (!ast_strlen_zero(i->language))
5662 ast_string_field_set(tmp, language, i->language);
5663 if (!i->owner)
5664 i->owner = tmp;
5665 if (!ast_strlen_zero(i->accountcode))
5666 ast_string_field_set(tmp, accountcode, i->accountcode);
5667 if (i->amaflags)
5668 tmp->amaflags = i->amaflags;
5669 i->subs[index].owner = tmp;
5670 ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
5671 ast_string_field_set(tmp, call_forward, i->call_forward);
5672 /* If we've been told "no ADSI" then enforce it */
5673 if (!i->adsi)
5674 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
5675 if (!ast_strlen_zero(i->exten))
5676 ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
5677 if (!ast_strlen_zero(i->rdnis))
5678 tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
5679 if (!ast_strlen_zero(i->dnid))
5680 tmp->cid.cid_dnid = ast_strdup(i->dnid);
5682 /* Don't use ast_set_callerid() here because it will
5683 * generate a needless NewCallerID event */
5684 #ifdef PRI_ANI
5685 if (!ast_strlen_zero(i->cid_ani))
5686 tmp->cid.cid_ani = ast_strdup(i->cid_ani);
5687 else
5688 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5689 #else
5690 tmp->cid.cid_ani = ast_strdup(i->cid_num);
5691 #endif
5692 tmp->cid.cid_pres = i->callingpres;
5693 tmp->cid.cid_ton = i->cid_ton;
5694 #ifdef HAVE_PRI
5695 tmp->transfercapability = transfercapability;
5696 pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
5697 if (transfercapability & PRI_TRANS_CAP_DIGITAL)
5698 i->digital = 1;
5699 /* Assume calls are not idle calls unless we're told differently */
5700 i->isidlecall = 0;
5701 i->alreadyhungup = 0;
5702 #endif
5703 /* clear the fake event in case we posted one before we had ast_channel */
5704 i->fake_event = 0;
5705 /* Assure there is no confmute on this channel */
5706 dahdi_confmute(i, 0);
5707 /* Configure the new channel jb */
5708 ast_jb_configure(tmp, &global_jbconf);
5709 if (startpbx) {
5710 if (ast_pbx_start(tmp)) {
5711 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
5712 ast_hangup(tmp);
5713 i->owner = NULL;
5714 return NULL;
5718 ast_module_ref(ast_module_info->self);
5720 return tmp;
5724 static int my_getsigstr(struct ast_channel *chan, char *str, const char *term, int ms)
5726 char c;
5728 *str = 0; /* start with empty output buffer */
5729 for (;;)
5731 /* Wait for the first digit (up to specified ms). */
5732 c = ast_waitfordigit(chan, ms);
5733 /* if timeout, hangup or error, return as such */
5734 if (c < 1)
5735 return c;
5736 *str++ = c;
5737 *str = 0;
5738 if (strchr(term, c))
5739 return 1;
5743 static int dahdi_wink(struct dahdi_pvt *p, int index)
5745 int j;
5746 dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
5747 for (;;)
5749 /* set bits of interest */
5750 j = DAHDI_IOMUX_SIGEVENT;
5751 /* wait for some happening */
5752 if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
5753 /* exit loop if we have it */
5754 if (j & DAHDI_IOMUX_SIGEVENT) break;
5756 /* get the event info */
5757 if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
5758 return 0;
5761 static void *ss_thread(void *data)
5763 struct ast_channel *chan = data;
5764 struct dahdi_pvt *p = chan->tech_pvt;
5765 char exten[AST_MAX_EXTENSION] = "";
5766 char exten2[AST_MAX_EXTENSION] = "";
5767 unsigned char buf[256];
5768 char dtmfcid[300];
5769 char dtmfbuf[300];
5770 struct callerid_state *cs = NULL;
5771 char *name = NULL, *number = NULL;
5772 int distMatches;
5773 int curRingData[3];
5774 int receivedRingT;
5775 int counter1;
5776 int counter;
5777 int samples = 0;
5778 struct ast_smdi_md_message *smdi_msg = NULL;
5779 int flags;
5780 int i;
5781 int timeout;
5782 int getforward = 0;
5783 char *s1, *s2;
5784 int len = 0;
5785 int res;
5786 int index;
5787 int network;
5789 ast_mutex_lock(&ss_thread_lock);
5790 ss_thread_count++;
5791 ast_mutex_unlock(&ss_thread_lock);
5792 /* in the bizarre case where the channel has become a zombie before we
5793 even get started here, abort safely
5795 if (!p) {
5796 ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
5797 ast_hangup(chan);
5798 goto quit;
5800 if (option_verbose > 2)
5801 ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
5802 index = dahdi_get_index(chan, p, 1);
5803 if (index < 0) {
5804 ast_log(LOG_WARNING, "Huh?\n");
5805 ast_hangup(chan);
5806 goto quit;
5808 if (p->dsp)
5809 ast_dsp_digitreset(p->dsp);
5810 switch (p->sig) {
5811 #ifdef HAVE_PRI
5812 case SIG_PRI:
5813 /* Now loop looking for an extension */
5814 ast_copy_string(exten, p->exten, sizeof(exten));
5815 len = strlen(exten);
5816 res = 0;
5817 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
5818 if (len && !ast_ignore_pattern(chan->context, exten)) {
5819 tone_zone_play_tone(p->subs[index].dfd, -1);
5820 } else {
5821 network = p->pri->nodetype == PRI_NETWORK || p->pri->nodetype == BRI_NETWORK || p->pri->nodetype == BRI_NETWORK_PTMP;
5822 if (network) {
5823 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
5824 } else {
5825 /* cpe be quiet */
5826 tone_zone_play_tone(p->subs[index].dfd, -1);
5829 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
5830 timeout = matchdigittimeout;
5831 else
5832 timeout = gendigittimeout;
5833 res = ast_waitfordigit(chan, timeout);
5834 if (res < 0) {
5835 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5836 ast_hangup(chan);
5837 goto quit;
5838 } else if (res) {
5839 exten[len++] = res;
5840 exten[len] = '\0';
5841 } else
5842 break;
5844 /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
5845 if (ast_strlen_zero(exten)) {
5846 if (option_verbose > 2)
5847 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
5848 exten[0] = 's';
5849 exten[1] = '\0';
5851 tone_zone_play_tone(p->subs[index].dfd, -1);
5852 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
5853 /* Start the real PBX */
5854 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
5855 if (p->dsp) ast_dsp_digitreset(p->dsp);
5856 dahdi_enable_ec(p);
5857 ast_setstate(chan, AST_STATE_RING);
5858 res = ast_pbx_run(chan);
5859 if (res) {
5860 ast_log(LOG_WARNING, "PBX exited non-zero!\n");
5862 } else {
5863 ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
5864 chan->hangupcause = AST_CAUSE_UNALLOCATED;
5865 ast_hangup(chan);
5866 p->exten[0] = '\0';
5867 /* Since we send release complete here, we won't get one */
5868 p->call = NULL;
5870 goto quit;
5871 break;
5872 #endif
5873 case SIG_FEATD:
5874 case SIG_FEATDMF:
5875 case SIG_FEATDMF_TA:
5876 case SIG_E911:
5877 case SIG_FGC_CAMAMF:
5878 case SIG_FEATB:
5879 case SIG_EMWINK:
5880 case SIG_SF_FEATD:
5881 case SIG_SF_FEATDMF:
5882 case SIG_SF_FEATB:
5883 case SIG_SFWINK:
5884 if (dahdi_wink(p, index))
5885 goto quit;
5886 /* Fall through */
5887 case SIG_EM:
5888 case SIG_EM_E1:
5889 case SIG_SF:
5890 case SIG_FGC_CAMA:
5891 res = tone_zone_play_tone(p->subs[index].dfd, -1);
5892 if (p->dsp)
5893 ast_dsp_digitreset(p->dsp);
5894 /* set digit mode appropriately */
5895 if (p->dsp) {
5896 if (NEED_MFDETECT(p))
5897 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
5898 else
5899 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
5901 memset(dtmfbuf, 0, sizeof(dtmfbuf));
5902 /* Wait for the first digit only if immediate=no */
5903 if (!p->immediate)
5904 /* Wait for the first digit (up to 5 seconds). */
5905 res = ast_waitfordigit(chan, 5000);
5906 else
5907 res = 0;
5908 if (res > 0) {
5909 /* save first char */
5910 dtmfbuf[0] = res;
5911 switch (p->sig) {
5912 case SIG_FEATD:
5913 case SIG_SF_FEATD:
5914 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5915 if (res > 0)
5916 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5917 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5918 break;
5919 case SIG_FEATDMF_TA:
5920 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5921 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5922 if (dahdi_wink(p, index)) goto quit;
5923 dtmfbuf[0] = 0;
5924 /* Wait for the first digit (up to 5 seconds). */
5925 res = ast_waitfordigit(chan, 5000);
5926 if (res <= 0) break;
5927 dtmfbuf[0] = res;
5928 /* fall through intentionally */
5929 case SIG_FEATDMF:
5930 case SIG_E911:
5931 case SIG_FGC_CAMAMF:
5932 case SIG_SF_FEATDMF:
5933 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5934 /* if international caca, do it again to get real ANO */
5935 if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
5937 if (dahdi_wink(p, index)) goto quit;
5938 dtmfbuf[0] = 0;
5939 /* Wait for the first digit (up to 5 seconds). */
5940 res = ast_waitfordigit(chan, 5000);
5941 if (res <= 0) break;
5942 dtmfbuf[0] = res;
5943 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5945 if (res > 0) {
5946 /* if E911, take off hook */
5947 if (p->sig == SIG_E911)
5948 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
5949 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
5951 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5952 break;
5953 case SIG_FEATB:
5954 case SIG_SF_FEATB:
5955 res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
5956 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5957 break;
5958 case SIG_EMWINK:
5959 /* if we received a '*', we are actually receiving Feature Group D
5960 dial syntax, so use that mode; otherwise, fall through to normal
5961 mode
5963 if (res == '*') {
5964 res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
5965 if (res > 0)
5966 res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
5967 if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
5968 break;
5970 default:
5971 /* If we got the first digit, get the rest */
5972 len = 1;
5973 dtmfbuf[len] = '\0';
5974 while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5975 if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
5976 timeout = matchdigittimeout;
5977 } else {
5978 timeout = gendigittimeout;
5980 res = ast_waitfordigit(chan, timeout);
5981 if (res < 0) {
5982 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
5983 ast_hangup(chan);
5984 goto quit;
5985 } else if (res) {
5986 dtmfbuf[len++] = res;
5987 dtmfbuf[len] = '\0';
5988 } else {
5989 break;
5992 break;
5995 if (res == -1) {
5996 ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
5997 ast_hangup(chan);
5998 goto quit;
5999 } else if (res < 0) {
6000 ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
6001 ast_hangup(chan);
6002 goto quit;
6005 if (p->sig == SIG_FGC_CAMA) {
6006 char anibuf[100];
6008 if (ast_safe_sleep(chan,1000) == -1) {
6009 ast_hangup(chan);
6010 goto quit;
6012 dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6013 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
6014 res = my_getsigstr(chan, anibuf, "#", 10000);
6015 if ((res > 0) && (strlen(anibuf) > 2)) {
6016 if (anibuf[strlen(anibuf) - 1] == '#')
6017 anibuf[strlen(anibuf) - 1] = 0;
6018 ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
6020 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
6023 ast_copy_string(exten, dtmfbuf, sizeof(exten));
6024 if (ast_strlen_zero(exten))
6025 ast_copy_string(exten, "s", sizeof(exten));
6026 if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
6027 /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
6028 if (exten[0] == '*') {
6029 char *stringp=NULL;
6030 ast_copy_string(exten2, exten, sizeof(exten2));
6031 /* Parse out extension and callerid */
6032 stringp=exten2 +1;
6033 s1 = strsep(&stringp, "*");
6034 s2 = strsep(&stringp, "*");
6035 if (s2) {
6036 if (!ast_strlen_zero(p->cid_num))
6037 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6038 else
6039 ast_set_callerid(chan, s1, NULL, s1);
6040 ast_copy_string(exten, s2, sizeof(exten));
6041 } else
6042 ast_copy_string(exten, s1, sizeof(exten));
6043 } else if (p->sig == SIG_FEATD)
6044 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
6046 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
6047 if (exten[0] == '*') {
6048 char *stringp=NULL;
6049 ast_copy_string(exten2, exten, sizeof(exten2));
6050 /* Parse out extension and callerid */
6051 stringp=exten2 +1;
6052 s1 = strsep(&stringp, "#");
6053 s2 = strsep(&stringp, "#");
6054 if (s2) {
6055 if (!ast_strlen_zero(p->cid_num))
6056 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6057 else
6058 if (*(s1 + 2))
6059 ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
6060 ast_copy_string(exten, s2 + 1, sizeof(exten));
6061 } else
6062 ast_copy_string(exten, s1 + 2, sizeof(exten));
6063 } else
6064 ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d. Assuming E&M Wink instead\n", p->channel);
6066 if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
6067 if (exten[0] == '*') {
6068 char *stringp=NULL;
6069 ast_copy_string(exten2, exten, sizeof(exten2));
6070 /* Parse out extension and callerid */
6071 stringp=exten2 +1;
6072 s1 = strsep(&stringp, "#");
6073 s2 = strsep(&stringp, "#");
6074 if (s2 && (*(s2 + 1) == '0')) {
6075 if (*(s2 + 2))
6076 ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
6078 if (s1) ast_copy_string(exten, s1, sizeof(exten));
6079 else ast_copy_string(exten, "911", sizeof(exten));
6080 } else
6081 ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d. Assuming E&M Wink instead\n", p->channel);
6083 if (p->sig == SIG_FEATB) {
6084 if (exten[0] == '*') {
6085 char *stringp=NULL;
6086 ast_copy_string(exten2, exten, sizeof(exten2));
6087 /* Parse out extension and callerid */
6088 stringp=exten2 +1;
6089 s1 = strsep(&stringp, "#");
6090 ast_copy_string(exten, exten2 + 1, sizeof(exten));
6091 } else
6092 ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d. Assuming E&M Wink instead\n", p->channel);
6094 if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
6095 dahdi_wink(p, index);
6096 /* some switches require a minimum guard time between
6097 the last FGD wink and something that answers
6098 immediately. This ensures it */
6099 if (ast_safe_sleep(chan,100)) goto quit;
6101 dahdi_enable_ec(p);
6102 if (NEED_MFDETECT(p)) {
6103 if (p->dsp) {
6104 if (!p->hardwaredtmf)
6105 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
6106 else {
6107 ast_dsp_free(p->dsp);
6108 p->dsp = NULL;
6113 if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
6114 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6115 if (p->dsp) ast_dsp_digitreset(p->dsp);
6116 res = ast_pbx_run(chan);
6117 if (res) {
6118 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6119 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6121 goto quit;
6122 } else {
6123 if (option_verbose > 2)
6124 ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
6125 sleep(2);
6126 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
6127 if (res < 0)
6128 ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
6129 else
6130 sleep(1);
6131 res = ast_streamfile(chan, "ss-noservice", chan->language);
6132 if (res >= 0)
6133 ast_waitstream(chan, "");
6134 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6135 ast_hangup(chan);
6136 goto quit;
6138 break;
6139 case SIG_FXOLS:
6140 case SIG_FXOGS:
6141 case SIG_FXOKS:
6142 /* Read the first digit */
6143 timeout = firstdigittimeout;
6144 /* If starting a threeway call, never timeout on the first digit so someone
6145 can use flash-hook as a "hold" feature */
6146 if (p->subs[SUB_THREEWAY].owner)
6147 timeout = 999999;
6148 while (len < AST_MAX_EXTENSION-1) {
6149 /* Read digit unless it's supposed to be immediate, in which case the
6150 only answer is 's' */
6151 if (p->immediate)
6152 res = 's';
6153 else
6154 res = ast_waitfordigit(chan, timeout);
6155 timeout = 0;
6156 if (res < 0) {
6157 ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
6158 res = tone_zone_play_tone(p->subs[index].dfd, -1);
6159 ast_hangup(chan);
6160 goto quit;
6161 } else if (res) {
6162 exten[len++]=res;
6163 exten[len] = '\0';
6165 if (!ast_ignore_pattern(chan->context, exten))
6166 tone_zone_play_tone(p->subs[index].dfd, -1);
6167 else
6168 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
6169 if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
6170 if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
6171 if (getforward) {
6172 /* Record this as the forwarding extension */
6173 ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
6174 if (option_verbose > 2)
6175 ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
6176 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6177 if (res)
6178 break;
6179 usleep(500000);
6180 res = tone_zone_play_tone(p->subs[index].dfd, -1);
6181 sleep(1);
6182 memset(exten, 0, sizeof(exten));
6183 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
6184 len = 0;
6185 getforward = 0;
6186 } else {
6187 res = tone_zone_play_tone(p->subs[index].dfd, -1);
6188 ast_copy_string(chan->exten, exten, sizeof(chan->exten));
6189 if (!ast_strlen_zero(p->cid_num)) {
6190 if (!p->hidecallerid)
6191 ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
6192 else
6193 ast_set_callerid(chan, NULL, NULL, p->cid_num);
6195 if (!ast_strlen_zero(p->cid_name)) {
6196 if (!p->hidecallerid)
6197 ast_set_callerid(chan, NULL, p->cid_name, NULL);
6199 ast_setstate(chan, AST_STATE_RING);
6200 dahdi_enable_ec(p);
6201 res = ast_pbx_run(chan);
6202 if (res) {
6203 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6204 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6206 goto quit;
6208 } else {
6209 /* It's a match, but they just typed a digit, and there is an ambiguous match,
6210 so just set the timeout to matchdigittimeout and wait some more */
6211 timeout = matchdigittimeout;
6213 } else if (res == 0) {
6214 ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
6215 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6216 dahdi_wait_event(p->subs[index].dfd);
6217 ast_hangup(chan);
6218 goto quit;
6219 } else if (p->callwaiting && !strcmp(exten, "*70")) {
6220 if (option_verbose > 2)
6221 ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
6222 /* Disable call waiting if enabled */
6223 p->callwaiting = 0;
6224 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6225 if (res) {
6226 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6227 chan->name, strerror(errno));
6229 len = 0;
6230 ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
6231 memset(exten, 0, sizeof(exten));
6232 timeout = firstdigittimeout;
6234 } else if (!strcmp(exten,ast_pickup_ext())) {
6235 /* Scan all channels and see if there are any
6236 * ringing channels that have call groups
6237 * that equal this channels pickup group
6239 if (index == SUB_REAL) {
6240 /* Switch us from Third call to Call Wait */
6241 if (p->subs[SUB_THREEWAY].owner) {
6242 /* If you make a threeway call and the *8# a call, it should actually
6243 look like a callwait */
6244 alloc_sub(p, SUB_CALLWAIT);
6245 swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
6246 unalloc_sub(p, SUB_THREEWAY);
6248 dahdi_enable_ec(p);
6249 if (ast_pickup_call(chan)) {
6250 ast_log(LOG_DEBUG, "No call pickup possible...\n");
6251 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6252 dahdi_wait_event(p->subs[index].dfd);
6254 ast_hangup(chan);
6255 goto quit;
6256 } else {
6257 ast_log(LOG_WARNING, "Huh? Got *8# on call not on real\n");
6258 ast_hangup(chan);
6259 goto quit;
6262 } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
6263 if (option_verbose > 2)
6264 ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
6265 /* Disable Caller*ID if enabled */
6266 p->hidecallerid = 1;
6267 if (chan->cid.cid_num)
6268 free(chan->cid.cid_num);
6269 chan->cid.cid_num = NULL;
6270 if (chan->cid.cid_name)
6271 free(chan->cid.cid_name);
6272 chan->cid.cid_name = NULL;
6273 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6274 if (res) {
6275 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6276 chan->name, strerror(errno));
6278 len = 0;
6279 memset(exten, 0, sizeof(exten));
6280 timeout = firstdigittimeout;
6281 } else if (p->callreturn && !strcmp(exten, "*69")) {
6282 res = 0;
6283 if (!ast_strlen_zero(p->lastcid_num)) {
6284 res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
6286 if (!res)
6287 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6288 break;
6289 } else if (!strcmp(exten, "*78")) {
6290 /* Do not disturb */
6291 if (option_verbose > 2)
6292 ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
6293 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6294 "Channel: %s/%d\r\n"
6295 "Status: enabled\r\n", dahdi_chan_name, p->channel);
6296 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6297 p->dnd = 1;
6298 getforward = 0;
6299 memset(exten, 0, sizeof(exten));
6300 len = 0;
6301 } else if (!strcmp(exten, "*79")) {
6302 /* Do not disturb */
6303 if (option_verbose > 2)
6304 ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
6305 manager_event(EVENT_FLAG_SYSTEM, "DNDState",
6306 "Channel: %s/%d\r\n"
6307 "Status: disabled\r\n", dahdi_chan_name, p->channel);
6308 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6309 p->dnd = 0;
6310 getforward = 0;
6311 memset(exten, 0, sizeof(exten));
6312 len = 0;
6313 } else if (p->cancallforward && !strcmp(exten, "*72")) {
6314 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6315 getforward = 1;
6316 memset(exten, 0, sizeof(exten));
6317 len = 0;
6318 } else if (p->cancallforward && !strcmp(exten, "*73")) {
6319 if (option_verbose > 2)
6320 ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
6321 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6322 memset(p->call_forward, 0, sizeof(p->call_forward));
6323 getforward = 0;
6324 memset(exten, 0, sizeof(exten));
6325 len = 0;
6326 } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
6327 p->subs[SUB_THREEWAY].owner &&
6328 ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
6329 /* This is a three way call, the main call being a real channel,
6330 and we're parking the first call. */
6331 ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
6332 if (option_verbose > 2)
6333 ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
6334 break;
6335 } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
6336 if (option_verbose > 2)
6337 ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
6338 res = ast_db_put("blacklist", p->lastcid_num, "1");
6339 if (!res) {
6340 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6341 memset(exten, 0, sizeof(exten));
6342 len = 0;
6344 } else if (p->hidecallerid && !strcmp(exten, "*82")) {
6345 if (option_verbose > 2)
6346 ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
6347 /* Enable Caller*ID if enabled */
6348 p->hidecallerid = 0;
6349 if (chan->cid.cid_num)
6350 free(chan->cid.cid_num);
6351 chan->cid.cid_num = NULL;
6352 if (chan->cid.cid_name)
6353 free(chan->cid.cid_name);
6354 chan->cid.cid_name = NULL;
6355 ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
6356 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
6357 if (res) {
6358 ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
6359 chan->name, strerror(errno));
6361 len = 0;
6362 memset(exten, 0, sizeof(exten));
6363 timeout = firstdigittimeout;
6364 } else if (!strcmp(exten, "*0")) {
6365 struct ast_channel *nbridge =
6366 p->subs[SUB_THREEWAY].owner;
6367 struct dahdi_pvt *pbridge = NULL;
6368 /* set up the private struct of the bridged one, if any */
6369 if (nbridge && ast_bridged_channel(nbridge))
6370 pbridge = ast_bridged_channel(nbridge)->tech_pvt;
6371 if (nbridge && pbridge &&
6372 (nbridge->tech == chan_tech) &&
6373 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
6374 ISTRUNK(pbridge)) {
6375 int func = DAHDI_FLASH;
6376 /* Clear out the dial buffer */
6377 p->dop.dialstr[0] = '\0';
6378 /* flash hookswitch */
6379 if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
6380 ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
6381 nbridge->name, strerror(errno));
6383 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6384 unalloc_sub(p, SUB_THREEWAY);
6385 p->owner = p->subs[SUB_REAL].owner;
6386 if (ast_bridged_channel(p->subs[SUB_REAL].owner))
6387 ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
6388 ast_hangup(chan);
6389 goto quit;
6390 } else {
6391 tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6392 dahdi_wait_event(p->subs[index].dfd);
6393 tone_zone_play_tone(p->subs[index].dfd, -1);
6394 swap_subs(p, SUB_REAL, SUB_THREEWAY);
6395 unalloc_sub(p, SUB_THREEWAY);
6396 p->owner = p->subs[SUB_REAL].owner;
6397 ast_hangup(chan);
6398 goto quit;
6400 } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
6401 ((exten[0] != '*') || (strlen(exten) > 2))) {
6402 if (option_debug)
6403 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);
6404 break;
6406 if (!timeout)
6407 timeout = gendigittimeout;
6408 if (len && !ast_ignore_pattern(chan->context, exten))
6409 tone_zone_play_tone(p->subs[index].dfd, -1);
6411 break;
6412 case SIG_FXSLS:
6413 case SIG_FXSGS:
6414 case SIG_FXSKS:
6415 #ifdef HAVE_PRI
6416 if (p->pri) {
6417 /* This is a GR-303 trunk actually. Wait for the first ring... */
6418 struct ast_frame *f;
6419 int res;
6420 time_t start;
6422 time(&start);
6423 ast_setstate(chan, AST_STATE_RING);
6424 while (time(NULL) < start + 3) {
6425 res = ast_waitfor(chan, 1000);
6426 if (res) {
6427 f = ast_read(chan);
6428 if (!f) {
6429 ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
6430 ast_hangup(chan);
6431 goto quit;
6432 } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
6433 res = 1;
6434 } else
6435 res = 0;
6436 ast_frfree(f);
6437 if (res) {
6438 ast_log(LOG_DEBUG, "Got ring!\n");
6439 res = 0;
6440 break;
6445 #endif
6446 /* check for SMDI messages */
6447 if (p->use_smdi && p->smdi_iface) {
6448 smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
6450 if (smdi_msg != NULL) {
6451 ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
6453 if (smdi_msg->type == 'B')
6454 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
6455 else if (smdi_msg->type == 'N')
6456 pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
6458 ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
6459 } else {
6460 ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
6464 if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
6465 number = smdi_msg->calling_st;
6467 /* If we want caller id, we're in a prering state due to a polarity reversal
6468 * and we're set to use a polarity reversal to trigger the start of caller id,
6469 * grab the caller id and wait for ringing to start... */
6470 } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
6471 /* If set to use DTMF CID signalling, listen for DTMF */
6472 if (p->cid_signalling == CID_SIG_DTMF) {
6473 int i = 0;
6474 cs = NULL;
6475 ast_log(LOG_DEBUG, "Receiving DTMF cid on "
6476 "channel %s\n", chan->name);
6477 dahdi_setlinear(p->subs[index].dfd, 0);
6478 res = 2000;
6479 for (;;) {
6480 struct ast_frame *f;
6481 res = ast_waitfor(chan, res);
6482 if (res <= 0) {
6483 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
6484 "Exiting simple switch\n");
6485 ast_hangup(chan);
6486 goto quit;
6488 f = ast_read(chan);
6489 if (!f)
6490 break;
6491 if (f->frametype == AST_FRAME_DTMF) {
6492 dtmfbuf[i++] = f->subclass;
6493 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
6494 res = 2000;
6496 ast_frfree(f);
6497 if (chan->_state == AST_STATE_RING ||
6498 chan->_state == AST_STATE_RINGING)
6499 break; /* Got ring */
6501 dtmfbuf[i] = '\0';
6502 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6503 /* Got cid and ring. */
6504 ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
6505 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
6506 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
6507 dtmfcid, flags);
6508 /* If first byte is NULL, we have no cid */
6509 if (!ast_strlen_zero(dtmfcid))
6510 number = dtmfcid;
6511 else
6512 number = NULL;
6513 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
6514 } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
6515 cs = callerid_new(p->cid_signalling);
6516 if (cs) {
6517 samples = 0;
6518 #if 1
6519 bump_gains(p);
6520 #endif
6521 /* Take out of linear mode for Caller*ID processing */
6522 dahdi_setlinear(p->subs[index].dfd, 0);
6524 /* First we wait and listen for the Caller*ID */
6525 for (;;) {
6526 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6527 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6528 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6529 callerid_free(cs);
6530 ast_hangup(chan);
6531 goto quit;
6533 if (i & DAHDI_IOMUX_SIGEVENT) {
6534 res = dahdi_get_event(p->subs[index].dfd);
6535 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6537 if (p->cid_signalling == CID_SIG_V23_JP) {
6538 #ifdef DAHDI_EVENT_RINGBEGIN
6539 if (res == DAHDI_EVENT_RINGBEGIN) {
6540 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6541 usleep(1);
6543 #endif
6544 } else {
6545 res = 0;
6546 break;
6548 } else if (i & DAHDI_IOMUX_READ) {
6549 res = read(p->subs[index].dfd, buf, sizeof(buf));
6550 if (res < 0) {
6551 if (errno != ELAST) {
6552 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6553 callerid_free(cs);
6554 ast_hangup(chan);
6555 goto quit;
6557 break;
6559 samples += res;
6561 if (p->cid_signalling == CID_SIG_V23_JP) {
6562 res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
6563 } else {
6564 res = callerid_feed(cs, buf, res, AST_LAW(p));
6567 if (res < 0) {
6568 ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
6569 break;
6570 } else if (res)
6571 break;
6572 else if (samples > (8000 * 10))
6573 break;
6576 if (res == 1) {
6577 callerid_get(cs, &name, &number, &flags);
6578 ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6581 if (p->cid_signalling == CID_SIG_V23_JP) {
6582 res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
6583 usleep(1);
6584 res = 4000;
6585 } else {
6587 /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
6588 res = 2000;
6591 for (;;) {
6592 struct ast_frame *f;
6593 res = ast_waitfor(chan, res);
6594 if (res <= 0) {
6595 ast_log(LOG_WARNING, "CID timed out waiting for ring. "
6596 "Exiting simple switch\n");
6597 ast_hangup(chan);
6598 goto quit;
6600 if (!(f = ast_read(chan))) {
6601 ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
6602 ast_hangup(chan);
6603 goto quit;
6605 ast_frfree(f);
6606 if (chan->_state == AST_STATE_RING ||
6607 chan->_state == AST_STATE_RINGING)
6608 break; /* Got ring */
6611 /* We must have a ring by now, so, if configured, lets try to listen for
6612 * distinctive ringing */
6613 if (p->usedistinctiveringdetection == 1) {
6614 len = 0;
6615 distMatches = 0;
6616 /* Clear the current ring data array so we dont have old data in it. */
6617 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6618 curRingData[receivedRingT] = 0;
6619 receivedRingT = 0;
6620 counter = 0;
6621 counter1 = 0;
6622 /* Check to see if context is what it should be, if not set to be. */
6623 if (strcmp(p->context,p->defcontext) != 0) {
6624 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6625 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6628 for (;;) {
6629 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6630 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6631 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6632 callerid_free(cs);
6633 ast_hangup(chan);
6634 goto quit;
6636 if (i & DAHDI_IOMUX_SIGEVENT) {
6637 res = dahdi_get_event(p->subs[index].dfd);
6638 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6639 res = 0;
6640 /* Let us detect distinctive ring */
6642 curRingData[receivedRingT] = p->ringt;
6644 if (p->ringt < p->ringt_base/2)
6645 break;
6646 /* Increment the ringT counter so we can match it against
6647 values in chan_dahdi.conf for distinctive ring */
6648 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6649 break;
6650 } else if (i & DAHDI_IOMUX_READ) {
6651 res = read(p->subs[index].dfd, buf, sizeof(buf));
6652 if (res < 0) {
6653 if (errno != ELAST) {
6654 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6655 callerid_free(cs);
6656 ast_hangup(chan);
6657 goto quit;
6659 break;
6661 if (p->ringt)
6662 p->ringt--;
6663 if (p->ringt == 1) {
6664 res = -1;
6665 break;
6669 if (option_verbose > 2)
6670 /* this only shows up if you have n of the dring patterns filled in */
6671 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6673 for (counter = 0; counter < 3; counter++) {
6674 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6675 channel */
6676 distMatches = 0;
6677 for (counter1 = 0; counter1 < 3; counter1++) {
6678 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6679 (p->drings.ringnum[counter].ring[counter1]-10)) {
6680 distMatches++;
6683 if (distMatches == 3) {
6684 /* The ring matches, set the context to whatever is for distinctive ring.. */
6685 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6686 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6687 if (option_verbose > 2)
6688 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6689 break;
6693 /* Restore linear mode (if appropriate) for Caller*ID processing */
6694 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6695 #if 1
6696 restore_gains(p);
6697 #endif
6698 } else
6699 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6700 } else {
6701 ast_log(LOG_WARNING, "Channel %s in prering "
6702 "state, but I have nothing to do. "
6703 "Terminating simple switch, should be "
6704 "restarted by the actual ring.\n",
6705 chan->name);
6706 ast_hangup(chan);
6707 goto quit;
6709 } else if (p->use_callerid && p->cid_start == CID_START_RING) {
6710 /* FSK Bell202 callerID */
6711 cs = callerid_new(p->cid_signalling);
6712 if (cs) {
6713 #if 1
6714 bump_gains(p);
6715 #endif
6716 samples = 0;
6717 len = 0;
6718 distMatches = 0;
6719 /* Clear the current ring data array so we dont have old data in it. */
6720 for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
6721 curRingData[receivedRingT] = 0;
6722 receivedRingT = 0;
6723 counter = 0;
6724 counter1 = 0;
6725 /* Check to see if context is what it should be, if not set to be. */
6726 if (strcmp(p->context,p->defcontext) != 0) {
6727 ast_copy_string(p->context, p->defcontext, sizeof(p->context));
6728 ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
6731 /* Take out of linear mode for Caller*ID processing */
6732 dahdi_setlinear(p->subs[index].dfd, 0);
6733 for (;;) {
6734 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6735 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6736 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6737 callerid_free(cs);
6738 ast_hangup(chan);
6739 goto quit;
6741 if (i & DAHDI_IOMUX_SIGEVENT) {
6742 res = dahdi_get_event(p->subs[index].dfd);
6743 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6744 /* If we get a PR event, they hung up while processing calerid */
6745 if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
6746 ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
6747 p->polarity = POLARITY_IDLE;
6748 callerid_free(cs);
6749 ast_hangup(chan);
6750 goto quit;
6752 res = 0;
6753 /* Let us detect callerid when the telco uses distinctive ring */
6755 curRingData[receivedRingT] = p->ringt;
6757 if (p->ringt < p->ringt_base/2)
6758 break;
6759 /* Increment the ringT counter so we can match it against
6760 values in chan_dahdi.conf for distinctive ring */
6761 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6762 break;
6763 } else if (i & DAHDI_IOMUX_READ) {
6764 res = read(p->subs[index].dfd, buf, sizeof(buf));
6765 if (res < 0) {
6766 if (errno != ELAST) {
6767 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6768 callerid_free(cs);
6769 ast_hangup(chan);
6770 goto quit;
6772 break;
6774 if (p->ringt)
6775 p->ringt--;
6776 if (p->ringt == 1) {
6777 res = -1;
6778 break;
6780 samples += res;
6781 res = callerid_feed(cs, buf, res, AST_LAW(p));
6782 if (res < 0) {
6783 ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
6784 break;
6785 } else if (res)
6786 break;
6787 else if (samples > (8000 * 10))
6788 break;
6791 if (res == 1) {
6792 callerid_get(cs, &name, &number, &flags);
6793 if (option_debug)
6794 ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
6796 if (distinctiveringaftercid == 1) {
6797 /* Clear the current ring data array so we dont have old data in it. */
6798 for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
6799 curRingData[receivedRingT] = 0;
6801 receivedRingT = 0;
6802 if (option_verbose > 2)
6803 ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
6804 for (;;) {
6805 i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
6806 if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i))) {
6807 ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
6808 callerid_free(cs);
6809 ast_hangup(chan);
6810 goto quit;
6812 if (i & DAHDI_IOMUX_SIGEVENT) {
6813 res = dahdi_get_event(p->subs[index].dfd);
6814 ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
6815 res = 0;
6816 /* Let us detect callerid when the telco uses distinctive ring */
6818 curRingData[receivedRingT] = p->ringt;
6820 if (p->ringt < p->ringt_base/2)
6821 break;
6822 /* Increment the ringT counter so we can match it against
6823 values in chan_dahdi.conf for distinctive ring */
6824 if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
6825 break;
6826 } else if (i & DAHDI_IOMUX_READ) {
6827 res = read(p->subs[index].dfd, buf, sizeof(buf));
6828 if (res < 0) {
6829 if (errno != ELAST) {
6830 ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
6831 callerid_free(cs);
6832 ast_hangup(chan);
6833 goto quit;
6835 break;
6837 if (p->ringt)
6838 p->ringt--;
6839 if (p->ringt == 1) {
6840 res = -1;
6841 break;
6846 if (p->usedistinctiveringdetection == 1) {
6847 if (option_verbose > 2)
6848 /* this only shows up if you have n of the dring patterns filled in */
6849 ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
6851 for (counter = 0; counter < 3; counter++) {
6852 /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
6853 channel */
6854 if (option_verbose > 2)
6855 /* this only shows up if you have n of the dring patterns filled in */
6856 ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
6857 p->drings.ringnum[counter].ring[0],
6858 p->drings.ringnum[counter].ring[1],
6859 p->drings.ringnum[counter].ring[2]);
6860 distMatches = 0;
6861 for (counter1 = 0; counter1 < 3; counter1++) {
6862 if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
6863 (p->drings.ringnum[counter].ring[counter1]-10)) {
6864 distMatches++;
6867 if (distMatches == 3) {
6868 /* The ring matches, set the context to whatever is for distinctive ring.. */
6869 ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
6870 ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
6871 if (option_verbose > 2)
6872 ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
6873 break;
6877 /* Restore linear mode (if appropriate) for Caller*ID processing */
6878 dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
6879 #if 1
6880 restore_gains(p);
6881 #endif
6882 if (res < 0) {
6883 ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
6885 } else
6886 ast_log(LOG_WARNING, "Unable to get caller ID space\n");
6888 else
6889 cs = NULL;
6891 if (number)
6892 ast_shrink_phone_number(number);
6893 ast_set_callerid(chan, number, name, number);
6895 if (smdi_msg)
6896 ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
6898 if (cs)
6899 callerid_free(cs);
6901 ast_setstate(chan, AST_STATE_RING);
6902 chan->rings = 1;
6903 p->ringt = p->ringt_base;
6904 res = ast_pbx_run(chan);
6905 if (res) {
6906 ast_hangup(chan);
6907 ast_log(LOG_WARNING, "PBX exited non-zero\n");
6909 goto quit;
6910 default:
6911 ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
6912 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6913 if (res < 0)
6914 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6916 res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
6917 if (res < 0)
6918 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
6919 ast_hangup(chan);
6920 quit:
6921 ast_mutex_lock(&ss_thread_lock);
6922 ss_thread_count--;
6923 ast_cond_signal(&ss_thread_complete);
6924 ast_mutex_unlock(&ss_thread_lock);
6925 return NULL;
6928 /* destroy a DAHDI channel, identified by its number */
6929 static int dahdi_destroy_channel_bynum(int channel)
6931 struct dahdi_pvt *tmp = NULL;
6932 struct dahdi_pvt *prev = NULL;
6934 tmp = iflist;
6935 while (tmp) {
6936 if (tmp->channel == channel) {
6937 int x = DAHDI_FLASH;
6938 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 */
6939 destroy_channel(prev, tmp, 1);
6940 ast_module_unref(ast_module_info->self);
6941 return RESULT_SUCCESS;
6943 prev = tmp;
6944 tmp = tmp->next;
6946 return RESULT_FAILURE;
6949 static int handle_init_event(struct dahdi_pvt *i, int event)
6951 int res;
6952 pthread_t threadid;
6953 pthread_attr_t attr;
6954 struct ast_channel *chan;
6955 pthread_attr_init(&attr);
6956 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
6957 /* Handle an event on a given channel for the monitor thread. */
6958 switch (event) {
6959 case DAHDI_EVENT_NONE:
6960 case DAHDI_EVENT_BITSCHANGED:
6961 break;
6962 case DAHDI_EVENT_WINKFLASH:
6963 case DAHDI_EVENT_RINGOFFHOOK:
6964 if (i->inalarm) break;
6965 if (i->radio) break;
6966 /* Got a ring/answer. What kind of channel are we? */
6967 switch (i->sig) {
6968 case SIG_FXOLS:
6969 case SIG_FXOGS:
6970 case SIG_FXOKS:
6971 res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
6972 if (res && (errno == EBUSY))
6973 break;
6974 if (i->cidspill) {
6975 /* Cancel VMWI spill */
6976 free(i->cidspill);
6977 i->cidspill = NULL;
6979 if (i->immediate) {
6980 dahdi_enable_ec(i);
6981 /* The channel is immediately up. Start right away */
6982 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
6983 chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
6984 if (!chan) {
6985 ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
6986 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
6987 if (res < 0)
6988 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
6990 } else {
6991 /* Check for callerid, digits, etc */
6992 chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
6993 if (chan) {
6994 if (has_voicemail(i))
6995 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
6996 else
6997 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
6998 if (res < 0)
6999 ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
7000 if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
7001 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7002 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
7003 if (res < 0)
7004 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7005 ast_hangup(chan);
7007 } else
7008 ast_log(LOG_WARNING, "Unable to create channel\n");
7010 break;
7011 case SIG_FXSLS:
7012 case SIG_FXSGS:
7013 case SIG_FXSKS:
7014 i->ringt = i->ringt_base;
7015 /* Fall through */
7016 case SIG_EMWINK:
7017 case SIG_FEATD:
7018 case SIG_FEATDMF:
7019 case SIG_FEATDMF_TA:
7020 case SIG_E911:
7021 case SIG_FGC_CAMA:
7022 case SIG_FGC_CAMAMF:
7023 case SIG_FEATB:
7024 case SIG_EM:
7025 case SIG_EM_E1:
7026 case SIG_SFWINK:
7027 case SIG_SF_FEATD:
7028 case SIG_SF_FEATDMF:
7029 case SIG_SF_FEATB:
7030 case SIG_SF:
7031 /* Check for callerid, digits, etc */
7032 chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
7033 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
7034 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7035 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
7036 if (res < 0)
7037 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7038 ast_hangup(chan);
7039 } else if (!chan) {
7040 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
7042 break;
7043 default:
7044 ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
7045 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
7046 if (res < 0)
7047 ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
7048 return -1;
7050 break;
7051 case DAHDI_EVENT_NOALARM:
7052 i->inalarm = 0;
7053 if (!i->unknown_alarm) {
7054 #ifdef HAVE_PRI
7055 if (i->pri) {
7056 if ((i->pri->nodetype == BRI_CPE_PTMP) || (i->pri->nodetype == BRI_CPE)) {
7057 /* dont annoy BRI TE mode users with layer2layer alarms */
7058 } else {
7059 #endif
7060 ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
7061 manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
7062 "Channel: %d\r\n", i->channel);
7063 #ifdef HAVE_PRI
7066 #endif
7068 } else {
7069 i->unknown_alarm = 0;
7071 break;
7072 case DAHDI_EVENT_ALARM:
7073 i->inalarm = 1;
7074 res = get_alarms(i);
7075 handle_alarms(i, res);
7076 /* fall thru intentionally */
7077 case DAHDI_EVENT_ONHOOK:
7078 if (i->radio)
7079 break;
7080 /* Back on hook. Hang up. */
7081 switch (i->sig) {
7082 case SIG_FXOLS:
7083 case SIG_FXOGS:
7084 case SIG_FEATD:
7085 case SIG_FEATDMF:
7086 case SIG_FEATDMF_TA:
7087 case SIG_E911:
7088 case SIG_FGC_CAMA:
7089 case SIG_FGC_CAMAMF:
7090 case SIG_FEATB:
7091 case SIG_EM:
7092 case SIG_EM_E1:
7093 case SIG_EMWINK:
7094 case SIG_SF_FEATD:
7095 case SIG_SF_FEATDMF:
7096 case SIG_SF_FEATB:
7097 case SIG_SF:
7098 case SIG_SFWINK:
7099 case SIG_FXSLS:
7100 case SIG_FXSGS:
7101 case SIG_FXSKS:
7102 case SIG_GR303FXSKS:
7103 dahdi_disable_ec(i);
7104 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
7105 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7106 break;
7107 case SIG_GR303FXOKS:
7108 case SIG_FXOKS:
7109 dahdi_disable_ec(i);
7110 /* Diddle the battery for the zhone */
7111 #ifdef ZHONE_HACK
7112 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
7113 usleep(1);
7114 #endif
7115 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
7116 dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7117 break;
7118 case SIG_PRI:
7119 if (event == DAHDI_EVENT_ALARM)
7120 break;
7121 dahdi_disable_ec(i);
7122 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
7123 break;
7124 default:
7125 ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
7126 res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
7127 return -1;
7129 break;
7130 case DAHDI_EVENT_POLARITY:
7131 switch (i->sig) {
7132 case SIG_FXSLS:
7133 case SIG_FXSKS:
7134 case SIG_FXSGS:
7135 /* We have already got a PR before the channel was
7136 created, but it wasn't handled. We need polarity
7137 to be REV for remote hangup detection to work.
7138 At least in Spain */
7139 if (i->hanguponpolarityswitch)
7140 i->polarity = POLARITY_REV;
7142 if (i->cid_start == CID_START_POLARITY) {
7143 i->polarity = POLARITY_REV;
7144 ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
7145 "CID detection on channel %d\n",
7146 i->channel);
7147 chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
7148 if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
7149 ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
7152 break;
7153 default:
7154 ast_log(LOG_WARNING, "handle_init_event detected "
7155 "polarity reversal on non-FXO (SIG_FXS) "
7156 "interface %d\n", i->channel);
7158 break;
7159 case DAHDI_EVENT_REMOVED: /* destroy channel */
7160 ast_log(LOG_NOTICE,
7161 "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
7162 i->channel);
7163 dahdi_destroy_channel_bynum(i->channel);
7164 break;
7166 pthread_attr_destroy(&attr);
7167 return 0;
7170 static void *do_monitor(void *data)
7172 int count, res, res2, spoint, pollres=0;
7173 struct dahdi_pvt *i;
7174 struct dahdi_pvt *last = NULL;
7175 time_t thispass = 0, lastpass = 0;
7176 int found;
7177 char buf[1024];
7178 struct pollfd *pfds=NULL;
7179 int lastalloc = -1;
7180 /* This thread monitors all the frame relay interfaces which are not yet in use
7181 (and thus do not have a separate thread) indefinitely */
7182 /* From here on out, we die whenever asked */
7183 #if 0
7184 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
7185 ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
7186 return NULL;
7188 ast_log(LOG_DEBUG, "Monitor starting...\n");
7189 #endif
7190 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
7192 for (;;) {
7193 /* Lock the interface list */
7194 ast_mutex_lock(&iflock);
7195 if (!pfds || (lastalloc != ifcount)) {
7196 if (pfds) {
7197 free(pfds);
7198 pfds = NULL;
7200 if (ifcount) {
7201 if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
7202 ast_mutex_unlock(&iflock);
7203 return NULL;
7206 lastalloc = ifcount;
7208 /* Build the stuff we're going to poll on, that is the socket of every
7209 dahdi_pvt that does not have an associated owner channel */
7210 count = 0;
7211 i = iflist;
7212 while (i) {
7213 if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
7214 if (!i->owner && !i->subs[SUB_REAL].owner) {
7215 /* This needs to be watched, as it lacks an owner */
7216 pfds[count].fd = i->subs[SUB_REAL].dfd;
7217 pfds[count].events = POLLPRI;
7218 pfds[count].revents = 0;
7219 /* Message waiting or r2 channels also get watched for reading */
7220 if (i->cidspill)
7221 pfds[count].events |= POLLIN;
7222 count++;
7225 i = i->next;
7227 /* Okay, now that we know what to do, release the interface lock */
7228 ast_mutex_unlock(&iflock);
7230 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
7231 pthread_testcancel();
7232 /* Wait at least a second for something to happen */
7233 res = poll(pfds, count, 1000);
7234 pthread_testcancel();
7235 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
7237 /* Okay, poll has finished. Let's see what happened. */
7238 if (res < 0) {
7239 if ((errno != EAGAIN) && (errno != EINTR))
7240 ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
7241 continue;
7243 /* Alright, lock the interface list again, and let's look and see what has
7244 happened */
7245 ast_mutex_lock(&iflock);
7246 found = 0;
7247 spoint = 0;
7248 lastpass = thispass;
7249 thispass = time(NULL);
7250 i = iflist;
7251 while (i) {
7252 if (thispass != lastpass) {
7253 if (!found && ((i == last) || ((i == iflist) && !last))) {
7254 last = i;
7255 if (last) {
7256 if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
7257 (last->sig & __DAHDI_SIG_FXO)) {
7258 res = ast_app_has_voicemail(last->mailbox, NULL);
7259 if (last->msgstate != res) {
7260 int x;
7261 ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
7262 x = DAHDI_FLUSH_BOTH;
7263 res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
7264 if (res2)
7265 ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
7266 if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
7267 /* Turn on on hook transfer for 4 seconds */
7268 x = 4000;
7269 ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
7270 last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
7271 last->cidpos = 0;
7272 last->msgstate = res;
7273 last->onhooktime = thispass;
7275 found ++;
7278 last = last->next;
7282 if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
7283 if (i->radio && !i->owner)
7285 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7286 if (res)
7288 if (option_debug)
7289 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
7290 /* Don't hold iflock while handling init events */
7291 ast_mutex_unlock(&iflock);
7292 handle_init_event(i, res);
7293 ast_mutex_lock(&iflock);
7295 i = i->next;
7296 continue;
7298 pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
7299 if (pollres & POLLIN) {
7300 if (i->owner || i->subs[SUB_REAL].owner) {
7301 #ifdef HAVE_PRI
7302 if (!i->pri)
7303 #endif
7304 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
7305 i = i->next;
7306 continue;
7308 if (!i->cidspill) {
7309 ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
7310 i = i->next;
7311 continue;
7313 res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
7314 if (res > 0) {
7315 /* We read some number of bytes. Write an equal amount of data */
7316 if (res > i->cidlen - i->cidpos)
7317 res = i->cidlen - i->cidpos;
7318 res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
7319 if (res2 > 0) {
7320 i->cidpos += res2;
7321 if (i->cidpos >= i->cidlen) {
7322 free(i->cidspill);
7323 i->cidspill = 0;
7324 i->cidpos = 0;
7325 i->cidlen = 0;
7327 } else {
7328 ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
7329 i->msgstate = -1;
7331 } else {
7332 ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
7335 if (pollres & POLLPRI) {
7336 if (i->owner || i->subs[SUB_REAL].owner) {
7337 #ifdef HAVE_PRI
7338 if (!i->pri)
7339 #endif
7340 ast_log(LOG_WARNING, "Whoa.... I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
7341 i = i->next;
7342 continue;
7344 res = dahdi_get_event(i->subs[SUB_REAL].dfd);
7345 if (option_debug)
7346 ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
7347 /* Don't hold iflock while handling init events */
7348 ast_mutex_unlock(&iflock);
7349 handle_init_event(i, res);
7350 ast_mutex_lock(&iflock);
7353 i=i->next;
7355 ast_mutex_unlock(&iflock);
7357 /* Never reached */
7358 return NULL;
7362 static int restart_monitor(void)
7364 pthread_attr_t attr;
7365 pthread_attr_init(&attr);
7366 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
7367 /* If we're supposed to be stopped -- stay stopped */
7368 if (monitor_thread == AST_PTHREADT_STOP)
7369 return 0;
7370 ast_mutex_lock(&monlock);
7371 if (monitor_thread == pthread_self()) {
7372 ast_mutex_unlock(&monlock);
7373 ast_log(LOG_WARNING, "Cannot kill myself\n");
7374 return -1;
7376 if (monitor_thread != AST_PTHREADT_NULL) {
7377 /* Wake up the thread */
7378 pthread_kill(monitor_thread, SIGURG);
7379 } else {
7380 /* Start a new monitor */
7381 if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
7382 ast_mutex_unlock(&monlock);
7383 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
7384 pthread_attr_destroy(&attr);
7385 return -1;
7388 ast_mutex_unlock(&monlock);
7389 pthread_attr_destroy(&attr);
7390 return 0;
7393 #ifdef HAVE_PRI
7394 static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spaninfo *si)
7396 int x;
7397 int trunkgroup;
7398 /* Get appropriate trunk group if there is one */
7399 trunkgroup = pris[*span].mastertrunkgroup;
7400 if (trunkgroup) {
7401 /* Select a specific trunk group */
7402 for (x = 0; x < NUM_SPANS; x++) {
7403 if (pris[x].trunkgroup == trunkgroup) {
7404 *span = x;
7405 return 0;
7408 ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
7409 *span = -1;
7410 } else {
7411 if (pris[*span].trunkgroup) {
7412 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
7413 *span = -1;
7414 } else if (pris[*span].mastertrunkgroup) {
7415 ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
7416 *span = -1;
7417 } else {
7418 if (si->totalchans == 31) {
7419 /* E1 */
7420 pris[*span].dchannels[0] = 16 + offset;
7421 } else if (si->totalchans == 24) {
7422 /* T1 or J1 */
7423 pris[*span].dchannels[0] = 24 + offset;
7424 } else if (si->totalchans == 3) {
7425 /* BRI */
7426 pris[*span].dchannels[0] = 3 + offset;
7427 } else {
7428 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);
7429 *span = -1;
7430 return 0;
7432 pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
7433 pris[*span].offset = offset;
7434 pris[*span].span = *span + 1;
7437 return 0;
7440 static int pri_create_trunkgroup(int trunkgroup, int *channels)
7442 struct dahdi_spaninfo si;
7443 struct dahdi_params p;
7444 int fd;
7445 int span;
7446 int ospan=0;
7447 int x,y;
7448 for (x = 0; x < NUM_SPANS; x++) {
7449 if (pris[x].trunkgroup == trunkgroup) {
7450 ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
7451 return -1;
7454 for (y = 0; y < NUM_DCHANS; y++) {
7455 if (!channels[y])
7456 break;
7457 memset(&si, 0, sizeof(si));
7458 memset(&p, 0, sizeof(p));
7459 #ifdef HAVE_ZAPTEL
7460 fd = open("/dev/zap/channel", O_RDWR);
7461 #else
7462 fd = open("/dev/dahdi/channel", O_RDWR);
7463 #endif
7464 if (fd < 0) {
7465 ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
7466 return -1;
7468 x = channels[y];
7469 if (ioctl(fd, DAHDI_SPECIFY, &x)) {
7470 ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
7471 close(fd);
7472 return -1;
7474 if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
7475 ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
7476 return -1;
7478 if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
7479 ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
7480 close(fd);
7481 return -1;
7483 span = p.spanno - 1;
7484 if (pris[span].trunkgroup) {
7485 ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
7486 close(fd);
7487 return -1;
7489 if (pris[span].pvts[0]) {
7490 ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
7491 close(fd);
7492 return -1;
7494 if (!y) {
7495 pris[span].trunkgroup = trunkgroup;
7496 pris[span].offset = channels[y] - p.chanpos;
7497 ospan = span;
7499 pris[ospan].dchannels[y] = channels[y];
7500 pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
7501 pris[span].span = span + 1;
7502 close(fd);
7504 return 0;
7507 static int pri_create_spanmap(int span, int trunkgroup, int logicalspan)
7509 if (pris[span].mastertrunkgroup) {
7510 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);
7511 return -1;
7513 pris[span].mastertrunkgroup = trunkgroup;
7514 pris[span].prilogicalspan = logicalspan;
7515 return 0;
7518 #endif
7520 #ifdef HAVE_GSMAT
7521 static void *gsm_dchannel(void *vgsm);
7522 #endif
7524 static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
7526 /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
7527 struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
7528 char fn[80];
7529 #if 1
7530 struct dahdi_bufferinfo bi;
7531 #endif
7532 int res;
7533 int span=0;
7534 int here = 0;
7535 int x;
7536 struct dahdi_pvt **wlist;
7537 struct dahdi_pvt **wend;
7538 struct dahdi_params p;
7540 wlist = &iflist;
7541 wend = &ifend;
7543 #ifdef HAVE_PRI
7544 if (pri) {
7545 wlist = &pri->crvs;
7546 wend = &pri->crvend;
7548 #endif
7550 tmp2 = *wlist;
7551 prev = NULL;
7553 while (tmp2) {
7554 if (!tmp2->destroy) {
7555 if (tmp2->channel == channel) {
7556 tmp = tmp2;
7557 here = 1;
7558 break;
7560 if (tmp2->channel > channel) {
7561 break;
7564 prev = tmp2;
7565 tmp2 = tmp2->next;
7568 if (!here && reloading != 1) {
7569 if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
7570 if (tmp)
7571 free(tmp);
7572 return NULL;
7574 ast_mutex_init(&tmp->lock);
7575 ifcount++;
7576 for (x = 0; x < 3; x++)
7577 tmp->subs[x].dfd = -1;
7578 tmp->channel = channel;
7581 if (tmp) {
7582 int chan_sig = conf->chan.sig;
7583 if (!here) {
7584 if ((channel != CHAN_PSEUDO) && !pri) {
7585 int count = 0;
7586 snprintf(fn, sizeof(fn), "%d", channel);
7587 /* Open non-blocking */
7588 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7589 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 */
7590 usleep(1);
7591 tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
7592 count++;
7594 /* Allocate a DAHDI structure */
7595 if (tmp->subs[SUB_REAL].dfd < 0) {
7596 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);
7597 destroy_dahdi_pvt(&tmp);
7598 return NULL;
7600 memset(&p, 0, sizeof(p));
7601 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7602 if (res < 0) {
7603 ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
7604 destroy_dahdi_pvt(&tmp);
7605 return NULL;
7607 if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
7608 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));
7609 destroy_dahdi_pvt(&tmp);
7610 return NULL;
7612 tmp->law = p.curlaw;
7613 tmp->span = p.spanno;
7614 span = p.spanno - 1;
7615 } else {
7616 if (channel == CHAN_PSEUDO)
7617 chan_sig = 0;
7618 else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
7619 ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
7620 return NULL;
7623 #ifdef HAVE_PRI
7624 if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
7625 int offset;
7626 int myswitchtype;
7627 int matchesdchan;
7628 int x,y;
7629 offset = 0;
7630 if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
7631 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
7632 destroy_dahdi_pvt(&tmp);
7633 return NULL;
7635 if (span >= NUM_SPANS) {
7636 ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
7637 destroy_dahdi_pvt(&tmp);
7638 return NULL;
7639 } else {
7640 struct dahdi_spaninfo si;
7641 si.spanno = 0;
7642 if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
7643 ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
7644 destroy_dahdi_pvt(&tmp);
7645 return NULL;
7647 /* Store the logical span first based upon the real span */
7648 tmp->logicalspan = pris[span].prilogicalspan;
7649 pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
7650 if (span < 0) {
7651 ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
7652 destroy_dahdi_pvt(&tmp);
7653 return NULL;
7655 if (chan_sig == SIG_PRI)
7656 myswitchtype = conf->pri.switchtype;
7657 else
7658 myswitchtype = PRI_SWITCH_GR303_TMC;
7659 /* Make sure this isn't a d-channel */
7660 matchesdchan=0;
7661 for (x = 0; x < NUM_SPANS; x++) {
7662 for (y = 0; y < NUM_DCHANS; y++) {
7663 if (pris[x].dchannels[y] == tmp->channel) {
7664 matchesdchan = 1;
7665 break;
7669 offset = p.chanpos;
7670 if (!matchesdchan) {
7671 if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
7672 ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
7673 destroy_dahdi_pvt(&tmp);
7674 return NULL;
7676 if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
7677 ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
7678 destroy_dahdi_pvt(&tmp);
7679 return NULL;
7681 if ((pris[span].localdialplan) && (pris[span].localdialplan != conf->pri.localdialplan)) {
7682 ast_log(LOG_ERROR, "Span %d is already a %s local dialing plan\n", span + 1, dialplan2str(pris[span].localdialplan));
7683 destroy_dahdi_pvt(&tmp);
7684 return NULL;
7686 if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
7687 ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
7688 destroy_dahdi_pvt(&tmp);
7689 return NULL;
7691 if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
7692 ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
7693 destroy_dahdi_pvt(&tmp);
7694 return NULL;
7696 if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
7697 ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
7698 destroy_dahdi_pvt(&tmp);
7699 return NULL;
7701 if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
7702 ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
7703 destroy_dahdi_pvt(&tmp);
7704 return NULL;
7706 if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
7707 ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
7708 destroy_dahdi_pvt(&tmp);
7709 return NULL;
7711 if (pris[span].numchans >= MAX_CHANNELS) {
7712 ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
7713 pris[span].trunkgroup);
7714 destroy_dahdi_pvt(&tmp);
7715 return NULL;
7717 pris[span].nodetype = conf->pri.nodetype;
7718 if (conf->pri.nodetype == BRI_NETWORK_PTMP) {
7719 pris[span].dchanavail[0] = DCHAN_AVAILABLE;
7720 pri_find_dchan(&pris[span]);
7722 pris[span].switchtype = myswitchtype;
7723 pris[span].nsf = conf->pri.nsf;
7724 pris[span].dialplan = conf->pri.dialplan;
7725 pris[span].localdialplan = conf->pri.localdialplan;
7726 pris[span].pvts[pris[span].numchans++] = tmp;
7727 pris[span].minunused = conf->pri.minunused;
7728 pris[span].minidle = conf->pri.minidle;
7729 pris[span].overlapdial = conf->pri.overlapdial;
7730 #ifdef HAVE_PRI_INBANDDISCONNECT
7731 pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
7732 #endif
7733 pris[span].suspended_calls = NULL;
7734 pris[span].holded_calls = NULL;
7735 pris[span].facilityenable = conf->pri.facilityenable;
7736 ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
7737 ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
7738 ast_copy_string(pris[span].nocid, conf->pri.nocid, sizeof(pris[span].nocid));
7739 ast_copy_string(pris[span].withheldcid, conf->pri.withheldcid, sizeof(pris[span].withheldcid));
7740 ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
7741 ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
7742 ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
7743 ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
7744 ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
7745 pris[span].resetinterval = conf->pri.resetinterval;
7747 tmp->pri = &pris[span];
7748 tmp->prioffset = offset;
7749 tmp->call = NULL;
7750 } else {
7751 ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
7752 destroy_dahdi_pvt(&tmp);
7753 return NULL;
7756 } else {
7757 tmp->prioffset = 0;
7759 #endif
7760 #ifdef HAVE_GSMAT
7761 if (conf->chan.sig == SIG_GSM) {
7762 struct dahdi_bufferinfo bi;
7763 ast_mutex_init(&tmp->gsm.lock);
7764 strncpy(tmp->gsm.pin, gsm_modem_pin, sizeof(tmp->gsm.pin) - 1);
7765 strncpy(tmp->gsm.exten, gsm_modem_exten, sizeof(tmp->gsm.exten) - 1);
7766 tmp->gsm.available = 0;
7767 snprintf(fn, sizeof(fn), "%d", channel + 1);
7768 /* Open non-blocking */
7769 tmp->gsm.fd = dahdi_open(fn);
7770 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
7771 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
7772 bi.numbufs = 16;
7773 bi.bufsize = 1024;
7774 if (ioctl(tmp->gsm.fd, DAHDI_SET_BUFINFO, &bi)) {
7775 ast_log(LOG_ERROR, "Unable to set buffer info on channel '%s': %s\n", fn, strerror(errno));
7776 return NULL;
7778 tmp->gsm.pvt = tmp;
7779 tmp->gsm.span = tmp->span;
7780 tmp->gsm.modul = gsm_new(tmp->gsm.fd, 0, tmp->gsm.pin, tmp->span, tmp->channel);
7781 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, tmp->channel)) {
7782 ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d: %s\n", tmp->channel, strerror(errno));
7783 destroy_dahdi_pvt(&tmp);
7784 return NULL;
7786 if (ast_pthread_create(&tmp->gsm.master, NULL, gsm_dchannel, &tmp->gsm)) {
7787 dahdi_close(tmp->gsm.fd);
7790 #endif
7791 } else {
7792 chan_sig = tmp->sig;
7793 memset(&p, 0, sizeof(p));
7794 if (tmp->subs[SUB_REAL].dfd > -1)
7795 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
7797 /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
7798 switch (chan_sig) {
7799 case SIG_FXSKS:
7800 case SIG_FXSLS:
7801 case SIG_EM:
7802 case SIG_EM_E1:
7803 case SIG_EMWINK:
7804 case SIG_FEATD:
7805 case SIG_FEATDMF:
7806 case SIG_FEATDMF_TA:
7807 case SIG_FEATB:
7808 case SIG_E911:
7809 case SIG_SF:
7810 case SIG_SFWINK:
7811 case SIG_FGC_CAMA:
7812 case SIG_FGC_CAMAMF:
7813 case SIG_SF_FEATD:
7814 case SIG_SF_FEATDMF:
7815 case SIG_SF_FEATB:
7816 p.starttime = 250;
7817 break;
7820 if (tmp->radio) {
7821 /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
7822 p.channo = channel;
7823 p.rxwinktime = 1;
7824 p.rxflashtime = 1;
7825 p.starttime = 1;
7826 p.debouncetime = 5;
7828 if (!tmp->radio) {
7829 p.channo = channel;
7830 /* Override timing settings based on config file */
7831 if (conf->timing.prewinktime >= 0)
7832 p.prewinktime = conf->timing.prewinktime;
7833 if (conf->timing.preflashtime >= 0)
7834 p.preflashtime = conf->timing.preflashtime;
7835 if (conf->timing.winktime >= 0)
7836 p.winktime = conf->timing.winktime;
7837 if (conf->timing.flashtime >= 0)
7838 p.flashtime = conf->timing.flashtime;
7839 if (conf->timing.starttime >= 0)
7840 p.starttime = conf->timing.starttime;
7841 if (conf->timing.rxwinktime >= 0)
7842 p.rxwinktime = conf->timing.rxwinktime;
7843 if (conf->timing.rxflashtime >= 0)
7844 p.rxflashtime = conf->timing.rxflashtime;
7845 if (conf->timing.debouncetime >= 0)
7846 p.debouncetime = conf->timing.debouncetime;
7849 /* dont set parms on a pseudo-channel (or CRV) */
7850 if (tmp->subs[SUB_REAL].dfd >= 0)
7852 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
7853 if (res < 0) {
7854 ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
7855 destroy_dahdi_pvt(&tmp);
7856 return NULL;
7859 #if 1
7860 if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
7861 memset(&bi, 0, sizeof(bi));
7862 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
7863 if (!res) {
7864 bi.txbufpolicy = conf->chan.buf_policy;
7865 bi.rxbufpolicy = conf->chan.buf_policy;
7866 bi.numbufs = conf->chan.buf_no;
7867 res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
7868 if (res < 0) {
7869 ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
7871 } else
7872 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
7874 #endif
7875 tmp->immediate = conf->chan.immediate;
7876 tmp->transfertobusy = conf->chan.transfertobusy;
7877 tmp->sig = chan_sig;
7878 tmp->outsigmod = conf->chan.outsigmod;
7879 tmp->ringt_base = ringt_base;
7880 tmp->firstradio = 0;
7881 if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
7882 tmp->permcallwaiting = conf->chan.callwaiting;
7883 else
7884 tmp->permcallwaiting = 0;
7885 /* Flag to destroy the channel must be cleared on new mkif. Part of changes for reload to work */
7886 tmp->destroy = 0;
7887 tmp->drings = drings;
7888 tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
7889 tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
7890 tmp->threewaycalling = conf->chan.threewaycalling;
7891 tmp->adsi = conf->chan.adsi;
7892 tmp->use_smdi = conf->chan.use_smdi;
7893 tmp->permhidecallerid = conf->chan.hidecallerid;
7894 tmp->callreturn = conf->chan.callreturn;
7895 tmp->echocancel = conf->chan.echocancel;
7896 tmp->echotraining = conf->chan.echotraining;
7897 tmp->pulse = conf->chan.pulse;
7898 if (tmp->echocancel)
7899 tmp->echocanbridged = conf->chan.echocanbridged;
7900 else {
7901 if (conf->chan.echocanbridged)
7902 ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
7903 tmp->echocanbridged = 0;
7905 tmp->busydetect = conf->chan.busydetect;
7906 tmp->busycount = conf->chan.busycount;
7907 tmp->busy_tonelength = conf->chan.busy_tonelength;
7908 tmp->busy_quietlength = conf->chan.busy_quietlength;
7909 tmp->callprogress = conf->chan.callprogress;
7910 tmp->cancallforward = conf->chan.cancallforward;
7911 tmp->dtmfrelax = conf->chan.dtmfrelax;
7912 tmp->callwaiting = tmp->permcallwaiting;
7913 tmp->hidecallerid = tmp->permhidecallerid;
7914 tmp->channel = channel;
7915 tmp->stripmsd = conf->chan.stripmsd;
7916 tmp->use_callerid = conf->chan.use_callerid;
7917 tmp->cid_signalling = conf->chan.cid_signalling;
7918 tmp->cid_start = conf->chan.cid_start;
7919 tmp->dahditrcallerid = conf->chan.dahditrcallerid;
7920 tmp->restrictcid = conf->chan.restrictcid;
7921 tmp->use_callingpres = conf->chan.use_callingpres;
7922 tmp->priindication_oob = conf->chan.priindication_oob;
7923 tmp->pritransfer = conf->chan.pritransfer;
7924 tmp->priexclusive = conf->chan.priexclusive;
7925 if (tmp->usedistinctiveringdetection) {
7926 if (!tmp->use_callerid) {
7927 ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
7928 tmp->use_callerid = 1;
7932 if (tmp->cid_signalling == CID_SIG_SMDI) {
7933 if (!tmp->use_smdi) {
7934 ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
7935 tmp->use_smdi = 1;
7938 if (tmp->use_smdi) {
7939 tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
7940 if (!(tmp->smdi_iface)) {
7941 ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
7942 tmp->use_smdi = 0;
7946 ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
7947 tmp->amaflags = conf->chan.amaflags;
7948 if (!here) {
7949 tmp->confno = -1;
7950 tmp->propconfno = -1;
7952 tmp->canpark = conf->chan.canpark;
7953 tmp->transfer = conf->chan.transfer;
7954 ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
7955 ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
7956 ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
7957 ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
7958 ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
7959 ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
7960 tmp->cid_ton = 0;
7961 ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
7962 ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
7963 tmp->msgstate = -1;
7964 tmp->group = conf->chan.group;
7965 tmp->callgroup = conf->chan.callgroup;
7966 tmp->pickupgroup= conf->chan.pickupgroup;
7967 tmp->rxgain = conf->chan.rxgain;
7968 tmp->txgain = conf->chan.txgain;
7969 tmp->tonezone = conf->chan.tonezone;
7970 tmp->onhooktime = time(NULL);
7971 if (tmp->subs[SUB_REAL].dfd > -1) {
7972 set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
7973 if (tmp->dsp)
7974 ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
7975 update_conf(tmp);
7976 if (!here) {
7977 if (chan_sig != SIG_PRI)
7978 /* Hang it up to be sure it's good */
7979 dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
7981 ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
7982 #ifdef HAVE_PRI
7983 /* the dchannel is down so put the channel in alarm */
7984 if (tmp->pri && !pri_is_up(tmp->pri)) {
7985 tmp->inalarm = 1;
7987 #endif
7988 if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
7989 tmp->inalarm = 1;
7990 handle_alarms(tmp, res);
7991 } else {
7992 /* yes, this looks strange... the unknown_alarm flag is only used to
7993 control whether an 'alarm cleared' message gets generated when we
7994 get an indication that the channel is no longer in alarm status.
7995 however, the channel *could* be in an alarm status that we aren't
7996 aware of (since get_alarms() only reports span alarms, not channel
7997 alarms). setting this flag will cause any potential 'alarm cleared'
7998 message to be suppressed, but if a real alarm occurs before that
7999 happens, this flag will get cleared by it and the situation will
8000 be normal.
8002 tmp->unknown_alarm = 1;
8006 tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
8007 tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
8008 tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
8009 tmp->sendcalleridafter = conf->chan.sendcalleridafter;
8012 if (tmp && !here) {
8013 /* nothing on the iflist */
8014 if (!*wlist) {
8015 *wlist = tmp;
8016 tmp->prev = NULL;
8017 tmp->next = NULL;
8018 *wend = tmp;
8019 } else {
8020 /* at least one member on the iflist */
8021 struct dahdi_pvt *working = *wlist;
8023 /* check if we maybe have to put it on the begining */
8024 if (working->channel > tmp->channel) {
8025 tmp->next = *wlist;
8026 tmp->prev = NULL;
8027 (*wlist)->prev = tmp;
8028 *wlist = tmp;
8029 } else {
8030 /* go through all the members and put the member in the right place */
8031 while (working) {
8032 /* in the middle */
8033 if (working->next) {
8034 if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
8035 tmp->next = working->next;
8036 tmp->prev = working;
8037 working->next->prev = tmp;
8038 working->next = tmp;
8039 break;
8041 } else {
8042 /* the last */
8043 if (working->channel < tmp->channel) {
8044 working->next = tmp;
8045 tmp->next = NULL;
8046 tmp->prev = working;
8047 *wend = tmp;
8048 break;
8051 working = working->next;
8056 return tmp;
8059 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
8061 int res;
8062 struct dahdi_params par;
8064 /* First, check group matching */
8065 if (groupmatch) {
8066 if ((p->group & groupmatch) != groupmatch)
8067 return 0;
8068 *groupmatched = 1;
8070 /* Check to see if we have a channel match */
8071 if (channelmatch != -1) {
8072 if (p->channel != channelmatch)
8073 return 0;
8074 *channelmatched = 1;
8076 /* We're at least busy at this point */
8077 if (busy) {
8078 if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
8079 *busy = 1;
8081 /* If do not disturb, definitely not */
8082 if (p->dnd)
8083 return 0;
8084 /* If guard time, definitely not */
8085 if (p->guardtime && (time(NULL) < p->guardtime))
8086 return 0;
8088 /* If no owner definitely available */
8089 if (!p->owner) {
8090 #ifdef HAVE_PRI
8091 /* Trust PRI */
8092 if (p->pri) {
8093 if (p->resetting || p->call)
8094 return 0;
8095 else
8096 return 1;
8098 #endif
8099 #ifdef HAVE_GSMAT
8100 if (p->gsm.modul) {
8101 return gsm_available(p->gsm.modul);
8104 #endif
8105 if (!(p->radio || (p->oprmode < 0)))
8107 if (!p->sig || (p->sig == SIG_FXSLS))
8108 return 1;
8109 /* Check hook state */
8110 if (p->subs[SUB_REAL].dfd > -1)
8111 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
8112 else {
8113 /* Assume not off hook on CVRS */
8114 res = 0;
8115 par.rxisoffhook = 0;
8117 if (res) {
8118 ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
8119 } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
8120 /* When "onhook" that means no battery on the line, and thus
8121 it is out of service..., if it's on a TDM card... If it's a channel
8122 bank, there is no telling... */
8123 if (par.rxbits > -1)
8124 return 1;
8125 if (par.rxisoffhook)
8126 return 1;
8127 else
8128 #ifdef DAHDI_CHECK_HOOKSTATE
8129 return 0;
8130 #else
8131 return 1;
8132 #endif
8133 } else if (par.rxisoffhook) {
8134 ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
8135 /* Not available when the other end is off hook */
8136 return 0;
8139 return 1;
8142 /* If it's not an FXO, forget about call wait */
8143 if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
8144 return 0;
8146 if (!p->callwaiting) {
8147 /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
8148 return 0;
8151 if (p->subs[SUB_CALLWAIT].dfd > -1) {
8152 /* If there is already a call waiting call, then we can't take a second one */
8153 return 0;
8156 if ((p->owner->_state != AST_STATE_UP) &&
8157 ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
8158 /* If the current call is not up, then don't allow the call */
8159 return 0;
8161 if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
8162 /* Can't take a call wait when the three way calling hasn't been merged yet. */
8163 return 0;
8165 /* We're cool */
8166 return 1;
8169 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
8171 struct dahdi_pvt *p;
8172 struct dahdi_bufferinfo bi;
8173 int res;
8175 if ((p = ast_malloc(sizeof(*p)))) {
8176 memcpy(p, src, sizeof(struct dahdi_pvt));
8177 ast_mutex_init(&p->lock);
8178 #ifdef HAVE_ZAPTEL
8179 p->subs[SUB_REAL].dfd = dahdi_open("/dev/zap/pseudo");
8180 #else
8181 p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
8182 #endif
8183 /* Allocate a DAHDI structure */
8184 if (p->subs[SUB_REAL].dfd < 0) {
8185 ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
8186 destroy_dahdi_pvt(&p);
8187 return NULL;
8189 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
8190 if (!res) {
8191 bi.txbufpolicy = p->buf_policy;
8192 bi.rxbufpolicy = p->buf_policy;
8193 bi.numbufs = p->buf_no;
8194 res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
8195 if (res < 0) {
8196 ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
8198 } else
8199 ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
8201 p->destroy = 1;
8202 p->next = iflist;
8203 p->prev = NULL;
8204 iflist = p;
8205 if (iflist->next)
8206 iflist->next->prev = p;
8207 return p;
8211 #ifdef HAVE_PRI
8212 static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
8214 int x;
8215 if (backwards)
8216 x = pri->numchans;
8217 else
8218 x = 0;
8219 for (;;) {
8220 if (backwards && (x < 0))
8221 break;
8222 if (!backwards && (x >= pri->numchans))
8223 break;
8224 if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner && !pri->pvts[x]->call) {
8225 ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
8226 pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
8227 return x;
8229 if (backwards)
8230 x--;
8231 else
8232 x++;
8234 return -1;
8236 #endif
8238 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
8240 ast_group_t groupmatch = 0;
8241 int channelmatch = -1;
8242 int roundrobin = 0;
8243 int callwait = 0;
8244 int busy = 0;
8245 struct dahdi_pvt *p;
8246 struct ast_channel *tmp = NULL;
8247 char *dest=NULL;
8248 int x;
8249 char *s;
8250 char opt=0;
8251 int res=0, y=0;
8252 int backwards = 0;
8253 #ifdef HAVE_PRI
8254 int crv;
8255 int bearer = -1;
8256 int trunkgroup;
8257 struct dahdi_pri *pri=NULL;
8258 #endif
8259 struct dahdi_pvt *exit, *start, *end;
8260 ast_mutex_t *lock;
8261 int channelmatched = 0;
8262 int groupmatched = 0;
8264 /* Assume we're locking the iflock */
8265 lock = &iflock;
8266 start = iflist;
8267 end = ifend;
8268 if (data) {
8269 dest = ast_strdupa((char *)data);
8270 } else {
8271 ast_log(LOG_WARNING, "Channel requested with no data\n");
8272 return NULL;
8274 if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
8275 /* Retrieve the group number */
8276 char *stringp=NULL;
8277 stringp=dest + 1;
8278 s = strsep(&stringp, "/");
8279 if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
8280 ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
8281 return NULL;
8283 groupmatch = ((ast_group_t) 1 << x);
8284 if (toupper(dest[0]) == 'G') {
8285 if (dest[0] == 'G') {
8286 backwards = 1;
8287 p = ifend;
8288 } else
8289 p = iflist;
8290 } else {
8291 if (dest[0] == 'R') {
8292 backwards = 1;
8293 p = round_robin[x]?round_robin[x]->prev:ifend;
8294 if (!p)
8295 p = ifend;
8296 } else {
8297 p = round_robin[x]?round_robin[x]->next:iflist;
8298 if (!p)
8299 p = iflist;
8301 roundrobin = 1;
8303 } else {
8304 char *stringp=NULL;
8305 stringp=dest;
8306 s = strsep(&stringp, "/");
8307 p = iflist;
8308 if (!strcasecmp(s, "pseudo")) {
8309 /* Special case for pseudo */
8310 x = CHAN_PSEUDO;
8311 channelmatch = x;
8313 #ifdef HAVE_PRI
8314 else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
8315 if ((trunkgroup < 1) || (crv < 1)) {
8316 ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
8317 return NULL;
8319 res--;
8320 for (x = 0; x < NUM_SPANS; x++) {
8321 if (pris[x].trunkgroup == trunkgroup) {
8322 pri = pris + x;
8323 lock = &pri->lock;
8324 start = pri->crvs;
8325 end = pri->crvend;
8326 break;
8329 if (!pri) {
8330 ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
8331 return NULL;
8333 channelmatch = crv;
8334 p = pris[x].crvs;
8336 #endif
8337 else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
8338 ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
8339 return NULL;
8340 } else {
8341 channelmatch = x;
8344 /* Search for an unowned channel */
8345 ast_mutex_lock(lock);
8346 exit = p;
8347 while (p && !tmp) {
8348 if (roundrobin)
8349 round_robin[x] = p;
8350 #if 0
8351 ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
8352 #endif
8354 if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
8355 if (option_debug)
8356 ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
8357 if (p->inalarm)
8358 goto next;
8360 callwait = (p->owner != NULL);
8361 #ifdef HAVE_PRI
8362 if (pri && (p->subs[SUB_REAL].dfd < 0)) {
8363 if (p->sig != SIG_FXSKS) {
8364 /* Gotta find an actual channel to use for this
8365 CRV if this isn't a callwait */
8366 bearer = pri_find_empty_chan(pri, 0);
8367 if (bearer < 0) {
8368 ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
8369 p = NULL;
8370 break;
8372 pri_assign_bearer(p, pri, pri->pvts[bearer]);
8373 } else {
8374 if (alloc_sub(p, 0)) {
8375 ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
8376 p = NULL;
8377 break;
8378 } else
8379 ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
8380 p->pri = pri;
8383 #endif
8384 if (p->channel == CHAN_PSEUDO) {
8385 p = chandup(p);
8386 if (!p) {
8387 break;
8390 if (p->owner) {
8391 if (alloc_sub(p, SUB_CALLWAIT)) {
8392 p = NULL;
8393 break;
8396 p->outgoing = 1;
8397 tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
8398 #ifdef HAVE_PRI
8399 if (p->bearer) {
8400 /* Log owner to bearer channel, too */
8401 p->bearer->owner = tmp;
8403 #endif
8404 /* Make special notes */
8405 if (res > 1) {
8406 if (opt == 'c') {
8407 /* Confirm answer */
8408 p->confirmanswer = 1;
8409 } else if (opt == 'r') {
8410 /* Distinctive ring */
8411 if (res < 3)
8412 ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
8413 else
8414 p->distinctivering = y;
8415 } else if (opt == 'd') {
8416 /* If this is an ISDN call, make it digital */
8417 p->digital = 1;
8418 if (tmp)
8419 tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
8420 } else if (opt == 'm') {
8421 /* If this is a modem/fax call, pretend to have the fax handled and dont do EC */
8422 p->faxhandled = 1;
8423 if (tmp)
8424 tmp->transfercapability = AST_TRANS_CAP_3_1K_AUDIO;
8425 } else {
8426 ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
8429 /* Note if the call is a call waiting call */
8430 if (tmp && callwait)
8431 tmp->cdrflags |= AST_CDR_CALLWAIT;
8432 break;
8434 next:
8435 if (backwards) {
8436 p = p->prev;
8437 if (!p)
8438 p = end;
8439 } else {
8440 p = p->next;
8441 if (!p)
8442 p = start;
8444 /* stop when you roll to the one that we started from */
8445 if (p == exit)
8446 break;
8448 ast_mutex_unlock(lock);
8449 restart_monitor();
8450 if (callwait)
8451 *cause = AST_CAUSE_BUSY;
8452 else if (!tmp) {
8453 if (channelmatched) {
8454 if (busy)
8455 *cause = AST_CAUSE_BUSY;
8456 } else if (groupmatched) {
8457 *cause = AST_CAUSE_CONGESTION;
8458 } else {
8459 *cause = AST_CAUSE_CONGESTION;
8463 return tmp;
8466 #ifdef HAVE_GSMAT
8467 static int dahdi_reset_span(int span, int sleep) {
8468 int ctl;
8469 int res;
8471 ctl = open("/dev/zap/ctl", O_RDWR);
8472 if (ctl < 0) {
8473 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
8474 return -1;
8476 ast_verbose(VERBOSE_PREFIX_2 "Shutting down span %d. Please wait...\n", span);
8477 res = ioctl(ctl, DAHDI_SHUTDOWN, &span);
8478 if (res) {
8479 ast_log(LOG_WARNING, "error shutting down span %d\n", span);
8480 return -1;
8482 usleep(sleep * 1000);
8483 ast_verbose(VERBOSE_PREFIX_2 "Starting up span %d. Please wait...\n", span);
8484 res = ioctl(ctl, DAHDI_STARTUP, &span);
8485 if (res) {
8486 ast_log(LOG_WARNING, "error starting up span %d\n", span);
8487 return -1;
8489 ast_verbose(VERBOSE_PREFIX_2 "Reset of span %d completed.\n", span);
8490 return 0;
8494 static void handle_gsm_event(struct dahdi_gsm *gsm, gsm_event *e)
8496 struct ast_channel *c = NULL;
8497 int law = DAHDI_LAW_ALAW;
8498 int res = 0;
8500 switch(e->e) {
8501 case GSM_EVENT_DCHAN_UP:
8502 if (option_verbose > 2)
8503 ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d registered to network!\n", gsm->span);
8504 gsm->available = 1;
8505 break;
8506 case GSM_EVENT_DCHAN_DOWN:
8507 if (option_verbose > 2)
8508 ast_verbose(VERBOSE_PREFIX_3 "GSM Span %d unregistered from network!\n", gsm->span);
8509 gsm->available = 0;
8510 /* ast_mutex_lock(&gsm->pvt->lock);
8511 gsm->pvt->alreadyhungup = 1;
8512 if (gsm->pvt->owner) {
8513 gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8515 ast_mutex_unlock(&gsm->pvt->lock); */
8516 break;
8517 case GSM_EVENT_RING:
8518 ast_mutex_lock(&gsm->pvt->lock);
8519 if (!ast_strlen_zero(e->ring.callingnum)) {
8520 strncpy(gsm->pvt->cid_num, e->ring.callingnum, sizeof(gsm->pvt->cid_num) - 1);
8521 } else {
8522 strncpy(gsm->pvt->cid_name, "CID withheld", sizeof(gsm->pvt->cid_name));
8524 if (!ast_strlen_zero(gsm->exten)) {
8525 strncpy(gsm->pvt->exten, gsm->exten, sizeof(gsm->pvt->exten) - 1);
8526 } else {
8527 gsm->pvt->exten[0] = 's';
8528 gsm->pvt->exten[1] = '\0';
8530 c = dahdi_new(gsm->pvt, AST_STATE_RING, 1, SUB_REAL, DAHDI_LAW_ALAW, AST_TRANS_CAP_SPEECH);
8531 if (c) {
8532 if (option_verbose > 2)
8533 ast_verbose(VERBOSE_PREFIX_3 "Ring on channel %d (from %s to %s)\n", e->ring.channel, e->ring.callingnum, gsm->exten);
8534 gsm->pvt->owner = c;
8535 if (ioctl(gsm->pvt->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
8536 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", gsm->pvt->channel, law);
8537 res = dahdi_setlaw(gsm->pvt->subs[SUB_REAL].dfd, law);
8538 res = set_actual_gain(gsm->pvt->subs[SUB_REAL].dfd, 0, gsm->pvt->rxgain, gsm->pvt->txgain, law);
8539 if (res < 0) {
8540 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", gsm->pvt->channel);
8541 // } else {
8542 // ast_log(LOG_NOTICE, "tx gain %f rx gain %f law %d pvt->law %d\n", gsm->pvt->txgain, gsm->pvt->rxgain, law, gsm->pvt->law);
8545 ast_mutex_unlock(&gsm->pvt->lock);
8546 break;
8547 case GSM_EVENT_HANGUP:
8548 ast_verbose(VERBOSE_PREFIX_3 "Got hang up on channel %d\n", e->hangup.channel);
8549 ast_mutex_lock(&gsm->pvt->lock);
8550 gsm->pvt->alreadyhungup = 1;
8551 if (gsm->pvt->owner) {
8552 gsm->pvt->owner->hangupcause = e->hangup.cause;
8553 gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8555 ast_mutex_unlock(&gsm->pvt->lock);
8556 break;
8557 case GSM_EVENT_ERROR:
8558 ast_log(LOG_WARNING, "Got error on channel\n");
8559 ast_mutex_lock(&gsm->pvt->lock);
8560 gsm->pvt->alreadyhungup = 1;
8561 if (gsm->pvt->owner) {
8562 gsm->pvt->owner->hangupcause = e->error.cause;
8563 gsm->pvt->owner->_softhangup |= AST_SOFTHANGUP_DEV;
8565 ast_mutex_unlock(&gsm->pvt->lock);
8566 if (e->error.hard) {
8567 // gsm_poweroff(gsm->modul);
8568 dahdi_reset_span(gsm->span, 8000);
8569 // gsm_restart(gsm->modul, 10000);
8570 } else {
8571 // gsm_poweroff(gsm->modul);
8572 dahdi_reset_span(gsm->span, 8000);
8573 // gsm_restart(gsm->modul, 10000);
8575 break;
8576 case GSM_EVENT_ALERTING:
8577 ast_mutex_lock(&gsm->pvt->lock);
8578 gsm->pvt->subs[SUB_REAL].needringing =1;
8579 ast_mutex_unlock(&gsm->pvt->lock);
8580 break;
8581 case GSM_EVENT_ANSWER:
8582 ast_mutex_lock(&gsm->pvt->lock);
8583 gsm->pvt->dialing = 0;
8584 gsm->pvt->subs[SUB_REAL].needanswer =1;
8585 gsm->pvt->ignoredtmf = 0;
8586 ast_mutex_unlock(&gsm->pvt->lock);
8587 break;
8588 case GSM_EVENT_PIN_REQUIRED:
8589 gsm_send_pin(gsm->modul, gsm->pin);
8590 break;
8591 case GSM_EVENT_SM_RECEIVED:
8592 ast_verbose(VERBOSE_PREFIX_3 "SMS from %s received on span %d. (Text: %s) (PDU: %s)\n", e->sm_received.sender, gsm->span, e->sm_received.text, e->sm_received.pdu);
8593 manager_event(EVENT_FLAG_CALL, "Message received",
8594 "Span: %d\r\n"
8595 "Sender: %s\r\n"
8596 "SMSC: %s\r\n"
8597 "Length: %d\r\n"
8598 "Text: %s\r\n"
8599 "PDU: %s\r\n",
8600 gsm->span,
8601 e->sm_received.sender,
8602 e->sm_received.smsc,
8603 e->sm_received.len,
8604 e->sm_received.text,
8605 e->sm_received.pdu);
8606 break;
8607 default:
8608 ast_log(LOG_WARNING,"!! Unknown GSM event %d !!\n", e->e);
8612 static void *gsm_dchannel(void *vgsm)
8614 struct dahdi_gsm *gsm = vgsm;
8615 gsm_event *e;
8616 struct timeval tv = {0,0}, *next;
8617 fd_set rfds, efds;
8618 int res,x;
8620 if (!gsm) return NULL;
8622 if (!gsm->modul) {
8623 fprintf(stderr, "No gsm_mod\n");
8624 return NULL;
8626 gsm_set_debug(gsm->modul, GSM_DEBUG_NONE);
8627 for (;;) {
8629 /* Run the D-Channel */
8630 FD_ZERO(&rfds);
8631 FD_ZERO(&efds);
8632 FD_SET(gsm->fd, &rfds);
8633 FD_SET(gsm->fd, &efds);
8635 if ((next = gsm_schedule_next(gsm->modul))) {
8636 gettimeofday(&tv, NULL);
8637 tv.tv_sec = next->tv_sec - tv.tv_sec;
8638 tv.tv_usec = next->tv_usec - tv.tv_usec;
8639 if (tv.tv_usec < 0) {
8640 tv.tv_usec += 1000000;
8641 tv.tv_sec -= 1;
8643 if (tv.tv_sec < 0) {
8644 tv.tv_sec = 0;
8645 tv.tv_usec = 0;
8648 res = select(gsm->fd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
8649 e = NULL;
8651 ast_mutex_lock(&gsm->lock);
8652 if (!res) {
8653 e = gsm_schedule_run(gsm->modul);
8654 } else if (res > 0) {
8655 e = gsm_check_event(gsm->modul, 1);
8656 } else if (errno == ELAST) {
8657 res = ioctl(gsm->fd, DAHDI_GETEVENT, &x);
8658 printf("Got Zaptel event: %d\n", x);
8659 } else if (errno != EINTR)
8660 fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
8662 if (!e) {
8663 e = gsm_check_event(gsm->modul, 0);
8666 if (e) {
8667 handle_gsm_event(gsm, e);
8669 ast_mutex_unlock(&gsm->lock);
8671 res = ioctl(gsm->fd, DAHDI_GETEVENT, &x);
8673 if (!res && x) {
8674 switch (x) {
8675 case DAHDI_EVENT_NOALARM:
8676 ast_log(LOG_NOTICE, "Alarm cleared on span %d\n", gsm->span);
8677 usleep(1000);
8678 gsm_restart(gsm->modul, 10000);
8679 break;
8680 case DAHDI_EVENT_ALARM:
8681 ast_log(LOG_NOTICE, "Alarm detected on span %d\n", gsm->span);
8682 break;
8683 default:
8684 fprintf(stderr, "Got event on GSM interface: %d\n", x);
8690 return NULL;
8693 #endif
8695 #ifdef HAVE_PRI
8696 static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
8698 struct dahdi_pvt *p;
8699 p = pri->crvs;
8700 while (p) {
8701 if (p->channel == crv)
8702 return p;
8703 p = p->next;
8705 return NULL;
8708 static int pri_find_tei(struct dahdi_pri *pri, q931_call *c, int tei)
8710 int x=0;
8711 for (x=0;x<pri->numchans;x++) {
8712 if (!pri->pvts[x]) continue;
8713 if ((pri->pvts[x]->tei == tei) && (pri->pvts[x]-> call != c)) {
8714 return x;
8717 return -1;
8720 static struct dahdi_holded_call *pri_get_callonhold(struct dahdi_pri *pri, int cref, int tei) {
8721 struct dahdi_holded_call *zhc = pri->holded_calls;
8722 struct dahdi_holded_call *zhctemp = NULL;
8724 while (zhc) {
8725 if ((zhc->tei == tei) && ((zhc->cref == cref) || (cref == -1))) {
8726 return zhc;
8728 zhctemp = zhc;
8729 if (zhc) zhc = zhc->next;
8731 return NULL;
8734 static int pri_destroy_callonhold(struct dahdi_pri *pri, struct dahdi_holded_call *onhold) {
8735 struct dahdi_holded_call *zhc = pri->holded_calls;
8736 struct dahdi_holded_call *zhctemp = NULL;
8738 while (zhc) {
8739 if (zhc == onhold) {
8740 if (zhctemp) {
8741 zhctemp->next = zhc->next;
8742 zhc = zhctemp;
8743 } else {
8744 pri->holded_calls = zhc->next;
8745 zhc = pri->holded_calls;
8746 zhctemp = NULL;
8749 zhctemp = zhc;
8750 if (zhc) zhc = zhc->next;
8752 if (onhold) {
8753 free(onhold);
8754 onhold = NULL;
8755 return 1;
8757 return 0;
8761 static int pri_find_principle(struct dahdi_pri *pri, int channel)
8763 int x;
8764 int span = PRI_SPAN(channel);
8765 int spanfd;
8766 struct dahdi_params param;
8767 int principle = -1;
8768 int explicit = PRI_EXPLICIT(channel);
8769 channel = PRI_CHANNEL(channel);
8771 if (!explicit) {
8772 spanfd = pri_active_dchan_fd(pri);
8773 if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
8774 return -1;
8775 span = pris[param.spanno - 1].prilogicalspan;
8778 for (x = 0; x < pri->numchans; x++) {
8779 if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
8780 principle = x;
8781 break;
8785 return principle;
8788 static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
8790 int x;
8791 int res = 0;
8792 struct dahdi_pvt *crv;
8793 if (!c) {
8794 if (principle < 0)
8795 return -1;
8796 return principle;
8798 if ((principle > -1) &&
8799 (principle < pri->numchans) &&
8800 (pri->pvts[principle]) &&
8801 (pri->pvts[principle]->call == c))
8802 return principle;
8803 /* First, check for other bearers */
8804 for (x = 0; x < pri->numchans; x++) {
8805 if (!pri->pvts[x])
8806 continue;
8807 if (pri->pvts[x]->call == c) {
8808 /* Found our call */
8809 if (principle != x) {
8810 struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
8812 if (option_verbose > 2)
8813 ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
8814 old->channel, new->channel);
8815 if (new->owner) {
8816 ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
8817 old->channel, new->channel, new->channel);
8818 return -1;
8820 /* Fix it all up now */
8821 new->owner = old->owner;
8822 new->outgoing = old->outgoing;
8823 old->owner = NULL;
8824 if (new->owner) {
8825 ast_string_field_build(new->owner, name,
8826 "Zap/%d:%d-%d", pri->trunkgroup,
8827 new->channel, 1);
8828 new->owner->tech_pvt = new;
8829 new->owner->fds[0] = new->subs[SUB_REAL].dfd;
8830 new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
8831 old->subs[SUB_REAL].owner = NULL;
8832 } else
8833 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);
8834 new->call = old->call;
8835 old->call = NULL;
8837 /* Copy any DSP that may be present */
8838 new->dsp = old->dsp;
8839 new->dsp_features = old->dsp_features;
8840 old->dsp = NULL;
8841 old->dsp_features = 0;
8843 /* Copy faxhandled/digial, alreadyhungup */
8844 new->faxhandled = old->faxhandled;
8845 new->digital = old->digital;
8846 new->alreadyhungup = old->alreadyhungup;
8848 /* Copy law, gains, etc */
8849 new->law = old->law;
8850 if (ioctl(new->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &new->law) == -1)
8851 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", new->channel, new->law);
8852 res = dahdi_setlaw(new->subs[SUB_REAL].dfd, new->law);
8853 if (res < 0)
8854 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", new->channel);
8855 res = set_actual_gain(new->subs[SUB_REAL].dfd, 0, new->rxgain, new->txgain, new->law);
8856 if (res < 0)
8857 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", new->channel);
8859 /* Shutdown old channel */
8860 dahdi_confmute(old, 0);
8861 update_conf(old);
8862 reset_conf(old);
8863 restore_gains(old);
8864 dahdi_disable_ec(old);
8865 dahdi_setlinear(old->subs[SUB_REAL].dfd, 0);
8867 return principle;
8870 /* Now check for a CRV with no bearer */
8871 crv = pri->crvs;
8872 while (crv) {
8873 if (crv->call == c) {
8874 /* This is our match... Perform some basic checks */
8875 if (crv->bearer)
8876 ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
8877 else if (pri->pvts[principle]->owner)
8878 ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
8879 else {
8880 /* Looks good. Drop the pseudo channel now, clear up the assignment, and
8881 wakeup the potential sleeper */
8882 dahdi_close_sub(crv, SUB_REAL);
8883 pri->pvts[principle]->call = crv->call;
8884 pri_assign_bearer(crv, pri, pri->pvts[principle]);
8885 ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
8886 pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
8887 pri->trunkgroup, crv->channel);
8888 wakeup_sub(crv, SUB_REAL, pri);
8890 return principle;
8892 crv = crv->next;
8894 if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
8895 ast_log(LOG_WARNING, "Call specified, but not found?\n");
8897 return -1;
8900 static void *do_idle_thread(void *vchan)
8902 struct ast_channel *chan = vchan;
8903 struct dahdi_pvt *pvt = chan->tech_pvt;
8904 struct ast_frame *f;
8905 char ex[80];
8906 /* Wait up to 30 seconds for an answer */
8907 int newms, ms = 30000;
8908 if (option_verbose > 2)
8909 ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
8910 snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
8911 if (ast_call(chan, ex, 0)) {
8912 ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
8913 ast_hangup(chan);
8914 return NULL;
8916 while ((newms = ast_waitfor(chan, ms)) > 0) {
8917 f = ast_read(chan);
8918 if (!f) {
8919 /* Got hangup */
8920 break;
8922 if (f->frametype == AST_FRAME_CONTROL) {
8923 switch (f->subclass) {
8924 case AST_CONTROL_ANSWER:
8925 /* Launch the PBX */
8926 ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
8927 ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
8928 chan->priority = 1;
8929 if (option_verbose > 3)
8930 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
8931 ast_pbx_run(chan);
8932 /* It's already hungup, return immediately */
8933 return NULL;
8934 case AST_CONTROL_BUSY:
8935 if (option_verbose > 3)
8936 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
8937 break;
8938 case AST_CONTROL_CONGESTION:
8939 if (option_verbose > 3)
8940 ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
8941 break;
8944 ast_frfree(f);
8945 ms = newms;
8947 /* Hangup the channel since nothing happend */
8948 ast_hangup(chan);
8949 return NULL;
8952 #ifndef PRI_RESTART
8953 #error "Upgrade your libpri"
8954 #endif
8955 static void dahdi_pri_message(char *s, int span)
8957 ast_verbose("%d %s", span, s);
8960 static void dahdi_pri_error(char *s, int span)
8962 ast_log(LOG_WARNING, "%d %s", span, s);
8965 #ifdef HAVE_GSMAT
8966 static void dahdi_gsm_message(char *s, int channel)
8968 ast_verbose("GSM %d: %s", channel, s);
8971 static void dahdi_gsm_error(char *s, int channel)
8973 ast_log(LOG_WARNING, "GSM %d: %s", channel, s);
8975 #endif
8977 static int pri_check_restart(struct dahdi_pri *pri)
8979 if ((pri->nodetype != PRI_NETWORK) && (pri->nodetype != PRI_CPE)) {
8980 return 0;
8982 do {
8983 pri->resetpos++;
8984 } while ((pri->resetpos < pri->numchans) &&
8985 (!pri->pvts[pri->resetpos] ||
8986 pri->pvts[pri->resetpos]->call ||
8987 pri->pvts[pri->resetpos]->resetting));
8988 if (pri->resetpos < pri->numchans) {
8989 /* Mark the channel as resetting and restart it */
8990 pri->pvts[pri->resetpos]->resetting = 1;
8991 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
8992 } else {
8993 pri->resetting = 0;
8994 time(&pri->lastreset);
8996 return 0;
8999 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
9001 int x;
9002 int redo;
9003 ast_mutex_unlock(&pri->lock);
9004 ast_mutex_lock(&p->lock);
9005 do {
9006 redo = 0;
9007 for (x = 0; x < 3; x++) {
9008 while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
9009 redo++;
9010 DEADLOCK_AVOIDANCE(&p->lock);
9012 if (p->subs[x].owner) {
9013 ast_queue_hangup(p->subs[x].owner);
9014 ast_mutex_unlock(&p->subs[x].owner->lock);
9017 } while (redo);
9018 ast_mutex_unlock(&p->lock);
9019 ast_mutex_lock(&pri->lock);
9020 return 0;
9023 static char * redirectingreason2str(int redirectingreason)
9025 switch (redirectingreason) {
9026 case 0:
9027 return "UNKNOWN";
9028 case 1:
9029 return "BUSY";
9030 case 2:
9031 return "NO_REPLY";
9032 case 0xF:
9033 return "UNCONDITIONAL";
9034 default:
9035 return "NOREDIRECT";
9039 static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
9041 switch (plan) {
9042 case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
9043 snprintf(buf, size, "%s%s", pri->internationalprefix, number);
9044 break;
9045 case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
9046 snprintf(buf, size, "%s%s", pri->nationalprefix, number);
9047 break;
9048 case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
9049 snprintf(buf, size, "%s%s", pri->localprefix, number);
9050 break;
9051 case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
9052 snprintf(buf, size, "%s%s", pri->privateprefix, number);
9053 break;
9054 case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
9055 snprintf(buf, size, "%s%s", pri->unknownprefix, number);
9056 break;
9057 default: /* other Q.931 dialplan => don't twiddle with callingnum */
9058 snprintf(buf, size, "%s", number);
9059 break;
9063 static int dahdi_setlaw(int dfd, int law)
9065 int res;
9066 res = ioctl(dfd, DAHDI_SETLAW, &law);
9067 if (res)
9068 return res;
9069 return 0;
9071 static void pri_make_callerid(struct dahdi_pri *pri, char *callerid, int callerid_len, char *callingnum, int callingnum_len, int callingplan, int callingpres, int stripmsd) {
9072 if (callingnum && (callingnum_len > stripmsd)) {
9073 callingnum += stripmsd;
9075 switch (callingplan) {
9076 case PRI_INTERNATIONAL_ISDN:
9077 snprintf(callerid, callerid_len, "%s%s", pri->internationalprefix, callingnum);
9078 break;
9079 case PRI_NATIONAL_ISDN:
9080 snprintf(callerid, callerid_len, "%s%s", pri->nationalprefix, callingnum);
9081 break;
9082 case PRI_LOCAL_ISDN:
9083 snprintf(callerid, callerid_len, "%s%s", pri->localprefix, callingnum);
9084 break;
9085 case PRI_PRIVATE:
9086 snprintf(callerid, callerid_len, "%s%s", pri->privateprefix, callingnum);
9087 break;
9088 case PRI_UNKNOWN:
9089 snprintf(callerid, callerid_len, "%s%s", pri->unknownprefix, callingnum);
9090 break;
9091 default:
9092 snprintf(callerid, callerid_len, "%s", callingnum);
9093 break;
9097 static void *pri_dchannel(void *vpri)
9099 struct dahdi_pri *pri = vpri;
9100 pri_event *e;
9101 struct pollfd fds[NUM_DCHANS];
9102 int res;
9103 int chanpos = 0;
9104 int x;
9105 int haveidles;
9106 int activeidles;
9107 int nextidle = -1;
9108 struct ast_channel *c;
9109 struct timeval tv, lowest, *next;
9110 struct timeval lastidle = { 0, 0 };
9111 int doidling=0;
9112 char *cc;
9113 char idlen[80];
9114 struct ast_channel *idle;
9115 pthread_t p;
9116 time_t t;
9117 int i, which=-1;
9118 int numdchans;
9119 int cause=0;
9120 struct dahdi_pvt *crv;
9121 pthread_t threadid;
9122 pthread_attr_t attr;
9123 char ani2str[6];
9124 char plancallingnum[256];
9125 char plancallingani[256];
9126 char calledtonstr[10];
9128 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
9130 gettimeofday(&lastidle, NULL);
9131 if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
9132 /* Need to do idle dialing, check to be sure though */
9133 cc = strchr(pri->idleext, '@');
9134 if (cc) {
9135 *cc = '\0';
9136 cc++;
9137 ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
9138 #if 0
9139 /* Extensions may not be loaded yet */
9140 if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
9141 ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
9142 else
9143 #endif
9144 doidling = 1;
9145 } else
9146 ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
9148 for (;;) {
9149 for (i = 0; i < NUM_DCHANS; i++) {
9150 if (!pri->dchannels[i])
9151 break;
9152 fds[i].fd = pri->fds[i];
9153 fds[i].events = POLLIN | POLLPRI;
9154 fds[i].revents = 0;
9156 numdchans = i;
9157 time(&t);
9158 ast_mutex_lock(&pri->lock);
9159 if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
9160 if (pri->resetting && pri_is_up(pri)) {
9161 if (pri->resetpos < 0)
9162 pri_check_restart(pri);
9163 } else {
9164 if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
9165 pri->resetting = 1;
9166 pri->resetpos = -1;
9170 /* Look for any idle channels if appropriate */
9171 if (doidling && pri_is_up(pri)) {
9172 nextidle = -1;
9173 haveidles = 0;
9174 activeidles = 0;
9175 for (x = pri->numchans; x >= 0; x--) {
9176 if (pri->pvts[x] && !pri->pvts[x]->owner &&
9177 !pri->pvts[x]->call) {
9178 if (haveidles < pri->minunused) {
9179 haveidles++;
9180 } else if (!pri->pvts[x]->resetting) {
9181 nextidle = x;
9182 break;
9184 } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
9185 activeidles++;
9187 if (nextidle > -1) {
9188 if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
9189 /* Don't create a new idle call more than once per second */
9190 snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
9191 idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
9192 if (idle) {
9193 pri->pvts[nextidle]->isidlecall = 1;
9194 if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
9195 ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
9196 dahdi_hangup(idle);
9198 } else
9199 ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
9200 gettimeofday(&lastidle, NULL);
9202 } else if ((haveidles < pri->minunused) &&
9203 (activeidles > pri->minidle)) {
9204 /* Mark something for hangup if there is something
9205 that can be hungup */
9206 for (x = pri->numchans; x >= 0; x--) {
9207 /* find a candidate channel */
9208 if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
9209 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9210 haveidles++;
9211 /* Stop if we have enough idle channels or
9212 can't spare any more active idle ones */
9213 if ((haveidles >= pri->minunused) ||
9214 (activeidles <= pri->minidle))
9215 break;
9220 /* Start with reasonable max */
9221 lowest = ast_tv(60, 0);
9222 for (i = 0; i < NUM_DCHANS; i++) {
9223 /* Find lowest available d-channel */
9224 if (!pri->dchannels[i])
9225 break;
9226 if ((next = pri_schedule_next(pri->dchans[i]))) {
9227 /* We need relative time here */
9228 tv = ast_tvsub(*next, ast_tvnow());
9229 if (tv.tv_sec < 0) {
9230 tv = ast_tv(0,0);
9232 if (doidling || pri->resetting) {
9233 if (tv.tv_sec > 1) {
9234 tv = ast_tv(1, 0);
9236 } else {
9237 if (tv.tv_sec > 60) {
9238 tv = ast_tv(60, 0);
9241 } else if (doidling || pri->resetting) {
9242 /* Make sure we stop at least once per second if we're
9243 monitoring idle channels */
9244 tv = ast_tv(1,0);
9245 } else {
9246 /* Don't poll for more than 60 seconds */
9247 tv = ast_tv(60, 0);
9249 if (!i || ast_tvcmp(tv, lowest) < 0) {
9250 lowest = tv;
9253 ast_mutex_unlock(&pri->lock);
9255 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
9256 pthread_testcancel();
9257 e = NULL;
9258 res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
9259 pthread_testcancel();
9260 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
9262 ast_mutex_lock(&pri->lock);
9263 if (!res) {
9264 for (which = 0; which < NUM_DCHANS; which++) {
9265 if (!pri->dchans[which])
9266 break;
9267 /* Just a timeout, run the scheduler */
9268 e = pri_schedule_run(pri->dchans[which]);
9269 if (e)
9270 break;
9272 } else if (res > -1) {
9273 for (which = 0; which < NUM_DCHANS; which++) {
9274 if (!pri->dchans[which])
9275 break;
9276 if (fds[which].revents & POLLPRI) {
9277 /* Check for an event */
9278 x = 0;
9279 res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
9280 if ((pri->nodetype != BRI_CPE) && (pri->nodetype != BRI_CPE_PTMP)) {
9281 /* dont annoy BRI TE mode users with layer2layer alarms */
9282 if (x)
9283 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);
9285 /* Keep track of alarm state */
9286 if (x == DAHDI_EVENT_ALARM) {
9287 pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
9288 pri_find_dchan(pri);
9289 if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
9290 if (pri->pri) {
9291 for (i=0; i<pri->numchans; i++) {
9292 struct dahdi_pvt *p = pri->pvts[i];
9293 if (p) {
9294 if (p->call) {
9295 if (p->pri && p->pri->pri) {
9296 pri_destroycall(p->pri->pri, p->call);
9297 p->call = NULL;
9298 p->tei = -1;
9299 } else
9300 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
9302 if (p->owner)
9303 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9304 p->inalarm = 1;
9307 pri_shutdown(pri->pri);
9310 } else if (x == DAHDI_EVENT_NOALARM) {
9311 if ((pri->nodetype == BRI_CPE) || (pri->nodetype == BRI_CPE_PTMP)) {
9312 pri->dchanavail[which] |= DCHAN_NOTINALARM;
9313 // pri->dchanavail[which] |= DCHAN_UP;
9314 } else {
9315 pri->dchanavail[which] |= DCHAN_NOTINALARM;
9316 pri_restart(pri->dchans[which]);
9320 if (option_debug)
9321 ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
9322 } else if (fds[which].revents & POLLIN) {
9323 e = pri_check_event(pri->dchans[which]);
9325 if (e)
9326 break;
9328 } else if (errno != EINTR)
9329 ast_log(LOG_WARNING, "pri_event returned error %d (%s) on span %d\n", errno, strerror(errno), pri->span);
9330 if (e) {
9331 if (pri->debug)
9332 pri_dump_event(pri->dchans[which], e);
9334 if (e->e != PRI_EVENT_DCHAN_DOWN) {
9335 if (!(pri->dchanavail[which] & DCHAN_UP)) {
9336 if (option_verbose > 1)
9337 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
9339 pri->dchanavail[which] |= DCHAN_UP;
9340 } else {
9341 if (pri->dchanavail[which] & DCHAN_UP) {
9342 if (option_verbose > 1)
9343 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
9345 pri->dchanavail[which] &= ~DCHAN_UP;
9348 if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
9349 /* Must be an NFAS group that has the secondary dchan active */
9350 pri->pri = pri->dchans[which];
9352 switch (e->e) {
9353 case PRI_EVENT_DCHAN_UP:
9354 if (pri->nodetype == BRI_NETWORK_PTMP) {
9355 if (option_verbose > 3)
9356 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
9357 } else if (pri->nodetype == BRI_CPE_PTMP) {
9358 if (option_verbose > 3)
9359 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
9360 } else {
9361 if (option_verbose > 1)
9362 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
9365 if (!pri->pri) pri_find_dchan(pri);
9367 /* Note presense of D-channel */
9368 time(&pri->lastreset);
9370 /* Restart in 5 seconds */
9371 if (pri->resetinterval > -1) {
9372 pri->lastreset -= pri->resetinterval;
9373 pri->lastreset += 5;
9375 pri->resetting = 0;
9376 /* Take the channels from inalarm condition */
9377 for (i = 0; i < pri->numchans; i++)
9378 if (pri->pvts[i]) {
9379 pri->pvts[i]->inalarm = 0;
9381 break;
9382 case PRI_EVENT_DCHAN_DOWN:
9383 if (pri->nodetype == BRI_NETWORK_PTMP) {
9384 if (option_verbose > 3)
9385 ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down for TEI %d\n", pri_order(which), pri->span, e->gen.tei);
9386 // PTMP BRIs have N dchans, handled by libpri
9387 if (e->gen.tei == 0) break;
9389 pri_find_dchan(pri);
9390 if (!pri_is_up(pri)) {
9391 pri->resetting = 0;
9392 /* Hangup active channels and put them in alarm mode */
9393 for (i = 0; i < pri->numchans; i++) {
9394 struct dahdi_pvt *p = pri->pvts[i];
9395 if (p) {
9396 if ((p->tei == e->gen.tei) || (pri->nodetype != BRI_NETWORK_PTMP)) {
9397 if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
9398 /* T309 is not enabled : hangup calls when alarm occurs */
9399 if (p->call) {
9400 if (p->pri && p->pri->pri) {
9401 pri_hangup(p->pri->pri, p->call, -1); /*! \fixme PRI_CAUSE_INTERWORKING? */
9402 pri_destroycall(p->pri->pri, p->call);
9403 p->call = NULL;
9404 } else
9405 ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
9407 p->tei = -1;
9408 if (p->realcall) {
9409 pri_hangup_all(p->realcall, pri);
9410 } else if (p->owner)
9411 p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9413 p->inalarm = 1;
9418 break;
9419 case PRI_EVENT_RESTART:
9420 if (e->restart.channel > -1) {
9421 chanpos = pri_find_principle(pri, e->restart.channel);
9422 if (chanpos < 0)
9423 ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
9424 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
9425 else {
9426 if (option_verbose > 2)
9427 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n",
9428 PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
9429 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9430 if (pri->pvts[chanpos]->call) {
9431 pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
9432 pri->pvts[chanpos]->call = NULL;
9434 /* Force soft hangup if appropriate */
9435 if (pri->pvts[chanpos]->realcall)
9436 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9437 else if (pri->pvts[chanpos]->owner)
9438 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9439 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9441 } else {
9442 if (option_verbose > 2)
9443 ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
9444 for (x = 0; x < pri->numchans; x++)
9445 if (pri->pvts[x]) {
9446 ast_mutex_lock(&pri->pvts[x]->lock);
9447 if (pri->pvts[x]->call) {
9448 pri_destroycall(pri->pri, pri->pvts[x]->call);
9449 pri->pvts[x]->call = NULL;
9451 if (pri->pvts[x]->realcall)
9452 pri_hangup_all(pri->pvts[x]->realcall, pri);
9453 else if (pri->pvts[x]->owner)
9454 pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9455 ast_mutex_unlock(&pri->pvts[x]->lock);
9458 break;
9459 case PRI_EVENT_KEYPAD_DIGIT:
9460 chanpos = pri_find_principle(pri, e->digit.channel);
9461 if (chanpos < 0) {
9462 ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
9463 PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
9464 } else {
9465 chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
9466 if (chanpos > -1) {
9467 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9468 /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
9469 if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
9470 /* how to do that */
9471 int digitlen = strlen(e->digit.digits);
9472 char digit;
9473 int i;
9474 for (i = 0; i < digitlen; i++) {
9475 digit = e->digit.digits[i];
9477 struct ast_frame f = { AST_FRAME_DTMF, digit, };
9478 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9482 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9485 break;
9487 case PRI_EVENT_INFO_RECEIVED:
9488 chanpos = pri_find_principle(pri, e->ring.channel);
9489 if (chanpos < 0) {
9490 ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
9491 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
9492 } else {
9493 chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
9494 if (chanpos > -1) {
9495 // ast_log(LOG_NOTICE, "INFO received on channel %d/%d span %d\n",
9496 // PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
9497 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9498 /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
9499 if (pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
9500 /* how to do that */
9501 int digitlen = strlen(e->ring.callednum);
9502 char digit;
9503 int i;
9504 for (i = 0; i < digitlen; i++) {
9505 digit = e->ring.callednum[i];
9507 struct ast_frame f = { AST_FRAME_DTMF, digit, };
9508 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9511 if (!pri->overlapdial) {
9512 strncat(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
9513 if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
9514 tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].dfd, -1);
9515 } else {
9516 tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
9520 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9523 break;
9524 case PRI_EVENT_RING:
9525 crv = NULL;
9526 if (e->ring.channel == -1)
9527 /* if no channel specified find one empty */
9528 chanpos = pri_find_empty_chan(pri, 1);
9529 else
9530 chanpos = pri_find_principle(pri, e->ring.channel);
9531 /* if no channel specified find one empty */
9532 if (chanpos < 0) {
9533 /* no channel specified and no free channel. this is a callwating SETUP */
9534 if (e->ring.channel <= 0) {
9535 if (option_verbose > 2)
9536 ast_verbose(VERBOSE_PREFIX_3 "Ignoring callwaiting SETUP on channel %d/%d span %d %d\n", PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span, e->ring.channel);
9537 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_USER_BUSY);
9538 break;
9540 } else {
9541 /* ok, we got a b channel for this call, lock it */
9542 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9543 if (pri->pvts[chanpos]->owner) {
9544 /* safety check, for messed up retransmissions? */
9545 if (pri->pvts[chanpos]->call == e->ring.call) {
9546 ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
9547 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
9548 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9549 chanpos = -1;
9550 break;
9551 } else {
9552 ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
9553 PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
9554 if (pri->pvts[chanpos]->realcall) {
9555 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
9556 } else {
9557 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9558 /* XXX destroy the call here, so we can accept the retransmission as a new call */
9559 pri_destroycall(pri->pri, e->ring.call);
9561 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9562 chanpos = -1;
9563 break;
9566 if (chanpos > -1)
9567 /* everything is ok with the b channel */
9568 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9570 /* actually, we already got a valid channel by now */
9571 if (chanpos > -1) {
9572 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9573 /* dont detect dtmfs before the signalling is done */
9574 disable_dtmf_detect(pri->pvts[chanpos]);
9575 /* this channel is owned by this TEI */
9576 pri->pvts[chanpos]->tei = e->ring.tei;
9577 if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
9578 /* Should be safe to lock CRV AFAIK while bearer is still locked */
9579 crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
9580 if (crv)
9581 ast_mutex_lock(&crv->lock);
9582 if (!crv || crv->owner) {
9583 pri->pvts[chanpos]->call = NULL;
9584 if (crv) {
9585 if (crv->owner)
9586 crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9587 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);
9588 } else
9589 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);
9590 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
9591 if (crv)
9592 ast_mutex_unlock(&crv->lock);
9593 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9594 break;
9597 /* assign call to b channel */
9598 pri->pvts[chanpos]->call = e->ring.call;
9599 apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
9600 if (pri->pvts[chanpos]->use_callerid) {
9601 ast_shrink_phone_number(plancallingnum);
9602 ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
9603 #ifdef PRI_ANI
9604 if (!ast_strlen_zero(e->ring.callingani)) {
9605 apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
9606 ast_shrink_phone_number(plancallingani);
9607 ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
9608 } else {
9609 pri->pvts[chanpos]->cid_ani[0] = '\0';
9611 #endif
9612 ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
9613 pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
9614 } else {
9615 pri->pvts[chanpos]->cid_num[0] = '\0';
9616 pri->pvts[chanpos]->cid_ani[0] = '\0';
9617 pri->pvts[chanpos]->cid_name[0] = '\0';
9618 pri->pvts[chanpos]->cid_ton = 0;
9620 apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
9621 e->ring.redirectingnum, e->ring.callingplanrdnis);
9622 /* get callingpres */
9623 pri->pvts[chanpos]->cid_pres = e->ring.callingpres;
9624 switch (e->ring.callingpres) {
9625 case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
9626 case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
9627 case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
9628 case PRES_PROHIB_NETWORK_NUMBER:
9629 ast_copy_string(pri->pvts[chanpos]->cid_name, pri->withheldcid, sizeof(pri->pvts[chanpos]->cid_name));
9630 break;
9631 case PRES_NUMBER_NOT_AVAILABLE:
9632 ast_copy_string(pri->pvts[chanpos]->cid_name, pri->nocid, sizeof(pri->pvts[chanpos]->cid_name));
9633 break;
9635 /* If immediate=yes go to s|1 */
9636 if (pri->pvts[chanpos]->immediate) {
9637 if (option_verbose > 2)
9638 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
9639 pri->pvts[chanpos]->exten[0] = 's';
9640 pri->pvts[chanpos]->exten[1] = '\0';
9642 else if (ast_strlen_zero(e->ring.callednum)) {
9643 /* called party number is empty */
9644 if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
9645 if (!pri->overlapdial) {
9646 // be able to set digittimeout for BRI phones
9647 pri->pvts[chanpos]->exten[0] = 's';
9648 pri->pvts[chanpos]->exten[1] = '\0';
9649 tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
9650 } else {
9651 pri->pvts[chanpos]->exten[0] = '\0';
9653 } else {
9654 if (pri->nodetype == BRI_CPE) {
9655 /* fix for .at p2p bri lines */
9656 pri->pvts[chanpos]->exten[0] = 's';
9657 pri->pvts[chanpos]->exten[1] = '\0';
9658 } else if (pri->overlapdial) {
9659 pri->pvts[chanpos]->exten[0] = '\0';
9660 } else {
9661 /* Some PRI circuits are set up to send _no_ digits. Handle them as 's'. */
9662 pri->pvts[chanpos]->exten[0] = 's';
9663 pri->pvts[chanpos]->exten[1] = '\0';
9666 /* No number yet, but received "sending complete"? */
9667 if (e->ring.complete) {
9668 if (option_verbose > 2)
9669 ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
9670 pri->pvts[chanpos]->exten[0] = 's';
9671 pri->pvts[chanpos]->exten[1] = '\0';
9673 } else {
9674 /* Get called number */
9675 pri_make_callerid(pri, pri->pvts[chanpos]->dnid, sizeof(pri->pvts[chanpos]->dnid), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
9676 pri_make_callerid(pri, pri->pvts[chanpos]->exten, sizeof(pri->pvts[chanpos]->exten), e->ring.callednum, sizeof(e->ring.callednum), e->ring.calledplan, 0, pri->pvts[chanpos]->stripmsd);
9677 if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
9678 /* if we get the next digit we should stop the dialtone */
9679 if (!pri->overlapdial) {
9680 // with overlapdial=no the exten is always prefixed by "s"
9681 if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten + 1)) {
9682 tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].dfd, -1);
9683 } else {
9684 tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
9686 } else {
9687 if (!ast_ignore_pattern(pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten)) {
9688 tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].dfd, -1);
9689 } else {
9690 tone_zone_play_tone(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
9695 /* Part 3: create channel, setup audio... */
9696 /* Set DNID on all incoming calls -- even immediate */
9697 if (!ast_strlen_zero(e->ring.callednum))
9698 strncpy(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid) - 1);
9699 /* Make sure extension exists (or in overlap dial mode, can exist) */
9700 if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
9701 ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
9702 /* Setup law */
9703 int law;
9704 if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
9705 /* Set to audio mode at this point */
9706 law = 1;
9707 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
9708 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
9710 if (e->ring.layer1 == PRI_LAYER_1_ALAW)
9711 law = DAHDI_LAW_ALAW;
9712 else
9713 law = DAHDI_LAW_MULAW;
9714 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
9715 if (res < 0)
9716 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
9717 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
9718 if (res < 0)
9719 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
9720 if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
9721 if (e->ring.complete || !pri->overlapdial) {
9722 /* Just announce proceeding */
9723 pri->pvts[chanpos]->proceeding = 1;
9724 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
9725 } else {
9726 if (pri->switchtype != PRI_SWITCH_GR303_TMC)
9727 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9728 else
9729 pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9731 } else {
9732 /* BRI_NETWORK | BRI_NETWORK_PTMP */
9733 if (pri->overlapdial || (!strcasecmp(pri->pvts[chanpos]->exten, "s"))) {
9734 /* send a SETUP_ACKNOWLEDGE */
9735 pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9736 } else {
9737 /* send an ALERTING ??? wtf */
9738 // pri_acknowledge(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
9739 pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
9742 /* overlapdial = yes and the extension can be valid */
9743 /* Get the use_callingpres state */
9744 pri->pvts[chanpos]->callingpres = e->ring.callingpres;
9746 /* Start PBX */
9747 if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
9748 /* Release the PRI lock while we create the channel */
9749 ast_mutex_unlock(&pri->lock);
9750 if (crv) {
9751 /* Set bearer and such */
9752 pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
9753 c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9754 if (c && (e->ring.lowlayercompat[0] > 0)) {
9755 memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
9757 pri->pvts[chanpos]->owner = &inuse;
9758 ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
9759 } else {
9760 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
9761 if (c && (e->ring.lowlayercompat[0] > 0)) {
9762 memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
9764 dahdi_enable_ec(pri->pvts[chanpos]); /* XXX rethink */
9767 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9769 if (!ast_strlen_zero(e->ring.callingsubaddr)) {
9770 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
9772 if (!ast_strlen_zero(e->ring.callingnum)) {
9773 char tmpstr[256];
9774 pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
9775 pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
9777 if (!ast_strlen_zero(e->ring.callingani)) {
9778 char tmpstr[256];
9779 pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
9780 pbx_builtin_setvar_helper(c, "PRI_USER_CID", tmpstr);
9782 if (e->ring.ani2 >= 0) {
9783 snprintf(ani2str, 5, "%.2d", e->ring.ani2);
9784 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9787 #ifdef SUPPORT_USERUSER
9788 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9789 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9791 #endif
9793 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9794 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9795 if (e->ring.redirectingreason >= 0)
9796 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9798 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9799 ast_mutex_lock(&pri->lock);
9801 pthread_attr_init(&attr);
9802 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
9803 if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
9804 if (option_verbose > 2)
9805 ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap %s call from '%s' to '%s' on channel %d/%d, span %d\n",
9806 pri->pvts[chanpos]->digital ? "data" : "voice", plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
9807 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9808 } else {
9809 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9810 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9811 if (c)
9812 ast_hangup(c);
9813 else {
9814 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9815 pri->pvts[chanpos]->call = NULL;
9818 pthread_attr_destroy(&attr);
9819 } else {
9820 /* overlapdial = no */
9821 ast_mutex_unlock(&pri->lock);
9822 /* Release PRI lock while we create the channel */
9823 c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
9824 if (c && (e->ring.lowlayercompat[0] > 0)) {
9825 memcpy(c->lowlayercompat, e->ring.lowlayercompat, sizeof(c->lowlayercompat));
9827 if (c) {
9828 char calledtonstr[10];
9830 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9832 if (e->ring.ani2 >= 0) {
9833 snprintf(ani2str, 5, "%d", e->ring.ani2);
9834 pbx_builtin_setvar_helper(c, "ANI2", ani2str);
9837 #ifdef SUPPORT_USERUSER
9838 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9839 pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
9841 #endif
9843 if (e->ring.redirectingreason >= 0)
9844 pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
9846 snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
9847 pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
9849 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9850 ast_mutex_lock(&pri->lock);
9852 if (option_verbose > 2)
9853 ast_verbose(VERBOSE_PREFIX_3 "Accepting %s call from '%s' to '%s' on channel %d/%d, span %d\n",
9854 pri->pvts[chanpos]->digital ? "data" : "voice", e->ring.callingnum, pri->pvts[chanpos]->exten,
9855 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9856 dahdi_enable_ec(pri->pvts[chanpos]);
9857 if(!ast_strlen_zero(e->ring.callingsubaddr)) {
9858 pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
9860 if (!ast_strlen_zero(e->ring.callingnum)) {
9861 char tmpstr[256];
9862 pri_make_callerid(pri, tmpstr, sizeof(tmpstr), e->ring.callingnum, sizeof(e->ring.callingnum), e->ring.callingplan, e->ring.callingpres, 0);
9863 pbx_builtin_setvar_helper(c, "PRI_NETWORK_CID", tmpstr);
9865 if (!ast_strlen_zero(e->ring.callingani)) {
9866 char tmpstr[256];
9867 pri_make_callerid(pri, tmpstr,sizeof(tmpstr), e->ring.callingani, sizeof(e->ring.callingani), e->ring.callingplanuser, e->ring.callingpresuser, 0);
9868 pbx_builtin_setvar_helper(c, "PRI_USER_CID", e->ring.callednum);
9870 if (!ast_strlen_zero(e->ring.useruserinfo)) {
9871 pbx_builtin_setvar_helper(c, "UUI", e->ring.useruserinfo);
9873 } else {
9875 ast_mutex_lock(&pri->lock);
9877 ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
9878 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
9879 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
9880 pri->pvts[chanpos]->call = NULL;
9883 } else {
9884 /* invalid extension */
9885 if (option_verbose > 2)
9886 ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d/%d, span %d\n",
9887 pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
9888 pri->pvts[chanpos]->prioffset, pri->span);
9889 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
9890 pri->pvts[chanpos]->call = NULL;
9891 pri->pvts[chanpos]->exten[0] = '\0';
9893 if (crv)
9894 ast_mutex_unlock(&crv->lock);
9895 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9896 } else {
9897 if (e->ring.flexible)
9898 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
9899 else
9900 pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
9902 break;
9903 case PRI_EVENT_RINGING:
9904 chanpos = pri_find_principle(pri, e->ringing.channel);
9905 if (chanpos < 0) {
9906 ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
9907 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9908 } else {
9909 chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
9910 if (chanpos < 0) {
9911 ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
9912 PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
9913 } else {
9914 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9915 if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
9916 // XXX dahdi_enable_ec(pri->pvts[chanpos]);
9917 pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
9918 pri->pvts[chanpos]->alerting = 1;
9919 } else
9920 ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
9921 #ifdef PRI_PROGRESS_MASK
9922 if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9923 #else
9924 if (e->ringing.progress == 8) {
9925 #endif
9926 /* Now we can do call progress detection */
9927 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9928 /* RINGING detection isn't required because we got ALERTING signal */
9929 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
9930 pri->pvts[chanpos]->dsp_features = 0;
9934 #ifdef SUPPORT_USERUSER
9935 if (!ast_strlen_zero(e->ringing.useruserinfo)) {
9936 struct ast_channel *owner = pri->pvts[chanpos]->owner;
9937 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9938 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
9939 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9941 #endif
9943 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
9946 break;
9947 case PRI_EVENT_PROGRESS:
9948 /* Get chan value if e->e is not PRI_EVENT_RINGING */
9949 chanpos = pri_find_principle(pri, e->proceeding.channel);
9950 if (chanpos > -1) {
9951 if ((pri->pvts[chanpos]->priindication_oob == 2) && (e->proceeding.cause == PRI_CAUSE_USER_BUSY)) {
9952 /* received PROGRESS with cause BUSY, no inband callprogress wanted => hang up! */
9953 if (pri->pvts[chanpos]->owner) {
9954 pri->pvts[chanpos]->owner->hangupcause = AST_CAUSE_USER_BUSY;
9955 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
9957 } else {
9958 #ifdef PRI_PROGRESS_MASK
9959 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
9960 #else
9961 if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
9962 #endif
9963 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
9965 if (e->proceeding.cause > -1) {
9966 if (option_verbose > 2)
9967 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
9969 /* Work around broken, out of spec USER_BUSY cause in a progress message */
9970 if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
9971 if (pri->pvts[chanpos]->owner) {
9972 if (option_verbose > 2)
9973 ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
9975 pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
9976 f.subclass = AST_CONTROL_BUSY;
9981 ast_mutex_lock(&pri->pvts[chanpos]->lock);
9982 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
9983 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
9984 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
9985 #ifdef PRI_PROGRESS_MASK
9986 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
9987 #else
9988 if (e->proceeding.progress == 8) {
9989 #endif
9990 /* Now we can do call progress detection */
9991 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
9992 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
9993 pri->pvts[chanpos]->dsp_features = 0;
9996 pri->pvts[chanpos]->progress = 1;
9997 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10000 break;
10001 case PRI_EVENT_PROCEEDING:
10002 chanpos = pri_find_principle(pri, e->proceeding.channel);
10003 if (chanpos > -1) {
10004 chanpos = pri_fixup_principle(pri, chanpos, e->proceeding.call);
10005 if (chanpos < 0) {
10006 ast_log(LOG_WARNING, "Received PROCEEDING on channel %d/%d not in use on span %d\n",
10007 PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), pri->span);
10008 chanpos = -1;
10009 } else {
10010 if (!pri->pvts[chanpos]->proceeding) {
10011 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10013 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10014 ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
10015 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
10016 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10017 #ifdef PRI_PROGRESS_MASK
10018 if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
10019 #else
10020 if (e->proceeding.progress == 8) {
10021 #endif
10022 /* Now we can do call progress detection */
10023 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10024 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10025 pri->pvts[chanpos]->dsp_features = 0;
10027 /* Bring voice path up */
10028 f.subclass = AST_CONTROL_PROGRESS;
10029 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10031 pri->pvts[chanpos]->proceeding = 1;
10032 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10035 break;
10036 case PRI_EVENT_FACNAME:
10037 chanpos = pri_find_principle(pri, e->facname.channel);
10038 if (chanpos < 0) {
10039 ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
10040 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10041 } else {
10042 chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
10043 if (chanpos < 0) {
10044 ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
10045 PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
10046 } else {
10047 /* Re-use *69 field for PRI */
10048 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10049 ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
10050 ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
10051 pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
10052 dahdi_enable_ec(pri->pvts[chanpos]);
10053 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10056 break;
10057 case PRI_EVENT_SUSPEND_REQ:
10058 if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
10059 pri_suspend_reject(pri->pri, e->suspend_req.call, "");
10060 break;
10062 chanpos = pri_find_principle(pri, e->suspend_req.channel);
10063 if (chanpos < 0) {
10064 ast_log(LOG_WARNING, "Suspend requested on unconfigured channel %d span %d\n", chanpos, pri->span);
10065 chanpos = -1;
10068 if (chanpos > -1) {
10069 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10070 if (pri->pvts[chanpos]->owner) {
10071 if (ast_bridged_channel(pri->pvts[chanpos]->owner)) {
10072 struct dahdi_suspended_call *zpc;
10073 char tmpstr[256];
10074 zpc = malloc(sizeof(struct dahdi_suspended_call));
10075 if (!zpc) {
10076 ast_log(LOG_ERROR, "unable to malloc dahdi_suspended_call\n");
10077 break;
10079 strncpy(zpc->msn, pri->pvts[chanpos]->cid_num, sizeof(zpc->msn));
10080 strncpy(zpc->callid, e->suspend_req.callid, sizeof(zpc->callid));
10081 ast_masq_park_call(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, 0, &zpc->parked_at);
10082 zpc->next = pri->suspended_calls;
10083 pri->suspended_calls = zpc;
10084 snprintf(tmpstr, sizeof(tmpstr), "Parked at %d", zpc->parked_at);
10085 pri_suspend_acknowledge(pri->pri, e->suspend_req.call,tmpstr);
10086 pri->pvts[chanpos]->call = NULL;
10087 pri->pvts[chanpos]->tei = -1;
10088 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10089 } else {
10090 pri_suspend_reject(pri->pri, e->suspend_req.call, "cant park a non-bridge");
10091 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10092 break;
10094 } else {
10095 pri_suspend_reject(pri->pri, e->suspend_req.call, "");
10097 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10099 break;
10100 case PRI_EVENT_RESUME_REQ:
10101 if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
10102 break;
10104 chanpos = pri_find_empty_chan(pri, 1);
10105 if (chanpos < 0) {
10106 pri_resume_reject(pri->pri, e->resume_req.call,"All channels busy");
10107 ast_log(LOG_WARNING, "Resume requested on odd channel number %d span %d\n", chanpos, pri->span);
10108 chanpos = -1;
10109 } else if (!pri->pvts[chanpos]) {
10110 pri_resume_reject(pri->pri, e->resume_req.call,"General protection fault in module 0x0BRI");
10111 chanpos = -1;
10114 if (chanpos > -1) {
10115 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10116 if (!pri->pvts[chanpos]->owner) {
10117 struct dahdi_suspended_call *zpc, *zpcl;
10118 int unparked=0;
10119 char extenstr[255], temp[255];
10120 zpc = NULL;
10121 zpcl = pri->suspended_calls;
10122 while (zpcl) {
10123 // ast_log(LOG_NOTICE, "zpc->parked_at %d zpcl->callid %s\n",zpcl->parked_at, zpcl->callid);
10124 if (((strlen(zpcl->callid) == 0) && (strlen(e->resume_req.callid)==0)) || (!strcmp(zpcl->callid,e->resume_req.callid))) {
10125 int law;
10126 // found a parked call
10127 snprintf(extenstr, sizeof(extenstr), "%d", zpcl->parked_at);
10128 strncpy(pri->pvts[chanpos]->exten, extenstr, sizeof(pri->pvts[chanpos]->exten));
10129 // strncpy(pri->pvts[chanpos]->context, ast_parking_con(), sizeof(pri->pvts[chanpos]->context));
10130 pri->pvts[chanpos]->call = e->resume_req.call;
10131 law = 1;
10132 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10133 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
10134 // uhh ohh...what shall we do without the bearer cap???
10135 law = DAHDI_LAW_ALAW;
10136 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10137 if (res < 0)
10138 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
10139 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10140 if (res < 0)
10141 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
10142 /* Start PBX */
10143 c = dahdi_new(pri->pvts[chanpos], AST_STATE_UP, 1, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
10144 if (c) {
10145 pri->pvts[chanpos]->owner = c;
10146 pri->pvts[chanpos]->call = e->resume_req.call;
10147 dahdi_enable_ec(pri->pvts[chanpos]);
10148 dahdi_train_ec(pri->pvts[chanpos]);
10149 } else {
10150 ast_log(LOG_ERROR, "unable to start pbx\n");
10153 if (zpc) {
10154 zpc->next = zpcl->next;
10155 free(zpcl);
10156 zpcl = zpc->next;
10157 } else {
10158 // remove head
10159 pri->suspended_calls = zpcl->next;
10160 free(zpcl);
10161 zpcl = pri->suspended_calls;
10162 zpc = NULL;
10164 unparked = 1;
10165 snprintf(temp, sizeof(temp), "Unparked %s", extenstr);
10166 pri_resume_acknowledge(pri->pri, e->resume_req.call, chanpos + 1, temp);
10167 break;
10169 zpc = zpcl;
10170 if (zpcl) zpcl = zpcl->next;
10172 if (!unparked)
10173 pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
10174 } else {
10175 pri_resume_reject(pri->pri, e->resume_req.call,"No suspended call to unpark!");
10177 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10179 break;
10180 case PRI_EVENT_HOLD_REQ:
10181 if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
10182 pri_hold_reject(pri->pri, e->hold_req.call);
10183 break;
10185 chanpos = pri_find_principle(pri, e->hold_req.channel);
10186 if (chanpos < 0) {
10187 ast_log(LOG_WARNING, "Hold requested on unconfigured channel %d span %d\n", chanpos, pri->span);
10188 chanpos = -1;
10190 if (chanpos > -1) {
10191 // ast_log(LOG_NOTICE, "Hold request for channel number %d span %d\n", chanpos, pri->span);
10192 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10193 if (pri->pvts[chanpos]->owner) {
10194 struct dahdi_pvt *p = pri->pvts[chanpos];
10195 struct dahdi_holded_call *zhc;
10196 int holdacked=0;
10198 // ast_log(LOG_NOTICE,"HOLD request from channel %s tei %d\n",p->owner->name, e->hold_req.tei);
10199 if (ast_bridged_channel(p->owner)) {
10200 zhc = malloc(sizeof(struct dahdi_holded_call));
10201 if (!zhc) {
10202 ast_log(LOG_ERROR, "unable to malloc dahdi_holded_call\n");
10203 break;
10205 memset(zhc, 0, sizeof(zhc));
10206 strncpy(zhc->msn, pri->pvts[chanpos]->cid_num, sizeof(zhc->msn));
10207 strncpy(zhc->uniqueid, ast_bridged_channel(p->owner)->uniqueid, sizeof(zhc->uniqueid));
10208 zhc->tei = e->hold_req.tei;
10209 zhc->cref = e->hold_req.cref;
10210 zhc->call = e->hold_req.call;
10211 zhc->channel = p->owner;
10212 zhc->alreadyhungup = 0;
10213 zhc->bridge = ast_bridged_channel(p->owner);
10214 zhc->next = pri->holded_calls;
10215 pri->holded_calls = zhc;
10217 /* put channel on hold */
10218 ast_masq_hold_call(ast_bridged_channel(p->owner), p->owner);
10220 pri_hold_acknowledge(pri->pri, e->hold_req.call);
10221 holdacked = 1;
10222 p->call = NULL; // free the bchannel withouth destroying the call
10223 p->tei = -1;
10224 } else {
10225 // cant hold a non-bridge,...yet
10227 // make a fake channel
10229 // masquerade
10231 // put on hold
10232 pri_hold_reject(pri->pri, e->hold_req.call);
10234 } else {
10235 pri_hold_reject(pri->pri, e->hold_req.call);
10237 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10238 } else {
10239 pri_hold_reject(pri->pri, e->hold_req.call);
10241 break;
10242 case PRI_EVENT_RETRIEVE_REQ:
10243 if ((pri->nodetype != BRI_NETWORK_PTMP) && (pri->nodetype != BRI_NETWORK)) {
10244 pri_retrieve_reject(pri->pri, e->retrieve_req.call);
10245 break;
10247 chanpos = pri_find_empty_chan(pri, 1);
10248 if (chanpos < 0) {
10249 pri_retrieve_reject(pri->pri, e->retrieve_req.call);
10250 ast_log(LOG_WARNING, "Retrieve requested on odd channel number %d span %d\n", chanpos, pri->span);
10251 chanpos = -1;
10252 break;
10253 } else if (!pri->pvts[chanpos]) {
10254 ast_log(LOG_WARNING, "Retrieve requested on unconfigured channel number %d span %d\n", chanpos, pri->span);
10255 pri_retrieve_reject(pri->pri, e->retrieve_req.call);
10256 chanpos = -1;
10257 break;
10259 if (chanpos > -1) {
10260 struct dahdi_holded_call *onhold = NULL;
10261 int retrieved = 0;
10262 int res = -1;
10263 struct app_tmp *tmp;
10264 pthread_attr_t attr;
10265 int law;
10267 onhold = pri_get_callonhold(pri, e->retrieve_req.cref, e->retrieve_req.tei);
10269 if (!onhold) {
10270 pri_retrieve_reject(pri->pri, e->retrieve_req.call);
10271 break;
10273 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10274 // found a parked call
10275 law = 1;
10276 if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
10277 ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]), law);
10278 // uhh ohh...what shall we do without the bearer cap???
10279 law = DAHDI_LAW_ALAW;
10280 res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
10281 if (res < 0)
10282 ast_log(LOG_WARNING, "Unable to set law on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
10283 res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
10284 if (res < 0)
10285 ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", PVT_TO_CHANNEL(pri->pvts[chanpos]));
10286 /* Start PBX */
10287 c = dahdi_new(pri->pvts[chanpos], AST_STATE_UP, 0, SUB_REAL, law, PRI_TRANS_CAP_SPEECH);
10288 if (c) {
10289 pri->pvts[chanpos]->owner = c;
10290 pri->pvts[chanpos]->outgoing = 1; /* for not sending proceedings... */
10291 pri->pvts[chanpos]->call = e->retrieve_req.call;
10292 pri->pvts[chanpos]->tei = e->retrieve_req.tei;
10293 dahdi_enable_ec(pri->pvts[chanpos]);
10294 dahdi_train_ec(pri->pvts[chanpos]);
10295 } else {
10296 ast_log(LOG_ERROR, "unable to start pbx\n");
10299 retrieved = 1;
10300 // ast_log(LOG_NOTICE, "sending RETRIEVE ACK on channel %d, span %d for tei %d cref %d\n",chanpos,pri->span, e->retrieve_req.tei, e->retrieve_req.cref);
10301 pri_retrieve_acknowledge(pri->pri, e->retrieve_req.call, chanpos + 1);
10303 // the magic begins here: ....
10304 tmp = malloc(sizeof(struct app_tmp));
10305 if (tmp) {
10306 memset(tmp, 0, sizeof(struct app_tmp));
10307 strncpy(tmp->app, "holdedcall", sizeof(tmp->app) - 1);
10308 strncpy(tmp->data, onhold->uniqueid, sizeof(tmp->data) - 1);
10309 tmp->chan = c;
10311 pri_destroy_callonhold(pri, onhold);
10312 onhold = NULL;
10314 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10315 pthread_attr_init(&attr);
10316 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
10317 if (ast_pthread_create(&tmp->t, &attr, ast_pbx_run_app, tmp)) {
10318 ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", c->name, strerror(errno));
10319 free(tmp);
10320 ast_hangup(c);
10321 retrieved = 0;
10324 if (!retrieved) {
10325 pri_retrieve_reject(pri->pri, e->retrieve_req.call);
10328 break;
10329 case PRI_EVENT_DISPLAY_RECEIVED:
10330 ast_log(LOG_NOTICE, "DISPLAY IE: [ %s ] received\n",e->display.text);
10331 chanpos = pri_find_principle(pri, e->display.channel);
10332 if (chanpos < 0) {
10333 ast_log(LOG_WARNING, "odd channel number %d span %d\n", chanpos, pri->span);
10334 chanpos = -1;
10336 if (chanpos > -1) {
10337 if (pri->pvts[chanpos]->owner) {
10338 // ast_sendtext(pri->pvt[chanpos]->owner, e->display.text);
10341 break;
10342 case PRI_EVENT_ANSWER:
10343 chanpos = pri_find_principle(pri, e->answer.channel);
10344 if (chanpos < 0) {
10345 ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
10346 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10347 } else {
10348 chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
10349 if (chanpos < 0) {
10350 ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
10351 PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
10352 } else {
10353 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10354 pri->pvts[chanpos]->tei = e->answer.tei;
10355 /* Now we can do call progress detection */
10357 /* We changed this so it turns on the DSP no matter what... progress or no progress.
10358 * By this time, we need DTMF detection and other features that were previously disabled
10359 * -- Matt F */
10360 if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
10361 ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
10362 pri->pvts[chanpos]->dsp_features = 0;
10364 if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
10365 ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
10366 x = DAHDI_START;
10367 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
10368 if (res < 0) {
10369 if (errno != EINPROGRESS) {
10370 ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
10373 } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
10374 pri->pvts[chanpos]->dialing = 1;
10375 /* Send any "w" waited stuff */
10376 res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
10377 if (res < 0) {
10378 ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
10379 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10380 } else
10381 ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
10382 pri->pvts[chanpos]->dop.dialstr[0] = '\0';
10383 } else if (pri->pvts[chanpos]->confirmanswer) {
10384 ast_log(LOG_DEBUG, "Waiting for answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
10385 enable_dtmf_detect(pri->pvts[chanpos]);
10386 } else {
10387 pri->pvts[chanpos]->dialing = 0;
10388 pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
10389 /* Enable echo cancellation if it's not on already */
10390 dahdi_enable_ec(pri->pvts[chanpos]);
10391 dahdi_train_ec(pri->pvts[chanpos]);
10392 /* stop ignoring inband dtmf */
10393 enable_dtmf_detect(pri->pvts[chanpos]);
10396 #ifdef SUPPORT_USERUSER
10397 if (!ast_strlen_zero(e->answer.useruserinfo)) {
10398 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10399 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10400 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
10401 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10403 #endif
10405 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10408 break;
10409 case PRI_EVENT_HANGUP:
10410 chanpos = pri_find_principle(pri, e->hangup.channel);
10411 if (chanpos < 0) {
10412 ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
10413 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10414 } else {
10415 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10416 if (chanpos > -1) {
10417 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10418 if (!pri->pvts[chanpos]->alreadyhungup) {
10419 /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
10420 pri->pvts[chanpos]->alreadyhungup = 1;
10421 if (pri->pvts[chanpos]->realcall)
10422 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10423 else if (pri->pvts[chanpos]->owner) {
10424 /* Queue a BUSY instead of a hangup if our cause is appropriate */
10425 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10426 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
10427 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10428 else {
10429 switch (e->hangup.cause) {
10430 case PRI_CAUSE_USER_BUSY:
10431 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10432 break;
10433 case PRI_CAUSE_CALL_REJECTED:
10434 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10435 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10436 case PRI_CAUSE_SWITCH_CONGESTION:
10437 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10438 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10439 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10440 break;
10441 default:
10442 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10446 if (option_verbose > 2)
10447 ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
10448 pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
10449 } else {
10450 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10451 pri->pvts[chanpos]->call = NULL;
10452 pri->pvts[chanpos]->tei = -1;
10454 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10455 if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
10456 if (option_verbose > 2)
10457 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
10458 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10459 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10460 pri->pvts[chanpos]->resetting = 1;
10463 handle_aoc_e(pri, e, chanpos);
10465 #ifdef SUPPORT_USERUSER
10466 if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
10467 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10468 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10469 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10470 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10472 #endif
10474 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10475 } else {
10476 struct dahdi_holded_call *onhold = NULL;
10477 /* check calls on hold */
10478 onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
10480 if (onhold) {
10481 // ast_log(LOG_NOTICE, "hangup, found cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
10482 pri_hangup(pri->pri, onhold->call, e->hangup.cause);
10483 pri_destroy_callonhold(pri, onhold);
10484 onhold = NULL;
10485 } else {
10486 ast_log(LOG_NOTICE, "Hangup, did not find cref %d, tei %d\n",e->hangup.cref, e->hangup.tei);
10487 ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
10488 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10492 break;
10493 #ifndef PRI_EVENT_HANGUP_REQ
10494 #error please update libpri
10495 #endif
10496 case PRI_EVENT_HANGUP_REQ:
10497 chanpos = pri_find_principle(pri, e->hangup.channel);
10498 if (chanpos < 0) {
10499 if (pri->nodetype == BRI_NETWORK_PTMP) {
10500 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
10501 } else {
10502 ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
10503 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10505 } else if ((pri->pvts[chanpos]->priindication_oob != 2) || (!e->hangup.inband_progress) || (!pri->pvts[chanpos]->outgoing)) {
10506 /* dont hang up if we want to hear inband call progress */
10507 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10508 if (chanpos > -1) {
10509 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10510 if (pri->pvts[chanpos]->realcall)
10511 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10512 else if (pri->pvts[chanpos]->owner) {
10513 char tmpstr[256];
10514 snprintf(tmpstr, sizeof(tmpstr), "%d", e->hangup.cause);
10515 pbx_builtin_setvar_helper(pri->pvts[chanpos]->owner, "PRI_CAUSE", tmpstr);
10516 pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
10517 if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
10518 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10519 else {
10520 switch (e->hangup.cause) {
10521 case PRI_CAUSE_USER_BUSY:
10522 pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
10523 break;
10524 case PRI_CAUSE_CALL_REJECTED:
10525 case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
10526 case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
10527 case PRI_CAUSE_SWITCH_CONGESTION:
10528 case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
10529 case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
10530 pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
10531 break;
10532 default:
10533 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10536 if (option_verbose > 2)
10537 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);
10538 handle_aoc_e(pri, e, chanpos);
10539 } else {
10540 pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
10541 pri->pvts[chanpos]->call = NULL;
10542 pri->pvts[chanpos]->tei = -1;
10544 if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
10545 if ((pri->nodetype != BRI_CPE_PTMP) && (pri->nodetype != BRI_NETWORK_PTMP)) {
10546 if (option_verbose > 2)
10547 ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n",
10548 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10549 pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
10550 pri->pvts[chanpos]->resetting = 1;
10554 #ifdef SUPPORT_USERUSER
10555 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
10556 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10557 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10558 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10559 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10561 #endif
10563 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10564 } else {
10565 if (pri->nodetype != BRI_NETWORK_PTMP) {
10566 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);
10567 } else {
10568 // check holded_calls!!!
10569 struct dahdi_holded_call *onhold = NULL;
10571 onhold = pri_get_callonhold(pri, e->hangup.cref, e->hangup.tei);
10573 if (onhold) {
10574 pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
10575 ast_retrieve_call_to_death(onhold->uniqueid);
10576 pri_destroy_callonhold(pri, onhold);
10577 onhold = NULL;
10578 } else {
10579 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);
10584 if ((chanpos > -1) && (pri->pvts[chanpos]->owner) && (pri->pvts[chanpos]->priindication_oob == 2) && (e->hangup.inband_progress) && (pri->pvts[chanpos]->outgoing)) {
10585 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10586 handle_aoc_e(pri, e, chanpos);
10587 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10589 break;
10590 case PRI_EVENT_HANGUP_ACK:
10591 chanpos = pri_find_principle(pri, e->hangup.channel);
10592 if (chanpos < 0) {
10593 ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
10594 PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
10595 } else {
10596 chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
10597 if (chanpos > -1) {
10598 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10599 pri->pvts[chanpos]->call = NULL;
10600 pri->pvts[chanpos]->tei = -1;
10601 pri->pvts[chanpos]->resetting = 0;
10602 if (pri->pvts[chanpos]->owner) {
10603 if (option_verbose > 2)
10604 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);
10607 #ifdef SUPPORT_USERUSER
10608 if (!ast_strlen_zero(e->hangup.useruserinfo)) {
10609 struct ast_channel *owner = pri->pvts[chanpos]->owner;
10610 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10611 pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
10612 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10614 #endif
10616 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10621 break;
10622 case PRI_EVENT_CONFIG_ERR:
10623 ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
10624 break;
10625 case PRI_EVENT_RESTART_ACK:
10626 chanpos = pri_find_principle(pri, e->restartack.channel);
10627 if (chanpos < 0) {
10628 /* Sometime switches (e.g. I421 / British Telecom) don't give us the
10629 channel number, so we have to figure it out... This must be why
10630 everybody resets exactly a channel at a time. */
10631 for (x = 0; x < pri->numchans; x++) {
10632 if (pri->pvts[x] && pri->pvts[x]->resetting) {
10633 chanpos = x;
10634 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10635 ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
10636 pri->pvts[chanpos]->prioffset, pri->span);
10637 if (pri->pvts[chanpos]->realcall)
10638 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10639 else if (pri->pvts[chanpos]->owner) {
10640 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
10641 pri->pvts[chanpos]->prioffset, pri->span);
10642 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10644 pri->pvts[chanpos]->resetting = 0;
10645 if (option_verbose > 2)
10646 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
10647 pri->pvts[chanpos]->prioffset, pri->span);
10648 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10649 if (pri->resetting)
10650 pri_check_restart(pri);
10651 break;
10654 if (chanpos < 0) {
10655 ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
10656 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
10658 } else {
10659 if (pri->pvts[chanpos]) {
10660 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10661 if (pri->pvts[chanpos]->realcall)
10662 pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
10663 else if (pri->pvts[chanpos]->owner) {
10664 ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
10665 PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
10666 pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10668 pri->pvts[chanpos]->resetting = 0;
10669 if (option_verbose > 2)
10670 ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
10671 pri->pvts[chanpos]->prioffset, pri->span);
10672 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10673 if (pri->resetting)
10674 pri_check_restart(pri);
10677 break;
10678 case PRI_EVENT_SETUP_ACK:
10679 chanpos = pri_find_principle(pri, e->setup_ack.channel);
10680 if (chanpos < 0) {
10681 ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
10682 PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
10683 } else {
10684 chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
10685 if (chanpos > -1) {
10686 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10687 pri->pvts[chanpos]->setup_ack = 1;
10688 /* Send any queued digits */
10689 for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
10690 ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
10691 pri_information(pri->pri, pri->pvts[chanpos]->call,
10692 pri->pvts[chanpos]->dialdest[x]);
10694 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10695 } else
10696 ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
10698 break;
10699 case PRI_EVENT_NOTIFY:
10700 chanpos = pri_find_principle(pri, e->notify.channel);
10701 if (chanpos < 0) {
10702 ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
10703 PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
10704 } else {
10705 struct ast_frame f = { AST_FRAME_CONTROL, };
10706 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10707 switch (e->notify.info) {
10708 case PRI_NOTIFY_REMOTE_HOLD:
10709 if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
10710 ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on NETWORK channel. Starting MoH\n");
10711 ast_moh_start(ast_bridged_channel(pri->pvts[chanpos]->owner), NULL, pri->pvts[chanpos]->mohinterpret);
10712 } else {
10713 ast_log(LOG_DEBUG, "Received REMOTE_HOLD notification on CPE channel. Not Starting MoH\n");
10715 f.subclass = AST_CONTROL_HOLD;
10716 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10717 break;
10718 case PRI_NOTIFY_REMOTE_RETRIEVAL:
10719 if ((pri->nodetype == BRI_NETWORK_PTMP) || (pri->nodetype == BRI_NETWORK)) {
10720 ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on NETWORK channel. Stopping MoH\n");
10721 ast_moh_stop(ast_bridged_channel(pri->pvts[chanpos]->owner));
10722 } else {
10723 ast_log(LOG_DEBUG, "Received REMOTE_RETRIEVAL notification on CPE channel.\n");
10725 f.subclass = AST_CONTROL_UNHOLD;
10726 dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
10727 break;
10729 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10731 break;
10732 case PRI_EVENT_FACILITY:
10733 if (e->facility.operation == 0x06) {
10734 struct ast_channel *chan = NULL;
10735 struct dahdi_holded_call *onhold = NULL;
10736 if (option_verbose > 2) {
10737 ast_verbose(VERBOSE_PREFIX_3 "ECT requested by TEI %d for cref %d\n", e->facility.tei, e->facility.cref);
10739 /* search for cref/tei in held calls */
10740 onhold = pri_get_callonhold(pri, e->facility.cref, e->facility.tei);
10741 if (onhold) {
10742 chan = ast_get_holded_call(onhold->uniqueid);
10743 onhold->alreadyhungup = 1;
10744 onhold = NULL;
10745 if (!chan) {
10746 /* hang up */
10747 pri_hangup(pri->pri, e->facility.call, PRI_CAUSE_NORMAL_CLEARING);
10748 break;
10750 } else {
10751 /* unknown cref/tei */
10752 ast_log(LOG_WARNING, "did not find call on hold for cref %d tei %d\n", e->facility.tei, e->facility.cref);
10753 /* hang up */
10754 pri_hangup(pri->pri, e->facility.call, PRI_CAUSE_NORMAL_CLEARING);
10755 break;
10758 /* find an active call for the same tei */
10759 chanpos = pri_find_tei(pri, e->facility.call, e->facility.tei);
10760 if (chanpos < 0) {
10761 /* did not find active call, hangup call on hold */
10762 if (chan) {
10763 ast_hangup(chan);
10764 chan = NULL;
10766 } else {
10767 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10768 /* transfer */
10769 if (pri->pvts[chanpos]->owner) {
10770 if (option_verbose > 3) {
10771 ast_verbose(VERBOSE_PREFIX_3 "ECT: found %s on channel %d for tei %d\n", pri->pvts[chanpos]->owner->name ,chanpos, e->facility.tei);
10773 /* pass callprogress if the channel is not up yet */
10774 if (pri->pvts[chanpos]->owner->_state == AST_STATE_RINGING) {
10775 ast_indicate(chan, AST_CONTROL_RINGING);
10777 /* unlock the channel we removed from hold */
10778 ast_mutex_unlock(&chan->lock);
10779 if (ast_channel_masquerade(pri->pvts[chanpos]->owner, chan)) {
10780 ast_log(LOG_WARNING, "unable to masquerade\n");
10781 } else {
10782 /* beware of zombies !!! */
10783 ast_set_flag(chan, AST_FLAG_ZOMBIE);
10784 // chan->zombie = 1;
10787 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10789 /* disconnect */
10790 pri_hangup(pri->pri, e->facility.call, PRI_CAUSE_NORMAL_CLEARING);
10791 } else if (e->facility.operation == 0x0D) {
10792 ast_log(LOG_NOTICE, "call deflection to %s requested.\n", e->facility.forwardnum);
10793 ast_mutex_lock(&pri->pvts[chanpos]->lock);
10794 /* transfer */
10795 if (pri->pvts[chanpos]->owner) {
10796 ast_string_field_build(pri->pvts[chanpos]->owner, call_forward,
10797 "Local/%s@%s", e->facility.forwardnum,
10798 pri->pvts[chanpos]->owner->context);
10800 ast_mutex_unlock(&pri->pvts[chanpos]->lock);
10801 } else {
10802 ast_log(LOG_WARNING, "Unknown facility operation %#x requested.\n", e->facility.operation);
10804 break;
10805 default:
10806 ast_log(LOG_DEBUG, "Event: %d\n", e->e);
10809 ast_mutex_unlock(&pri->lock);
10811 /* Never reached */
10812 return NULL;
10815 static int start_pri(struct dahdi_pri *pri)
10817 int res, x;
10818 struct dahdi_params p;
10819 struct dahdi_bufferinfo bi;
10820 struct dahdi_spaninfo si;
10821 int i;
10823 for (i = 0; i < NUM_DCHANS; i++) {
10824 if (!pri->dchannels[i])
10825 break;
10826 #ifdef HAVE_ZAPTEL
10827 pri->fds[i] = open("/dev/zap/channel", O_RDWR, 0600);
10828 #else
10829 pri->fds[i] = open("/dev/dahdi/channel", O_RDWR, 0600);
10830 #endif
10831 x = pri->dchannels[i];
10832 if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
10833 ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
10834 return -1;
10836 res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
10837 if (res) {
10838 dahdi_close_pri_fd(pri, i);
10839 ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
10840 return -1;
10842 if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
10843 dahdi_close_pri_fd(pri, i);
10844 ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode. See /etc/dahdi/system.conf\n", x);
10845 return -1;
10847 memset(&si, 0, sizeof(si));
10848 res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
10849 if (res) {
10850 dahdi_close_pri_fd(pri, i);
10851 ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
10853 if (!si.alarms)
10854 pri->dchanavail[i] |= DCHAN_NOTINALARM;
10855 else
10856 pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
10857 bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
10858 bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
10859 bi.numbufs = 32;
10860 bi.bufsize = 1024;
10861 if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
10862 ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
10863 dahdi_close_pri_fd(pri, i);
10864 return -1;
10866 pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype, pri->span);
10867 /* Force overlap dial if we're doing GR-303! */
10868 if (pri->switchtype == PRI_SWITCH_GR303_TMC)
10869 pri->overlapdial = 1;
10870 pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
10871 #ifdef HAVE_PRI_INBANDDISCONNECT
10872 pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
10873 #endif
10874 /* Enslave to master if appropriate */
10875 if (i)
10876 pri_enslave(pri->dchans[0], pri->dchans[i]);
10877 if (!pri->dchans[i]) {
10878 dahdi_close_pri_fd(pri, i);
10879 ast_log(LOG_ERROR, "Unable to create PRI structure\n");
10880 return -1;
10882 pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
10883 pri_set_nsf(pri->dchans[i], pri->nsf);
10884 #ifdef PRI_GETSET_TIMERS
10885 for (x = 0; x < PRI_MAX_TIMERS; x++) {
10886 if (pritimers[x] != 0)
10887 pri_set_timer(pri->dchans[i], x, pritimers[x]);
10889 #endif
10891 /* Assume primary is the one we use */
10892 pri->pri = pri->dchans[0];
10893 pri->resetpos = -1;
10894 if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
10895 for (i = 0; i < NUM_DCHANS; i++) {
10896 if (!pri->dchannels[i])
10897 break;
10898 dahdi_close_pri_fd(pri, i);
10900 ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
10901 return -1;
10903 return 0;
10906 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
10908 int which, span;
10909 char *ret = NULL;
10911 if (pos != rpos)
10912 return ret;
10914 for (which = span = 0; span < NUM_SPANS; span++) {
10915 if (pris[span].pri && ++which > state) {
10916 asprintf(&ret, "%d", span + 1); /* user indexes start from 1 */
10917 break;
10920 return ret;
10923 static char *complete_span_4(const char *line, const char *word, int pos, int state)
10925 return complete_span_helper(line,word,pos,state,3);
10928 static char *complete_span_5(const char *line, const char *word, int pos, int state)
10930 return complete_span_helper(line,word,pos,state,4);
10933 static int handle_pri_set_debug_file(int fd, int argc, char **argv)
10935 int myfd, x, d;
10936 int span;
10938 if (argc < 6)
10939 return RESULT_SHOWUSAGE;
10941 if (!strncasecmp(argv[1], "set", 3)) {
10942 if (argc < 7)
10943 return RESULT_SHOWUSAGE;
10945 if (!argv[4] || ast_strlen_zero(argv[4]))
10946 return RESULT_SHOWUSAGE;
10948 if (!argv[5])
10949 return RESULT_SHOWUSAGE;
10951 if (!argv[6] || ast_strlen_zero(argv[6]))
10952 return RESULT_SHOWUSAGE;
10954 span = atoi(argv[6]);
10955 if ((span < 1) && (span > NUM_SPANS)) {
10956 return RESULT_SUCCESS;
10960 myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
10961 if (myfd < 0) {
10962 ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
10963 return RESULT_SUCCESS;
10965 for (x=0; x < NUM_SPANS; x++) {
10966 ast_mutex_lock(&pris[x].lock);
10968 if (pris[x].span == span) {
10969 if (pris[x].debugfd >= 0)
10970 close(pris[x].debugfd);
10971 pris[x].debugfd = myfd;
10972 for (d=0; d < NUM_DCHANS; d++) {
10973 if (pris[x].dchans[d])
10974 pri_set_debug_fd(pris[x].dchans[d], myfd);
10977 ast_mutex_unlock(&pris[x].lock);
10980 ast_cli(fd, "PRI debug output for span %d will be sent to '%s'\n", span, argv[4]);
10981 } else {
10982 if (!argv[5] || ast_strlen_zero(argv[5]))
10983 return RESULT_SHOWUSAGE;
10984 /* Assume it is unset */
10985 span = atoi(argv[5]);
10986 if ((span < 1) && (span > NUM_SPANS)) {
10987 return RESULT_SUCCESS;
10990 for (x=0; x < NUM_SPANS; x++) {
10991 ast_mutex_lock(&pris[x].lock);
10993 if (pris[x].span == span) {
10994 if (pris[x].debugfd >= 0)
10995 close(pris[x].debugfd);
10996 pris[x].debugfd = -1;
10997 for (d=0; d < NUM_DCHANS; d++) {
10998 if (pris[x].dchans[d])
10999 pri_set_debug_fd(pris[x].dchans[d], -1);
11002 ast_mutex_unlock(&pris[x].lock);
11005 ast_cli(fd, "PRI debug output to file for span %d disabled\n", span);
11008 return RESULT_SUCCESS;
11011 #ifdef HAVE_PRI_VERSION
11012 static int handle_pri_version(int fd, int agc, char *argv[]) {
11013 ast_cli(fd, "libpri version: %s\n", pri_get_version());
11014 return RESULT_SUCCESS;
11016 #endif
11018 static int handle_pri_debug(int fd, int argc, char *argv[])
11020 int span;
11021 int x;
11022 if (argc < 4) {
11023 return RESULT_SHOWUSAGE;
11025 span = atoi(argv[3]);
11026 if ((span < 1) || (span > NUM_SPANS)) {
11027 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
11028 return RESULT_SUCCESS;
11030 if (!pris[span-1].pri) {
11031 ast_cli(fd, "No PRI running on span %d\n", span);
11032 return RESULT_SUCCESS;
11034 for (x = 0; x < NUM_DCHANS; x++) {
11035 if (pris[span-1].dchans[x])
11036 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11037 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11038 PRI_DEBUG_Q921_STATE);
11040 ast_cli(fd, "Enabled debugging on span %d\n", span);
11041 return RESULT_SUCCESS;
11046 static int handle_pri_no_debug(int fd, int argc, char *argv[])
11048 int span;
11049 int x;
11050 if (argc < 5)
11051 return RESULT_SHOWUSAGE;
11052 span = atoi(argv[4]);
11053 if ((span < 1) || (span > NUM_SPANS)) {
11054 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11055 return RESULT_SUCCESS;
11057 if (!pris[span-1].pri) {
11058 ast_cli(fd, "No PRI running on span %d\n", span);
11059 return RESULT_SUCCESS;
11061 for (x = 0; x < NUM_DCHANS; x++) {
11062 if (pris[span-1].dchans[x])
11063 pri_set_debug(pris[span-1].dchans[x], 0);
11065 ast_cli(fd, "Disabled debugging on span %d\n", span);
11066 return RESULT_SUCCESS;
11069 static int handle_pri_really_debug(int fd, int argc, char *argv[])
11071 int span;
11072 int x;
11073 if (argc < 5)
11074 return RESULT_SHOWUSAGE;
11075 span = atoi(argv[4]);
11076 if ((span < 1) || (span > NUM_SPANS)) {
11077 ast_cli(fd, "Invalid span %s. Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
11078 return RESULT_SUCCESS;
11080 if (!pris[span-1].pri) {
11081 ast_cli(fd, "No PRI running on span %d\n", span);
11082 return RESULT_SUCCESS;
11084 for (x = 0; x < NUM_DCHANS; x++) {
11085 if (pris[span-1].dchans[x])
11086 pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11087 PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11088 PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
11090 ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
11091 return RESULT_SUCCESS;
11094 static void build_status(char *s, size_t len, int status, int active)
11096 if (!s || len < 1) {
11097 return;
11099 s[0] = '\0';
11100 if (status & DCHAN_PROVISIONED)
11101 strncat(s, "Provisioned, ", len - strlen(s) - 1);
11102 if (!(status & DCHAN_NOTINALARM))
11103 strncat(s, "In Alarm, ", len - strlen(s) - 1);
11104 if (status & DCHAN_UP)
11105 strncat(s, "Up", len - strlen(s) - 1);
11106 else
11107 strncat(s, "Down", len - strlen(s) - 1);
11108 if (active)
11109 strncat(s, ", Active", len - strlen(s) - 1);
11110 else
11111 strncat(s, ", Standby", len - strlen(s) - 1);
11112 s[len - 1] = '\0';
11115 static int handle_pri_show_spans(int fd, int argc, char *argv[])
11117 int span;
11118 int x;
11119 char status[256];
11120 if (argc != 3)
11121 return RESULT_SHOWUSAGE;
11123 for (span = 0; span < NUM_SPANS; span++) {
11124 if (pris[span].pri) {
11125 for (x = 0; x < NUM_DCHANS; x++) {
11126 if (pris[span].dchannels[x]) {
11127 build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
11128 ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
11133 return RESULT_SUCCESS;
11136 static int handle_pri_show_span(int fd, int argc, char *argv[])
11138 int span;
11139 int x;
11140 char status[256];
11141 if (argc < 4)
11142 return RESULT_SHOWUSAGE;
11143 span = atoi(argv[3]);
11144 if ((span < 1) || (span > NUM_SPANS)) {
11145 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11146 return RESULT_SUCCESS;
11148 if (!pris[span-1].pri) {
11149 ast_cli(fd, "No PRI running on span %d\n", span);
11150 return RESULT_SUCCESS;
11152 for (x = 0; x < NUM_DCHANS; x++) {
11153 if (pris[span-1].dchannels[x]) {
11154 #ifdef PRI_DUMP_INFO_STR
11155 char *info_str = NULL;
11156 #endif
11157 ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
11158 build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
11159 ast_cli(fd, "Status: %s\n", status);
11160 #ifdef PRI_DUMP_INFO_STR
11161 info_str = pri_dump_info_str(pris[span-1].pri);
11162 if (info_str) {
11163 ast_cli(fd, "%s", info_str);
11164 free(info_str);
11166 #else
11167 pri_dump_info(pris[span-1].pri);
11168 #endif
11169 ast_cli(fd, "\n");
11172 return RESULT_SUCCESS;
11175 static int handle_pri_show_debug(int fd, int argc, char *argv[])
11177 int x;
11178 int span;
11179 int count=0;
11180 int debug=0;
11182 for (span = 0; span < NUM_SPANS; span++) {
11183 if (pris[span].pri) {
11184 for (x = 0; x < NUM_DCHANS; x++) {
11185 debug = 0;
11186 if (pris[span].dchans[x]) {
11187 debug = pri_get_debug(pris[span].dchans[x]);
11188 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" );
11189 count++;
11196 if (!count)
11197 ast_cli(fd, "No debug set or no PRI running\n");
11198 return RESULT_SUCCESS;
11201 static const char pri_debug_help[] =
11202 "Usage: pri debug span <span>\n"
11203 " Enables debugging on a given PRI span\n";
11205 static const char pri_no_debug_help[] =
11206 "Usage: pri no debug span <span>\n"
11207 " Disables debugging on a given PRI span\n";
11209 static const char pri_really_debug_help[] =
11210 "Usage: pri intensive debug span <span>\n"
11211 " Enables debugging down to the Q.921 level\n";
11213 static const char pri_show_span_help[] =
11214 "Usage: pri show span <span>\n"
11215 " Displays PRI Information on a given PRI span\n";
11217 static const char pri_show_spans_help[] =
11218 "Usage: pri show spans\n"
11219 " Displays PRI Information\n";
11221 static char bri_debug_help[] =
11222 "Usage: bri debug span <span>\n"
11223 " Enables debugging on a given BRI span\n";
11225 static char bri_no_debug_help[] =
11226 "Usage: bri no debug span <span>\n"
11227 " Disables debugging on a given BRI span\n";
11229 static char bri_really_debug_help[] =
11230 "Usage: bri intensive debug span <span>\n"
11231 " Enables debugging down to the Q.921 level\n";
11233 static struct ast_cli_entry dahdi_pri_cli[] = {
11234 { { "pri", "debug", "span", NULL },
11235 handle_pri_debug, "Enables PRI debugging on a span",
11236 pri_debug_help, complete_span_4 },
11238 { { "pri", "no", "debug", "span", NULL },
11239 handle_pri_no_debug, "Disables PRI debugging on a span",
11240 pri_no_debug_help, complete_span_5 },
11242 { { "pri", "intense", "debug", "span", NULL },
11243 handle_pri_really_debug, "Enables REALLY INTENSE PRI debugging",
11244 pri_really_debug_help, complete_span_5 },
11246 { { "pri", "show", "spans", NULL },
11247 handle_pri_show_spans, "Displays PRI Information",
11248 pri_show_spans_help },
11250 { { "pri", "show", "span", NULL },
11251 handle_pri_show_span, "Displays PRI Information",
11252 pri_show_span_help, complete_span_4 },
11254 { { "pri", "show", "debug", NULL },
11255 handle_pri_show_debug, "Displays current PRI debug settings" },
11257 { { "bri", "debug", "span", NULL }, handle_pri_debug,
11258 "Enables BRI debugging on a span", bri_debug_help, complete_span_4 },
11260 { { "bri", "no", "debug", "span", NULL }, handle_pri_no_debug,
11261 "Disables BRI debugging on a span", bri_no_debug_help, complete_span_5 },
11263 { { "bri", "intense", "debug", "span", NULL }, handle_pri_really_debug,
11264 "Enables REALLY INTENSE BRI debugging", bri_really_debug_help, complete_span_5 },
11266 { { "pri", "set", "debug", "file", NULL },
11267 handle_pri_set_debug_file, "Sends PRI debug output to the specified file" },
11269 { { "pri", "unset", "debug", "file", NULL },
11270 handle_pri_set_debug_file, "Ends PRI debug output to file" },
11272 #ifdef HAVE_PRI_VERSION
11273 { { "pri", "show", "version", NULL },
11274 handle_pri_version, "Displays version of libpri" },
11275 #endif
11278 static char *zapCD_tdesc = "Call Deflection";
11279 static char *zapCD_app = "zapCD";
11280 static char *zapCD_synopsis = "Call Deflection";
11282 static int app_zapCD(struct ast_channel *chan, void *data)
11284 struct dahdi_pvt *p = chan->tech_pvt;
11286 if((!p->pri) || (!p->pri->pri)) {
11287 return -1;
11290 if(!data) {
11291 ast_log(LOG_WARNING, "zapCD wants a number to deflect to\n");
11292 return -1;
11294 return pri_deflect(p->pri->pri, p->call, data);
11297 static char *zapInband_tdesc = "Inband Call Progress (pre-answer)";
11298 static char *zapInband_app = "zapInband";
11299 static char *zapInband_synopsis = "Inband Call Progress";
11301 static int app_zapInband(struct ast_channel *chan, void *data)
11303 struct dahdi_pvt *p = chan->tech_pvt;
11305 return pri_acknowledge(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1);
11308 #endif /* HAVE_PRI */
11310 #ifdef HAVE_GSMAT
11311 static int handle_zap_reset_span(int fd, int argc, char *argv[])
11313 int span;
11314 int sleep = 5000;
11315 if (argc < 4)
11316 return RESULT_SHOWUSAGE;
11317 span = atoi(argv[3]);
11318 if ((span < 1) || (span > NUM_SPANS)) {
11319 ast_cli(fd, "Invalid span '%s'. Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
11320 return RESULT_SUCCESS;
11322 if (dahdi_reset_span(span, sleep)) {
11323 return RESULT_FAILURE;
11325 return RESULT_SUCCESS;
11328 static int handle_gsm_debug_helper(int fd, int channel, int debug)
11330 /* gsm debug channel <channel> */
11331 struct dahdi_pvt *pvt = NULL;
11332 if (channel < 1) {
11333 ast_cli(fd, "Invalid channel %d. Should be a number.\n", channel);
11334 return RESULT_SUCCESS;
11336 pvt = iflist;
11337 while (pvt) {
11338 if (pvt->channel == channel) {
11339 ast_mutex_lock(&pvt->lock);
11340 gsm_set_debug(pvt->gsm.modul, debug);
11341 ast_mutex_unlock(&pvt->lock);
11342 ast_cli(fd, "%s debugging on channel %d\n", debug ? "Enabled":"Disabled", channel);
11343 return RESULT_SUCCESS;
11345 pvt = pvt->next;
11348 ast_cli(fd, "No GSM running on channel %d\n", channel);
11349 return RESULT_SUCCESS;
11354 static int handle_gsm_debug(int fd, int argc, char *argv[])
11356 /* gsm debug channel <channel> */
11357 int channel;
11358 if (argc < 4) {
11359 return RESULT_SHOWUSAGE;
11361 channel = atoi(argv[3]);
11362 return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_AT);
11365 static int handle_gsm_no_debug(int fd, int argc, char *argv[])
11367 /* gsm no debug channel <channel> */
11368 int channel;
11369 if (argc < 5) {
11370 return RESULT_SHOWUSAGE;
11372 channel = atoi(argv[4]);
11373 return handle_gsm_debug_helper(fd, channel, GSM_DEBUG_NONE);
11376 static char zap_reset_help[] =
11377 "Usage: zap reset span <span>\n"
11378 " Reset/Restart a zaptel span\n";
11380 static char gsm_debug_help[] =
11381 "Usage: gsm debug channel <channel>\n"
11382 " Enables debugging on a given GSM channel\n";
11384 static char gsm_no_debug_help[] =
11385 "Usage: gsm no debug channel <channel>\n"
11386 " Disables debugging on a given GSM channel\n";
11388 static struct ast_cli_entry zap_gsm_cli[] = {
11389 { { "zap", "reset", "span", NULL }, handle_zap_reset_span,
11390 "Restart a zaptel span", zap_reset_help, complete_span_4 },
11391 { { "gsm", "debug", "channel", NULL }, handle_gsm_debug,
11392 "Enables GSM debugging on a channel", gsm_debug_help },
11393 { { "gsm", "no", "debug", "channel", NULL }, handle_gsm_no_debug,
11394 "Disables GSM debugging on a channel", gsm_no_debug_help},
11399 static char gsm_send_pdu_help[] =
11400 "Usage: gsm send pdu <channel> <pdu>\n"
11401 " Sends a PDU on a GSM channel\n";
11405 static int handle_gsm_send_pdu(int fd, int argc, char *argv[])
11407 /* gsm send sms <channel> <destination> <message> */
11408 int channel;
11409 struct dahdi_pvt *pvt = NULL;
11410 if (argc < 5) {
11411 return RESULT_SHOWUSAGE;
11413 channel = atoi(argv[3]);
11414 if (channel < 1) {
11415 ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
11416 return RESULT_SUCCESS;
11418 pvt = iflist;
11419 while (pvt) {
11420 if (pvt->channel == channel) {
11421 if (pvt->owner) {
11422 ast_cli(fd, "Channel in use.\n");
11423 return RESULT_FAILURE;
11424 } else {
11425 ast_mutex_lock(&pvt->lock);
11426 gsm_sms_send_pdu(pvt->gsm.modul, argv[4]);
11427 ast_mutex_unlock(&pvt->lock);
11428 return RESULT_SUCCESS;
11431 pvt = pvt->next;
11434 return RESULT_SUCCESS;
11437 static struct ast_cli_entry gsm_send_pdu = {
11438 { "gsm", "send", "pdu", NULL }, handle_gsm_send_pdu, "Sends a SM on a GSM channel", gsm_send_pdu_help, complete_span_4 };
11441 static char gsm_send_sms_help[] =
11442 "Usage: gsm send sms <channel> <destination> <message>\n"
11443 " Sends a SM on a GSM channel\n";
11446 static int handle_gsm_send_sms(int fd, int argc, char *argv[])
11448 /* gsm send sms <channel> <destination> <message> */
11449 int channel;
11450 struct dahdi_pvt *pvt = NULL;
11451 if (argc < 6) {
11452 return RESULT_SHOWUSAGE;
11454 channel = atoi(argv[3]);
11455 if (channel < 1) {
11456 ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
11457 return RESULT_SUCCESS;
11459 pvt = iflist;
11460 while (pvt) {
11461 if (pvt->channel == channel) {
11462 if (pvt->owner) {
11463 ast_cli(fd, "Channel in use.\n");
11464 return RESULT_FAILURE;
11465 } else {
11466 ast_mutex_lock(&pvt->lock);
11467 gsm_sms_send_text(pvt->gsm.modul, argv[4], argv[5]);
11468 ast_mutex_unlock(&pvt->lock);
11469 return RESULT_SUCCESS;
11472 pvt = pvt->next;
11475 return RESULT_SUCCESS;
11478 static int dahdi_gsm_sendtext(struct ast_channel *chan, const char * dest, const char *text, int ispdu) {
11479 struct dahdi_pvt *pvt = NULL;
11480 char *c = NULL;
11481 pvt = chan->tech_pvt;
11483 if (!pvt) return -1;
11485 /* parse dialstring */
11486 c = strrchr(dest, '/');
11487 if (c)
11488 c++;
11489 else
11490 c = (char *)dest;
11492 ast_mutex_lock(&pvt->lock);
11493 if (ispdu) {
11494 gsm_sms_send_pdu(pvt->gsm.modul, (char *)text);
11495 } else {
11496 gsm_sms_send_text(pvt->gsm.modul, c, (char *)text);
11498 ast_mutex_unlock(&pvt->lock);
11499 gsm_wait(pvt->gsm.modul);
11500 return 0;
11503 static struct ast_cli_entry gsm_send_sms = {
11504 { "gsm", "send", "sms", NULL }, handle_gsm_send_sms, "Sends a SM on a GSM channel", gsm_send_sms_help, complete_span_4 };
11506 static char gsm_show_status_help[] =
11507 "Usage: gsm show status <channel>>\n"
11508 " Displays status information about the GSM channel.\n";
11511 static int handle_gsm_show_status(int fd, int argc, char *argv[])
11513 int channel;
11514 struct dahdi_pvt *pvt = NULL;
11515 if (argc < 4) {
11516 return RESULT_SHOWUSAGE;
11518 channel = atoi(argv[3]);
11519 if (channel < 1) {
11520 ast_cli(fd, "Invalid channel %s. Should be a number.\n", argv[3]);
11521 return RESULT_SUCCESS;
11523 pvt = iflist;
11524 while (pvt) {
11525 if (pvt->channel == channel) {
11526 if (pvt->owner) {
11527 ast_cli(fd, "Channel in use.\n");
11528 return RESULT_FAILURE;
11529 } else {
11530 ast_mutex_lock(&pvt->lock);
11531 gsm_request_status(pvt->gsm.modul);
11532 ast_mutex_unlock(&pvt->lock);
11533 return RESULT_SUCCESS;
11536 pvt = pvt->next;
11539 return RESULT_SUCCESS;
11542 static struct ast_cli_entry gsm_show_status = {
11543 { "gsm", "show", "status", NULL }, handle_gsm_show_status, "Displays status information about the GSM channel.", gsm_show_status_help, complete_span_4 };
11545 #endif /* HAVE_GSMAT */
11547 static int app_zapEC(struct ast_channel *chan, void *data)
11549 int res=-1;
11550 struct dahdi_pvt *p = NULL;
11552 if (!data) {
11553 ast_log(LOG_WARNING, "zapEC requires one argument (on | off)\n");
11555 if (chan && !strcasecmp("ZAP",chan->tech->type)) {
11556 p = chan->tech_pvt;
11557 if (!p) return res;
11558 if (!strcasecmp("on",(char *)data)) {
11559 dahdi_enable_ec(p);
11560 res = 0;
11561 if (option_verbose > 3) {
11562 ast_verbose(VERBOSE_PREFIX_3 "Enabled echo cancelation on channel %s.\n", chan->name);
11564 } else if (!strcasecmp("off",(char *)data)) {
11565 dahdi_disable_ec(p);
11566 res = 0;
11567 if (option_verbose > 3) {
11568 ast_verbose(VERBOSE_PREFIX_3 "Disabled echo cancelation on channel %s.\n", chan->name);
11570 } else {
11571 ast_log(LOG_WARNING, "Unknown argument %s to zapEC\n", (char *)data);
11573 } else {
11574 ast_log(LOG_WARNING, "zapNoEC only works on ZAP channels, check your extensions.conf!\n");
11575 res = 0;
11578 return res;
11581 static char *zapEC_tdesc = "Enable/disable Echo cancelation";
11582 static char *zapEC_app = "zapEC";
11583 static char *zapEC_synopsis = "Enable/Disable Echo Cancelation on a Zap channel";
11585 static int dahdi_destroy_channel(int fd, int argc, char **argv)
11587 int channel;
11589 if (argc != 4)
11590 return RESULT_SHOWUSAGE;
11592 channel = atoi(argv[3]);
11594 return dahdi_destroy_channel_bynum(channel);
11597 static void dahdi_softhangup_all(void)
11599 struct dahdi_pvt *p;
11600 retry:
11601 ast_mutex_lock(&iflock);
11602 for (p = iflist; p; p = p->next) {
11603 ast_mutex_lock(&p->lock);
11604 if (p->owner && !p->restartpending) {
11605 if (ast_channel_trylock(p->owner)) {
11606 if (option_debug > 2)
11607 ast_verbose("Avoiding deadlock\n");
11608 /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
11609 ast_mutex_unlock(&p->lock);
11610 ast_mutex_unlock(&iflock);
11611 goto retry;
11613 if (option_debug > 2)
11614 ast_verbose("Softhanging up on %s\n", p->owner->name);
11615 ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
11616 p->restartpending = 1;
11617 num_restart_pending++;
11618 ast_channel_unlock(p->owner);
11620 ast_mutex_unlock(&p->lock);
11622 ast_mutex_unlock(&iflock);
11625 static int setup_dahdi(int reload);
11626 static int dahdi_restart(void)
11628 #if defined(HAVE_PRI)
11629 int i, j;
11630 #endif
11631 int cancel_code;
11632 struct dahdi_pvt *p;
11634 ast_mutex_lock(&restart_lock);
11636 if (option_verbose)
11637 ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
11638 dahdi_softhangup_all();
11639 if (option_verbose > 3)
11640 ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
11642 #if defined(HAVE_PRI)
11643 for (i = 0; i < NUM_SPANS; i++) {
11644 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
11645 cancel_code = pthread_cancel(pris[i].master);
11646 pthread_kill(pris[i].master, SIGURG);
11647 if (option_debug > 3)
11648 ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
11649 pthread_join(pris[i].master, NULL);
11650 if (option_debug > 3)
11651 ast_verbose("Joined thread of span %d\n", i);
11654 #endif
11656 ast_mutex_lock(&monlock);
11657 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11658 cancel_code = pthread_cancel(monitor_thread);
11659 pthread_kill(monitor_thread, SIGURG);
11660 if (option_debug > 3)
11661 ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
11662 pthread_join(monitor_thread, NULL);
11663 if (option_debug > 3)
11664 ast_verbose("Joined monitor thread\n");
11666 monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
11668 ast_mutex_lock(&ss_thread_lock);
11669 while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
11670 int x = DAHDI_FLASH;
11671 if (option_debug > 2)
11672 ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
11674 for (p = iflist; p; p = p->next) {
11675 if (p->owner)
11676 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 */
11678 ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
11681 /* ensure any created channels before monitor threads were stopped are hungup */
11682 dahdi_softhangup_all();
11683 if (option_verbose > 3)
11684 ast_verbose("Final softhangup of all DAHDI channels complete.\n");
11685 destroy_all_channels();
11686 if (option_debug)
11687 ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
11689 ast_mutex_unlock(&monlock);
11691 #ifdef HAVE_PRI
11692 for (i = 0; i < NUM_SPANS; i++) {
11693 for (j = 0; j < NUM_DCHANS; j++)
11694 dahdi_close_pri_fd(&(pris[i]), j);
11697 memset(pris, 0, sizeof(pris));
11698 for (i = 0; i < NUM_SPANS; i++) {
11699 ast_mutex_init(&pris[i].lock);
11700 pris[i].offset = -1;
11701 pris[i].master = AST_PTHREADT_NULL;
11702 for (j = 0; j < NUM_DCHANS; j++)
11703 pris[i].fds[j] = -1;
11705 pri_set_error(dahdi_pri_error);
11706 pri_set_message(dahdi_pri_message);
11707 #endif
11709 if (setup_dahdi(2) != 0) {
11710 ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
11711 ast_mutex_unlock(&ss_thread_lock);
11712 return 1;
11714 ast_mutex_unlock(&ss_thread_lock);
11715 ast_mutex_unlock(&restart_lock);
11716 return 0;
11719 static int dahdi_restart_cmd(int fd, int argc, char **argv)
11721 if (argc != 2) {
11722 return RESULT_SHOWUSAGE;
11725 if (dahdi_restart() != 0)
11726 return RESULT_FAILURE;
11727 return RESULT_SUCCESS;
11730 static int dahdi_show_channels(int fd, int argc, char **argv)
11732 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11733 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
11734 struct dahdi_pvt *tmp = NULL;
11735 char tmps[20] = "";
11736 ast_mutex_t *lock;
11737 struct dahdi_pvt *start;
11738 #ifdef HAVE_PRI
11739 int trunkgroup;
11740 struct dahdi_pri *pri = NULL;
11741 int x;
11742 #endif
11744 lock = &iflock;
11745 start = iflist;
11747 #ifdef HAVE_PRI
11748 if (argc == 4) {
11749 if ((trunkgroup = atoi(argv[3])) < 1)
11750 return RESULT_SHOWUSAGE;
11751 for (x = 0; x < NUM_SPANS; x++) {
11752 if (pris[x].trunkgroup == trunkgroup) {
11753 pri = pris + x;
11754 break;
11757 if (pri) {
11758 start = pri->crvs;
11759 lock = &pri->lock;
11760 } else {
11761 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
11762 return RESULT_FAILURE;
11764 } else
11765 #endif
11766 if (argc != 3)
11767 return RESULT_SHOWUSAGE;
11769 ast_mutex_lock(lock);
11770 #ifdef HAVE_PRI
11771 ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
11772 #else
11773 ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
11774 #endif
11776 tmp = start;
11777 while (tmp) {
11778 if (tmp->channel > 0) {
11779 snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
11780 } else
11781 ast_copy_string(tmps, "pseudo", sizeof(tmps));
11782 ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
11783 tmp = tmp->next;
11785 ast_mutex_unlock(lock);
11786 return RESULT_SUCCESS;
11787 #undef FORMAT
11788 #undef FORMAT2
11791 static int dahdi_show_channel(int fd, int argc, char **argv)
11793 int channel;
11794 struct dahdi_pvt *tmp = NULL;
11795 struct dahdi_confinfo ci;
11796 struct dahdi_params ps;
11797 int x;
11798 ast_mutex_t *lock;
11799 struct dahdi_pvt *start;
11800 #ifdef HAVE_PRI
11801 char *c;
11802 int trunkgroup;
11803 struct dahdi_pri *pri=NULL;
11804 #endif
11806 lock = &iflock;
11807 start = iflist;
11809 if (argc != 4)
11810 return RESULT_SHOWUSAGE;
11811 #ifdef HAVE_PRI
11812 if ((c = strchr(argv[3], ':'))) {
11813 if (sscanf(argv[3], "%d:%d", &trunkgroup, &channel) != 2)
11814 return RESULT_SHOWUSAGE;
11815 if ((trunkgroup < 1) || (channel < 1))
11816 return RESULT_SHOWUSAGE;
11817 for (x = 0; x < NUM_SPANS; x++) {
11818 if (pris[x].trunkgroup == trunkgroup) {
11819 pri = pris + x;
11820 break;
11823 if (pri) {
11824 start = pri->crvs;
11825 lock = &pri->lock;
11826 } else {
11827 ast_cli(fd, "No such trunk group %d\n", trunkgroup);
11828 return RESULT_FAILURE;
11830 } else
11831 #endif
11832 channel = atoi(argv[3]);
11834 ast_mutex_lock(lock);
11835 tmp = start;
11836 while (tmp) {
11837 if (tmp->channel == channel) {
11838 #ifdef HAVE_PRI
11839 if (pri)
11840 ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
11841 else
11842 #endif
11843 ast_cli(fd, "Channel: %d\n", tmp->channel);
11844 ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
11845 ast_cli(fd, "Span: %d\n", tmp->span);
11846 ast_cli(fd, "Extension: %s\n", tmp->exten);
11847 ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
11848 ast_cli(fd, "Context: %s\n", tmp->context);
11849 ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
11850 ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
11851 ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
11852 ast_cli(fd, "Destroy: %d\n", tmp->destroy);
11853 ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
11854 ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
11855 ast_cli(fd, "Radio: %d\n", tmp->radio);
11856 ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
11857 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)" : "");
11858 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)" : "");
11859 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)" : "");
11860 ast_cli(fd, "Confno: %d\n", tmp->confno);
11861 ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
11862 ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
11863 ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
11864 ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
11865 ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
11866 ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
11867 ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
11868 ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
11869 ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
11870 if (tmp->master)
11871 ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
11872 for (x = 0; x < MAX_SLAVES; x++) {
11873 if (tmp->slaves[x])
11874 ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
11876 #ifdef HAVE_PRI
11877 if (tmp->pri) {
11878 ast_cli(fd, "PRI Flags: ");
11879 if (tmp->resetting)
11880 ast_cli(fd, "Resetting ");
11881 if (tmp->call)
11882 ast_cli(fd, "Call ");
11883 if (tmp->bearer)
11884 ast_cli(fd, "Bearer ");
11885 ast_cli(fd, "\n");
11886 if (tmp->logicalspan)
11887 ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
11888 else
11889 ast_cli(fd, "PRI Logical Span: Implicit\n");
11892 #endif
11893 memset(&ci, 0, sizeof(ci));
11894 ps.channo = tmp->channel;
11895 if (tmp->subs[SUB_REAL].dfd > -1) {
11896 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
11897 ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
11899 #ifdef DAHDI_GETCONFMUTE
11900 if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
11901 ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
11903 #endif
11904 if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
11905 ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
11906 } else {
11907 ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
11910 ast_mutex_unlock(lock);
11911 return RESULT_SUCCESS;
11913 tmp = tmp->next;
11916 ast_cli(fd, "Unable to find given channel %d\n", channel);
11917 ast_mutex_unlock(lock);
11918 return RESULT_FAILURE;
11921 static char dahdi_show_cadences_usage[] =
11922 "Usage: dahdi show cadences\n"
11923 " Shows all cadences currently defined\n";
11925 static int handle_dahdi_show_cadences(int fd, int argc, char *argv[])
11927 int i, j;
11928 for (i = 0; i < num_cadence; i++) {
11929 char output[1024];
11930 char tmp[16], tmp2[64];
11931 snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
11932 term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
11934 for (j = 0; j < 16; j++) {
11935 if (cadences[i].ringcadence[j] == 0)
11936 break;
11937 snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
11938 if (cidrings[i] * 2 - 1 == j)
11939 term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
11940 else
11941 term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
11942 if (j != 0)
11943 strncat(output, ",", sizeof(output) - strlen(output) - 1);
11944 strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
11946 ast_cli(fd,"%s\n",output);
11948 return 0;
11951 /* Based on irqmiss.c */
11952 static int dahdi_show_status(int fd, int argc, char *argv[]) {
11953 #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
11954 #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
11956 int span;
11957 int res;
11958 char alarms[50];
11960 int ctl;
11961 struct dahdi_spaninfo s;
11963 #ifdef HAVE_ZAPTEL
11964 if ((ctl = open("/dev/zap/ctl", O_RDWR)) < 0) {
11965 ast_log(LOG_WARNING, "Unable to open /dev/zap/ctl: %s\n", strerror(errno));
11966 ast_cli(fd, "No Zaptel interface found.\n");
11967 return RESULT_FAILURE;
11969 #else
11970 if ((ctl = open("/dev/dahdi/ctl", O_RDWR)) < 0) {
11971 ast_log(LOG_WARNING, "Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
11972 ast_cli(fd, "No DAHDI interface found.\n");
11973 return RESULT_FAILURE;
11975 #endif
11976 ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
11978 for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
11979 s.spanno = span;
11980 res = ioctl(ctl, DAHDI_SPANSTAT, &s);
11981 if (res) {
11982 continue;
11984 alarms[0] = '\0';
11985 if (s.alarms > 0) {
11986 if (s.alarms & DAHDI_ALARM_BLUE)
11987 strcat(alarms, "BLU/");
11988 if (s.alarms & DAHDI_ALARM_YELLOW)
11989 strcat(alarms, "YEL/");
11990 if (s.alarms & DAHDI_ALARM_RED)
11991 strcat(alarms, "RED/");
11992 if (s.alarms & DAHDI_ALARM_LOOPBACK)
11993 strcat(alarms, "LB/");
11994 if (s.alarms & DAHDI_ALARM_RECOVER)
11995 strcat(alarms, "REC/");
11996 if (s.alarms & DAHDI_ALARM_NOTOPEN)
11997 strcat(alarms, "NOP/");
11998 if (!strlen(alarms))
11999 strcat(alarms, "UUU/");
12000 if (strlen(alarms)) {
12001 /* Strip trailing / */
12002 alarms[strlen(alarms) - 1] = '\0';
12004 } else {
12005 if (s.numchans)
12006 strcpy(alarms, "OK");
12007 else
12008 strcpy(alarms, "UNCONFIGURED");
12011 ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
12013 close(ctl);
12015 return RESULT_SUCCESS;
12016 #undef FORMAT
12017 #undef FORMAT2
12020 static char show_channels_usage[] =
12021 "Usage: dahdi show channels\n"
12022 " Shows a list of available channels\n";
12024 static char show_channel_usage[] =
12025 "Usage: dahdi show channel <chan num>\n"
12026 " Detailed information about a given channel\n";
12028 static char dahdi_show_status_usage[] =
12029 "Usage: dahdi show status\n"
12030 " Shows a list of DAHDI cards with status\n";
12032 static char destroy_channel_usage[] =
12033 "Usage: dahdi destroy channel <chan num>\n"
12034 " DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING. Immediately removes a given channel, whether it is in use or not\n";
12036 static char dahdi_restart_usage[] =
12037 "Usage: dahdi restart\n"
12038 " Restarts the DAHDI channels: destroys them all and then\n"
12039 " re-reads them from chan_dahdi.conf.\n"
12040 " Note that this will STOP any running CALL on DAHDI channels.\n"
12043 static struct ast_cli_entry cli_zap_show_cadences_deprecated = {
12044 { "zap", "show", "cadences", NULL },
12045 handle_dahdi_show_cadences, NULL,
12046 NULL };
12048 static struct ast_cli_entry cli_zap_show_channels_deprecated = {
12049 { "zap", "show", "channels", NULL },
12050 dahdi_show_channels, NULL,
12051 NULL };
12053 static struct ast_cli_entry cli_zap_show_channel_deprecated = {
12054 { "zap", "show", "channel", NULL },
12055 dahdi_show_channel, NULL,
12056 NULL };
12058 static struct ast_cli_entry cli_zap_destroy_channel_deprecated = {
12059 { "zap", "destroy", "channel", NULL },
12060 dahdi_destroy_channel, NULL,
12061 NULL };
12063 static struct ast_cli_entry cli_zap_restart_deprecated = {
12064 { "zap", "restart", NULL },
12065 dahdi_restart_cmd, NULL,
12066 NULL };
12068 static struct ast_cli_entry cli_zap_show_status_deprecated = {
12069 { "zap", "show", "status", NULL },
12070 dahdi_show_status, NULL,
12071 NULL };
12073 static struct ast_cli_entry dahdi_cli[] = {
12074 { { "dahdi", "show", "cadences", NULL },
12075 handle_dahdi_show_cadences, "List cadences",
12076 dahdi_show_cadences_usage, NULL, &cli_zap_show_cadences_deprecated },
12078 { { "dahdi", "show", "channels", NULL},
12079 dahdi_show_channels, "Show active DAHDI channels",
12080 show_channels_usage, NULL, &cli_zap_show_channels_deprecated },
12082 { { "dahdi", "show", "channel", NULL},
12083 dahdi_show_channel, "Show information on a channel",
12084 show_channel_usage, NULL, &cli_zap_show_channel_deprecated },
12086 { { "dahdi", "destroy", "channel", NULL},
12087 dahdi_destroy_channel, "Destroy a channel",
12088 destroy_channel_usage, NULL, &cli_zap_destroy_channel_deprecated },
12090 { { "dahdi", "restart", NULL},
12091 dahdi_restart_cmd, "Fully restart DAHDI channels",
12092 dahdi_restart_usage, NULL, &cli_zap_restart_deprecated },
12094 { { "dahdi", "show", "status", NULL},
12095 dahdi_show_status, "Show all DAHDI cards status",
12096 dahdi_show_status_usage, NULL, &cli_zap_show_status_deprecated },
12099 #define TRANSFER 0
12100 #define HANGUP 1
12102 static int dahdi_fake_event(struct dahdi_pvt *p, int mode)
12104 if (p) {
12105 switch (mode) {
12106 case TRANSFER:
12107 p->fake_event = DAHDI_EVENT_WINKFLASH;
12108 break;
12109 case HANGUP:
12110 p->fake_event = DAHDI_EVENT_ONHOOK;
12111 break;
12112 default:
12113 ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
12116 return 0;
12118 static struct dahdi_pvt *find_channel(int channel)
12120 struct dahdi_pvt *p = iflist;
12121 while (p) {
12122 if (p->channel == channel) {
12123 break;
12125 p = p->next;
12127 return p;
12130 #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)
12131 #define local_astman_header(m, hdr, zap) astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
12133 static int __action_dnd(struct mansession *s, const struct message *m, int zap_mode, int dnd)
12135 struct dahdi_pvt *p = NULL;
12136 const char *channel = local_astman_header(m, "Channel", zap_mode);
12138 if (ast_strlen_zero(channel)) {
12139 astman_send_error(s, m, "No channel specified");
12140 return 0;
12142 if (!(p = find_channel(atoi(channel)))) {
12143 astman_send_error(s, m, "No such channel");
12144 return 0;
12146 p->dnd = dnd;
12147 local_astman_ack(s, m, "DND", zap_mode);
12149 return 0;
12152 static int zap_action_dndon(struct mansession *s, const struct message *m)
12154 return __action_dnd(s, m, 1, 1);
12157 static int dahdi_action_dndon(struct mansession *s, const struct message *m)
12159 return __action_dnd(s, m, 0, 1);
12162 static int zap_action_dndoff(struct mansession *s, const struct message *m)
12164 return __action_dnd(s, m, 1, 0);
12167 static int dahdi_action_dndoff(struct mansession *s, const struct message *m)
12169 return __action_dnd(s, m, 0, 0);
12172 static int __action_transfer(struct mansession *s, const struct message *m, int zap_mode)
12174 struct dahdi_pvt *p = NULL;
12175 const char *channel = local_astman_header(m, "Channel", zap_mode);
12177 if (ast_strlen_zero(channel)) {
12178 astman_send_error(s, m, "No channel specified");
12179 return 0;
12181 if (!(p = find_channel(atoi(channel)))) {
12182 astman_send_error(s, m, "No such channel");
12183 return 0;
12185 dahdi_fake_event(p,TRANSFER);
12186 local_astman_ack(s, m, "Transfer", zap_mode);
12188 return 0;
12191 static int zap_action_transfer(struct mansession *s, const struct message *m)
12193 return __action_transfer(s, m, 1);
12196 static int dahdi_action_transfer(struct mansession *s, const struct message *m)
12198 return __action_transfer(s, m, 0);
12201 static int __action_transferhangup(struct mansession *s, const struct message *m, int zap_mode)
12203 struct dahdi_pvt *p = NULL;
12204 const char *channel = local_astman_header(m, "Channel", zap_mode);
12206 if (ast_strlen_zero(channel)) {
12207 astman_send_error(s, m, "No channel specified");
12208 return 0;
12210 if (!(p = find_channel(atoi(channel)))) {
12211 astman_send_error(s, m, "No such channel");
12212 return 0;
12214 dahdi_fake_event(p, HANGUP);
12215 local_astman_ack(s, m, "Hangup", zap_mode);
12216 return 0;
12219 static int zap_action_transferhangup(struct mansession *s, const struct message *m)
12221 return __action_transferhangup(s, m, 1);
12224 static int dahdi_action_transferhangup(struct mansession *s, const struct message *m)
12226 return __action_transferhangup(s, m, 0);
12229 static int __action_dialoffhook(struct mansession *s, const struct message *m, int zap_mode)
12231 struct dahdi_pvt *p = NULL;
12232 const char *channel = local_astman_header(m, "Channel", zap_mode);
12233 const char *number = astman_get_header(m, "Number");
12234 int i;
12236 if (ast_strlen_zero(channel)) {
12237 astman_send_error(s, m, "No channel specified");
12238 return 0;
12240 if (ast_strlen_zero(number)) {
12241 astman_send_error(s, m, "No number specified");
12242 return 0;
12244 if (!(p = find_channel(atoi(channel)))) {
12245 astman_send_error(s, m, "No such channel");
12246 return 0;
12248 if (!p->owner) {
12249 astman_send_error(s, m, "Channel does not have its owner");
12250 return 0;
12252 for (i = 0; i < strlen(number); i++) {
12253 struct ast_frame f = { AST_FRAME_DTMF, number[i] };
12255 dahdi_queue_frame(p, &f, NULL);
12257 local_astman_ack(s, m, "DialOffHook", zap_mode);
12259 return 0;
12262 static int zap_action_dialoffhook(struct mansession *s, const struct message *m)
12264 return __action_dialoffhook(s, m, 1);
12267 static int dahdi_action_dialoffhook(struct mansession *s, const struct message *m)
12269 return __action_dialoffhook(s, m, 0);
12272 static int __action_showchannels(struct mansession *s, const struct message *m, int zap_mode)
12274 struct dahdi_pvt *tmp = NULL;
12275 const char *id = astman_get_header(m, "ActionID");
12276 char idText[256] = "";
12278 local_astman_ack(s, m, " channel status will follow", zap_mode);
12279 if (!ast_strlen_zero(id))
12280 snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
12282 ast_mutex_lock(&iflock);
12284 tmp = iflist;
12285 while (tmp) {
12286 if (tmp->channel > 0) {
12287 int alarm = get_alarms(tmp);
12288 astman_append(s,
12289 "Event: %sShowChannels\r\n"
12290 "Channel: %d\r\n"
12291 "Signalling: %s\r\n"
12292 "Context: %s\r\n"
12293 "DND: %s\r\n"
12294 "Alarm: %s\r\n"
12295 "%s"
12296 "\r\n",
12297 dahdi_chan_name,
12298 tmp->channel, sig2str(tmp->sig), tmp->context,
12299 tmp->dnd ? "Enabled" : "Disabled",
12300 alarm2str(alarm), idText);
12303 tmp = tmp->next;
12306 ast_mutex_unlock(&iflock);
12308 astman_append(s,
12309 "Event: %sShowChannelsComplete\r\n"
12310 "%s"
12311 "\r\n",
12312 dahdi_chan_name,
12313 idText);
12314 return 0;
12317 static int zap_action_showchannels(struct mansession *s, const struct message *m)
12319 return __action_showchannels(s, m, 1);
12322 static int dahdi_action_showchannels(struct mansession *s, const struct message *m)
12324 return __action_showchannels(s, m, 0);
12327 static int __action_restart(struct mansession *s, const struct message *m, int zap_mode)
12329 if (dahdi_restart() != 0) {
12330 if (zap_mode) {
12331 astman_send_error(s, m, "Failed to restart Zap");
12332 } else {
12333 astman_send_error(s, m, "Failed to restart DAHDI");
12335 return 1;
12337 local_astman_ack(s, m, "Restart: Success", zap_mode);
12338 return 0;
12341 static int zap_action_restart(struct mansession *s, const struct message *m)
12343 return __action_restart(s, m, 1);
12346 static int dahdi_action_restart(struct mansession *s, const struct message *m)
12348 return __action_restart(s, m, 0);
12351 #define local_astman_unregister(a) do { \
12352 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
12353 ast_manager_unregister("DAHDI" a); \
12355 ast_manager_unregister("Zap" a); \
12356 } while (0)
12358 static int __unload_module(void)
12360 struct dahdi_pvt *p;
12362 #ifdef HAVE_PRI
12363 int i, j;
12364 for (i = 0; i < NUM_SPANS; i++) {
12365 if (pris[i].master != AST_PTHREADT_NULL)
12366 pthread_cancel(pris[i].master);
12368 ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12370 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12371 ast_unregister_application(dahdi_send_keypad_facility_app);
12373 ast_unregister_application(zap_send_keypad_facility_app);
12374 ast_unregister_application(zapCD_app);
12375 ast_unregister_application(zapInband_app);
12376 #endif
12377 #ifdef HAVE_GSMAT
12378 ast_cli_unregister_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
12379 ast_cli_unregister(&gsm_send_sms);
12380 ast_cli_unregister(&gsm_send_pdu);
12381 ast_cli_unregister(&gsm_show_status);
12382 #endif
12383 ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12384 ast_unregister_application(zapEC_app);
12385 local_astman_unregister("DialOffHook");
12386 local_astman_unregister("Hangup");
12387 local_astman_unregister("Transfer");
12388 local_astman_unregister("DNDoff");
12389 local_astman_unregister("DNDon");
12390 local_astman_unregister("ShowChannels");
12391 local_astman_unregister("Restart");
12392 ast_channel_unregister(chan_tech);
12393 ast_mutex_lock(&iflock);
12394 /* Hangup all interfaces if they have an owner */
12395 p = iflist;
12396 while (p) {
12397 if (p->owner)
12398 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
12399 p = p->next;
12401 ast_mutex_unlock(&iflock);
12402 ast_mutex_lock(&monlock);
12403 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12404 pthread_cancel(monitor_thread);
12405 pthread_kill(monitor_thread, SIGURG);
12406 pthread_join(monitor_thread, NULL);
12408 monitor_thread = AST_PTHREADT_STOP;
12409 ast_mutex_unlock(&monlock);
12411 destroy_all_channels();
12412 #ifdef HAVE_PRI
12413 for (i = 0; i < NUM_SPANS; i++) {
12414 if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
12415 pthread_join(pris[i].master, NULL);
12416 for (j = 0; j < NUM_DCHANS; j++) {
12417 dahdi_close_pri_fd(&(pris[i]), j);
12420 #endif
12421 ast_cond_destroy(&ss_thread_complete);
12422 return 0;
12425 static int unload_module(void)
12427 #ifdef HAVE_PRI
12428 int y;
12429 for (y = 0; y < NUM_SPANS; y++)
12430 ast_mutex_destroy(&pris[y].lock);
12431 #endif
12432 return __unload_module();
12435 static int build_channels(struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
12437 char *c, *chan;
12438 int x, start, finish;
12439 struct dahdi_pvt *tmp;
12440 #ifdef HAVE_PRI
12441 struct dahdi_pri *pri;
12442 int trunkgroup, y;
12443 #endif
12445 if ((reload == 0) && (conf->chan.sig < 0)) {
12446 ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
12447 return -1;
12450 c = ast_strdupa(value);
12452 #ifdef HAVE_PRI
12453 pri = NULL;
12454 if (iscrv) {
12455 if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
12456 ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
12457 return -1;
12459 if (trunkgroup < 1) {
12460 ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
12461 return -1;
12463 c += y;
12464 for (y = 0; y < NUM_SPANS; y++) {
12465 if (pris[y].trunkgroup == trunkgroup) {
12466 pri = pris + y;
12467 break;
12470 if (!pri) {
12471 ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
12472 return -1;
12475 #endif
12477 while ((chan = strsep(&c, ","))) {
12478 if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
12479 /* Range */
12480 } else if (sscanf(chan, "%d", &start)) {
12481 /* Just one */
12482 finish = start;
12483 } else if (!strcasecmp(chan, "pseudo")) {
12484 finish = start = CHAN_PSEUDO;
12485 if (found_pseudo)
12486 *found_pseudo = 1;
12487 } else {
12488 ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
12489 return -1;
12491 if (finish < start) {
12492 ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
12493 x = finish;
12494 finish = start;
12495 start = x;
12498 for (x = start; x <= finish; x++) {
12499 #ifdef HAVE_PRI
12500 tmp = mkintf(x, conf, pri, reload);
12501 #else
12502 tmp = mkintf(x, conf, NULL, reload);
12503 #endif
12505 if (tmp) {
12506 if (option_verbose > 2) {
12507 #ifdef HAVE_PRI
12508 if (pri)
12509 ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
12510 else
12511 #endif
12512 ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
12514 } else {
12515 ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
12516 (reload == 1) ? "reconfigure" : "register", value);
12517 return -1;
12522 return 0;
12525 /** The length of the parameters list of 'dahdichan'.
12526 * \todo Move definition of MAX_CHANLIST_LEN to a proper place. */
12527 #define MAX_CHANLIST_LEN 80
12528 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
12530 struct dahdi_pvt *tmp;
12531 int y;
12532 int found_pseudo = 0;
12533 char dahdichan[MAX_CHANLIST_LEN] = {};
12535 for (; v; v = v->next) {
12536 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
12537 continue;
12539 /* Create the interface list */
12540 if (!strcasecmp(v->name, "channel")
12541 #ifdef HAVE_PRI
12542 || !strcasecmp(v->name, "crv")
12543 #endif
12545 int iscrv;
12546 if (skipchannels)
12547 continue;
12548 iscrv = !strcasecmp(v->name, "crv");
12549 if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
12550 return -1;
12551 } else if (!strcasecmp(v->name, "buffers")) {
12552 int res;
12553 char policy[8] = "";
12554 res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
12555 if (res != 2) {
12556 ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
12557 confp->chan.buf_no = numbufs;
12558 continue;
12560 if (confp->chan.buf_no < 0)
12561 confp->chan.buf_no = numbufs;
12562 if (!strcasecmp(policy, "full")) {
12563 confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
12564 } else if (!strcasecmp(policy, "half")) {
12565 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /* TODO: change to HALF_FULL */;
12566 } else if (!strcasecmp(policy, "immediate")) {
12567 confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
12568 } else {
12569 ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
12571 } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
12572 ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
12573 if (v->name[0] == 'z' || v->name[0] == 'Z') {
12574 ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
12576 } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
12577 if (ast_true(v->value))
12578 confp->chan.usedistinctiveringdetection = 1;
12579 } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
12580 if (ast_true(v->value))
12581 distinctiveringaftercid = 1;
12582 } else if (!strcasecmp(v->name, "dring1context")) {
12583 ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
12584 } else if (!strcasecmp(v->name, "dring2context")) {
12585 ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
12586 } else if (!strcasecmp(v->name, "dring3context")) {
12587 ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
12588 } else if (!strcasecmp(v->name, "dring1")) {
12589 sscanf(v->value, "%d,%d,%d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
12590 } else if (!strcasecmp(v->name, "dring2")) {
12591 sscanf(v->value, "%d,%d,%d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
12592 } else if (!strcasecmp(v->name, "dring3")) {
12593 sscanf(v->value, "%d,%d,%d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
12594 } else if (!strcasecmp(v->name, "usecallerid")) {
12595 confp->chan.use_callerid = ast_true(v->value);
12596 } else if (!strcasecmp(v->name, "cidsignalling")) {
12597 if (!strcasecmp(v->value, "bell"))
12598 confp->chan.cid_signalling = CID_SIG_BELL;
12599 else if (!strcasecmp(v->value, "v23"))
12600 confp->chan.cid_signalling = CID_SIG_V23;
12601 else if (!strcasecmp(v->value, "dtmf"))
12602 confp->chan.cid_signalling = CID_SIG_DTMF;
12603 else if (!strcasecmp(v->value, "smdi"))
12604 confp->chan.cid_signalling = CID_SIG_SMDI;
12605 else if (!strcasecmp(v->value, "v23_jp"))
12606 confp->chan.cid_signalling = CID_SIG_V23_JP;
12607 else if (ast_true(v->value))
12608 confp->chan.cid_signalling = CID_SIG_BELL;
12609 } else if (!strcasecmp(v->name, "cidstart")) {
12610 if (!strcasecmp(v->value, "ring"))
12611 confp->chan.cid_start = CID_START_RING;
12612 else if (!strcasecmp(v->value, "polarity"))
12613 confp->chan.cid_start = CID_START_POLARITY;
12614 else if (ast_true(v->value))
12615 confp->chan.cid_start = CID_START_RING;
12616 } else if (!strcasecmp(v->name, "threewaycalling")) {
12617 confp->chan.threewaycalling = ast_true(v->value);
12618 } else if (!strcasecmp(v->name, "cancallforward")) {
12619 confp->chan.cancallforward = ast_true(v->value);
12620 } else if (!strcasecmp(v->name, "relaxdtmf")) {
12621 if (ast_true(v->value))
12622 confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
12623 else
12624 confp->chan.dtmfrelax = 0;
12625 } else if (!strcasecmp(v->name, "mailbox")) {
12626 ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
12627 } else if (!strcasecmp(v->name, "hasvoicemail")) {
12628 if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
12629 ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
12631 } else if (!strcasecmp(v->name, "adsi")) {
12632 confp->chan.adsi = ast_true(v->value);
12633 } else if (!strcasecmp(v->name, "usesmdi")) {
12634 confp->chan.use_smdi = ast_true(v->value);
12635 } else if (!strcasecmp(v->name, "smdiport")) {
12636 ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
12637 } else if (!strcasecmp(v->name, "transfer")) {
12638 confp->chan.transfer = ast_true(v->value);
12639 } else if (!strcasecmp(v->name, "canpark")) {
12640 confp->chan.canpark = ast_true(v->value);
12641 } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
12642 confp->chan.echocanbridged = ast_true(v->value);
12643 } else if (!strcasecmp(v->name, "busydetect")) {
12644 confp->chan.busydetect = ast_true(v->value);
12645 } else if (!strcasecmp(v->name, "busycount")) {
12646 confp->chan.busycount = atoi(v->value);
12647 } else if (!strcasecmp(v->name, "busypattern")) {
12648 if (sscanf(v->value, "%d,%d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
12649 ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength\n");
12651 } else if (!strcasecmp(v->name, "callprogress")) {
12652 if (ast_true(v->value))
12653 confp->chan.callprogress |= 1;
12654 else
12655 confp->chan.callprogress &= ~1;
12656 } else if (!strcasecmp(v->name, "faxdetect")) {
12657 if (!strcasecmp(v->value, "incoming")) {
12658 confp->chan.callprogress |= 4;
12659 confp->chan.callprogress &= ~2;
12660 } else if (!strcasecmp(v->value, "outgoing")) {
12661 confp->chan.callprogress &= ~4;
12662 confp->chan.callprogress |= 2;
12663 } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
12664 confp->chan.callprogress |= 6;
12665 else
12666 confp->chan.callprogress &= ~6;
12667 } else if (!strcasecmp(v->name, "echocancel")) {
12668 if (!ast_strlen_zero(v->value)) {
12669 y = atoi(v->value);
12670 } else
12671 y = 0;
12672 if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
12673 confp->chan.echocancel = y;
12674 else {
12675 confp->chan.echocancel = ast_true(v->value);
12676 if (confp->chan.echocancel)
12677 confp->chan.echocancel=128;
12679 } else if (!strcasecmp(v->name, "echotraining")) {
12680 if (sscanf(v->value, "%d", &y) == 1) {
12681 if ((y < 10) || (y > 4000)) {
12682 ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);
12683 } else {
12684 confp->chan.echotraining = y;
12686 } else if (ast_true(v->value)) {
12687 confp->chan.echotraining = 400;
12688 } else
12689 confp->chan.echotraining = 0;
12690 } else if (!strcasecmp(v->name, "hidecallerid")) {
12691 confp->chan.hidecallerid = ast_true(v->value);
12692 } else if (!strcasecmp(v->name, "hidecalleridname")) {
12693 confp->chan.hidecalleridname = ast_true(v->value);
12694 } else if (!strcasecmp(v->name, "pulsedial")) {
12695 confp->chan.pulse = ast_true(v->value);
12696 } else if (!strcasecmp(v->name, "callreturn")) {
12697 confp->chan.callreturn = ast_true(v->value);
12698 } else if (!strcasecmp(v->name, "callwaiting")) {
12699 confp->chan.callwaiting = ast_true(v->value);
12700 } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
12701 confp->chan.callwaitingcallerid = ast_true(v->value);
12702 } else if (!strcasecmp(v->name, "context")) {
12703 ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
12704 } else if (!strcasecmp(v->name, "language")) {
12705 ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
12706 } else if (!strcasecmp(v->name, "progzone")) {
12707 ast_copy_string(progzone, v->value, sizeof(progzone));
12708 } else if (!strcasecmp(v->name, "mohinterpret")
12709 ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
12710 ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
12711 } else if (!strcasecmp(v->name, "mohsuggest")) {
12712 ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
12713 } else if (!strcasecmp(v->name, "stripmsd")) {
12714 confp->chan.stripmsd = atoi(v->value);
12715 } else if (!strcasecmp(v->name, "jitterbuffers")) {
12716 numbufs = atoi(v->value);
12717 } else if (!strcasecmp(v->name, "group")) {
12718 confp->chan.group = ast_get_group(v->value);
12719 } else if (!strcasecmp(v->name, "callgroup")) {
12720 confp->chan.callgroup = ast_get_group(v->value);
12721 } else if (!strcasecmp(v->name, "pickupgroup")) {
12722 confp->chan.pickupgroup = ast_get_group(v->value);
12723 } else if (!strcasecmp(v->name, "immediate")) {
12724 confp->chan.immediate = ast_true(v->value);
12725 } else if (!strcasecmp(v->name, "transfertobusy")) {
12726 confp->chan.transfertobusy = ast_true(v->value);
12727 } else if (!strcasecmp(v->name, "rxgain")) {
12728 if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
12729 ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
12731 } else if (!strcasecmp(v->name, "txgain")) {
12732 if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
12733 ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
12735 } else if (!strcasecmp(v->name, "tonezone")) {
12736 if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
12737 ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
12739 } else if (!strcasecmp(v->name, "callerid")) {
12740 if (!strcasecmp(v->value, "asreceived")) {
12741 confp->chan.cid_num[0] = '\0';
12742 confp->chan.cid_name[0] = '\0';
12743 } else {
12744 ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
12746 } else if (!strcasecmp(v->name, "fullname")) {
12747 ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
12748 } else if (!strcasecmp(v->name, "cid_number")) {
12749 ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
12750 } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
12751 confp->chan.dahditrcallerid = ast_true(v->value);
12752 if (strstr(v->name, "zap")) {
12753 ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
12755 } else if (!strcasecmp(v->name, "restrictcid")) {
12756 confp->chan.restrictcid = ast_true(v->value);
12757 } else if (!strcasecmp(v->name, "usecallingpres")) {
12758 confp->chan.use_callingpres = ast_true(v->value);
12759 } else if (!strcasecmp(v->name, "accountcode")) {
12760 ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
12761 } else if (!strcasecmp(v->name, "amaflags")) {
12762 y = ast_cdr_amaflags2int(v->value);
12763 if (y < 0)
12764 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
12765 else
12766 confp->chan.amaflags = y;
12767 } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
12768 confp->chan.polarityonanswerdelay = atoi(v->value);
12769 } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
12770 confp->chan.answeronpolarityswitch = ast_true(v->value);
12771 } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
12772 confp->chan.hanguponpolarityswitch = ast_true(v->value);
12773 } else if (!strcasecmp(v->name, "sendcalleridafter")) {
12774 confp->chan.sendcalleridafter = atoi(v->value);
12775 } else if (reload != 1){
12776 if (!strcasecmp(v->name, "signalling")) {
12777 confp->chan.outsigmod = -1;
12778 if (!strcasecmp(v->value, "em")) {
12779 confp->chan.sig = SIG_EM;
12780 } else if (!strcasecmp(v->value, "em_e1")) {
12781 confp->chan.sig = SIG_EM_E1;
12782 } else if (!strcasecmp(v->value, "em_w")) {
12783 confp->chan.sig = SIG_EMWINK;
12784 confp->chan.radio = 0;
12785 } else if (!strcasecmp(v->value, "fxs_ls")) {
12786 confp->chan.sig = SIG_FXSLS;
12787 confp->chan.radio = 0;
12788 } else if (!strcasecmp(v->value, "fxs_gs")) {
12789 confp->chan.sig = SIG_FXSGS;
12790 confp->chan.radio = 0;
12791 } else if (!strcasecmp(v->value, "fxs_ks")) {
12792 confp->chan.sig = SIG_FXSKS;
12793 confp->chan.radio = 0;
12794 } else if (!strcasecmp(v->value, "fxo_ls")) {
12795 confp->chan.sig = SIG_FXOLS;
12796 confp->chan.radio = 0;
12797 } else if (!strcasecmp(v->value, "fxo_gs")) {
12798 confp->chan.sig = SIG_FXOGS;
12799 confp->chan.radio = 0;
12800 } else if (!strcasecmp(v->value, "fxo_ks")) {
12801 confp->chan.sig = SIG_FXOKS;
12802 confp->chan.radio = 0;
12803 } else if (!strcasecmp(v->value, "fxs_rx")) {
12804 confp->chan.sig = SIG_FXSKS;
12805 confp->chan.radio = 1;
12806 } else if (!strcasecmp(v->value, "fxo_rx")) {
12807 confp->chan.sig = SIG_FXOLS;
12808 confp->chan.radio = 1;
12809 } else if (!strcasecmp(v->value, "fxs_tx")) {
12810 confp->chan.sig = SIG_FXSLS;
12811 confp->chan.radio = 1;
12812 } else if (!strcasecmp(v->value, "fxo_tx")) {
12813 confp->chan.sig = SIG_FXOGS;
12814 confp->chan.radio = 1;
12815 } else if (!strcasecmp(v->value, "em_rx")) {
12816 confp->chan.sig = SIG_EM;
12817 confp->chan.radio = 1;
12818 } else if (!strcasecmp(v->value, "em_tx")) {
12819 confp->chan.sig = SIG_EM;
12820 confp->chan.radio = 1;
12821 } else if (!strcasecmp(v->value, "em_rxtx")) {
12822 confp->chan.sig = SIG_EM;
12823 confp->chan.radio = 2;
12824 } else if (!strcasecmp(v->value, "em_txrx")) {
12825 confp->chan.sig = SIG_EM;
12826 confp->chan.radio = 2;
12827 } else if (!strcasecmp(v->value, "sf")) {
12828 confp->chan.sig = SIG_SF;
12829 confp->chan.radio = 0;
12830 } else if (!strcasecmp(v->value, "sf_w")) {
12831 confp->chan.sig = SIG_SFWINK;
12832 confp->chan.radio = 0;
12833 } else if (!strcasecmp(v->value, "sf_featd")) {
12834 confp->chan.sig = SIG_FEATD;
12835 confp->chan.radio = 0;
12836 } else if (!strcasecmp(v->value, "sf_featdmf")) {
12837 confp->chan.sig = SIG_FEATDMF;
12838 confp->chan.radio = 0;
12839 } else if (!strcasecmp(v->value, "sf_featb")) {
12840 confp->chan.sig = SIG_SF_FEATB;
12841 confp->chan.radio = 0;
12842 } else if (!strcasecmp(v->value, "sf")) {
12843 confp->chan.sig = SIG_SF;
12844 confp->chan.radio = 0;
12845 } else if (!strcasecmp(v->value, "sf_rx")) {
12846 confp->chan.sig = SIG_SF;
12847 confp->chan.radio = 1;
12848 } else if (!strcasecmp(v->value, "sf_tx")) {
12849 confp->chan.sig = SIG_SF;
12850 confp->chan.radio = 1;
12851 } else if (!strcasecmp(v->value, "sf_rxtx")) {
12852 confp->chan.sig = SIG_SF;
12853 confp->chan.radio = 2;
12854 } else if (!strcasecmp(v->value, "sf_txrx")) {
12855 confp->chan.sig = SIG_SF;
12856 confp->chan.radio = 2;
12857 } else if (!strcasecmp(v->value, "featd")) {
12858 confp->chan.sig = SIG_FEATD;
12859 confp->chan.radio = 0;
12860 } else if (!strcasecmp(v->value, "featdmf")) {
12861 confp->chan.sig = SIG_FEATDMF;
12862 confp->chan.radio = 0;
12863 } else if (!strcasecmp(v->value, "featdmf_ta")) {
12864 confp->chan.sig = SIG_FEATDMF_TA;
12865 confp->chan.radio = 0;
12866 } else if (!strcasecmp(v->value, "e911")) {
12867 confp->chan.sig = SIG_E911;
12868 confp->chan.radio = 0;
12869 } else if (!strcasecmp(v->value, "fgccama")) {
12870 confp->chan.sig = SIG_FGC_CAMA;
12871 confp->chan.radio = 0;
12872 } else if (!strcasecmp(v->value, "fgccamamf")) {
12873 confp->chan.sig = SIG_FGC_CAMAMF;
12874 confp->chan.radio = 0;
12875 } else if (!strcasecmp(v->value, "featb")) {
12876 confp->chan.sig = SIG_FEATB;
12877 confp->chan.radio = 0;
12878 #ifdef HAVE_PRI
12879 } else if (!strcasecmp(v->value, "pri_net")) {
12880 confp->chan.radio = 0;
12881 confp->chan.sig = SIG_PRI;
12882 confp->pri.nodetype = PRI_NETWORK;
12883 } else if (!strcasecmp(v->value, "pri_cpe")) {
12884 confp->chan.sig = SIG_PRI;
12885 confp->chan.radio = 0;
12886 confp->pri.nodetype = PRI_CPE;
12887 } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
12888 confp->chan.sig = SIG_GR303FXOKS;
12889 confp->chan.radio = 0;
12890 confp->pri.nodetype = PRI_NETWORK;
12891 } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
12892 confp->chan.sig = SIG_GR303FXSKS;
12893 confp->chan.radio = 0;
12894 confp->pri.nodetype = PRI_CPE;
12895 } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
12896 confp->chan.radio = 0;
12897 confp->chan.sig = SIG_PRI;
12898 confp->pri.nodetype = BRI_NETWORK_PTMP;
12899 } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
12900 confp->chan.sig = SIG_PRI;
12901 confp->chan.radio = 0;
12902 confp->pri.nodetype = BRI_CPE_PTMP;
12903 } else if (!strcasecmp(v->value, "bri_net")) {
12904 confp->chan.radio = 0;
12905 confp->chan.sig = SIG_PRI;
12906 confp->pri.nodetype = BRI_NETWORK;
12907 } else if (!strcasecmp(v->value, "bri_cpe")) {
12908 confp->chan.sig = SIG_PRI;
12909 confp->chan.radio = 0;
12910 confp->pri.nodetype = BRI_CPE;
12911 #endif
12912 #ifdef HAVE_GSMAT
12913 } else if (!strcasecmp(v->value, "gsm")) {
12914 confp->chan.sig = SIG_GSM;
12915 confp->chan.radio = 0;
12916 #endif
12917 } else {
12918 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
12920 } else if (!strcasecmp(v->name, "outsignalling")) {
12921 if (!strcasecmp(v->value, "em")) {
12922 confp->chan.outsigmod = SIG_EM;
12923 } else if (!strcasecmp(v->value, "em_e1")) {
12924 confp->chan.outsigmod = SIG_EM_E1;
12925 } else if (!strcasecmp(v->value, "em_w")) {
12926 confp->chan.outsigmod = SIG_EMWINK;
12927 } else if (!strcasecmp(v->value, "sf")) {
12928 confp->chan.outsigmod = SIG_SF;
12929 } else if (!strcasecmp(v->value, "sf_w")) {
12930 confp->chan.outsigmod = SIG_SFWINK;
12931 } else if (!strcasecmp(v->value, "sf_featd")) {
12932 confp->chan.outsigmod = SIG_FEATD;
12933 } else if (!strcasecmp(v->value, "sf_featdmf")) {
12934 confp->chan.outsigmod = SIG_FEATDMF;
12935 } else if (!strcasecmp(v->value, "sf_featb")) {
12936 confp->chan.outsigmod = SIG_SF_FEATB;
12937 } else if (!strcasecmp(v->value, "sf")) {
12938 confp->chan.outsigmod = SIG_SF;
12939 } else if (!strcasecmp(v->value, "featd")) {
12940 confp->chan.outsigmod = SIG_FEATD;
12941 } else if (!strcasecmp(v->value, "featdmf")) {
12942 confp->chan.outsigmod = SIG_FEATDMF;
12943 } else if (!strcasecmp(v->value, "featdmf_ta")) {
12944 confp->chan.outsigmod = SIG_FEATDMF_TA;
12945 } else if (!strcasecmp(v->value, "e911")) {
12946 confp->chan.outsigmod = SIG_E911;
12947 } else if (!strcasecmp(v->value, "fgccama")) {
12948 confp->chan.outsigmod = SIG_FGC_CAMA;
12949 } else if (!strcasecmp(v->value, "fgccamamf")) {
12950 confp->chan.outsigmod = SIG_FGC_CAMAMF;
12951 } else if (!strcasecmp(v->value, "featb")) {
12952 confp->chan.outsigmod = SIG_FEATB;
12953 } else {
12954 ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
12956 #ifdef HAVE_PRI
12957 } else if (!strcasecmp(v->name, "pridialplan")) {
12958 if (!strcasecmp(v->value, "national")) {
12959 confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
12960 } else if (!strcasecmp(v->value, "unknown")) {
12961 confp->pri.dialplan = PRI_UNKNOWN + 1;
12962 } else if (!strcasecmp(v->value, "private")) {
12963 confp->pri.dialplan = PRI_PRIVATE + 1;
12964 } else if (!strcasecmp(v->value, "international")) {
12965 confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
12966 } else if (!strcasecmp(v->value, "local")) {
12967 confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
12968 } else if (!strcasecmp(v->value, "dynamic")) {
12969 confp->pri.dialplan = -1;
12970 } else {
12971 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
12973 } else if (!strcasecmp(v->name, "prilocaldialplan")) {
12974 if (!strcasecmp(v->value, "national")) {
12975 confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
12976 } else if (!strcasecmp(v->value, "unknown")) {
12977 confp->pri.localdialplan = PRI_UNKNOWN + 1;
12978 } else if (!strcasecmp(v->value, "private")) {
12979 confp->pri.localdialplan = PRI_PRIVATE + 1;
12980 } else if (!strcasecmp(v->value, "international")) {
12981 confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
12982 } else if (!strcasecmp(v->value, "local")) {
12983 confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
12984 } else if (!strcasecmp(v->value, "dynamic")) {
12985 confp->pri.localdialplan = -1;
12986 } else {
12987 ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
12989 } else if (!strcasecmp(v->name, "switchtype")) {
12990 if (!strcasecmp(v->value, "national"))
12991 confp->pri.switchtype = PRI_SWITCH_NI2;
12992 else if (!strcasecmp(v->value, "ni1"))
12993 confp->pri.switchtype = PRI_SWITCH_NI1;
12994 else if (!strcasecmp(v->value, "dms100"))
12995 confp->pri.switchtype = PRI_SWITCH_DMS100;
12996 else if (!strcasecmp(v->value, "4ess"))
12997 confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
12998 else if (!strcasecmp(v->value, "5ess"))
12999 confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
13000 else if (!strcasecmp(v->value, "euroisdn"))
13001 confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
13002 else if (!strcasecmp(v->value, "qsig"))
13003 confp->pri.switchtype = PRI_SWITCH_QSIG;
13004 else {
13005 ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
13006 return -1;
13008 } else if (!strcasecmp(v->name, "nsf")) {
13009 if (!strcasecmp(v->value, "sdn"))
13010 confp->pri.nsf = PRI_NSF_SDN;
13011 else if (!strcasecmp(v->value, "megacom"))
13012 confp->pri.nsf = PRI_NSF_MEGACOM;
13013 else if (!strcasecmp(v->value, "tollfreemegacom"))
13014 confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
13015 else if (!strcasecmp(v->value, "accunet"))
13016 confp->pri.nsf = PRI_NSF_ACCUNET;
13017 else if (!strcasecmp(v->value, "none"))
13018 confp->pri.nsf = PRI_NSF_NONE;
13019 else {
13020 ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
13021 confp->pri.nsf = PRI_NSF_NONE;
13023 } else if (!strcasecmp(v->name, "priindication")) {
13024 if (!strcasecmp(v->value, "outofband"))
13025 confp->chan.priindication_oob = 1;
13026 else if (!strcasecmp(v->value, "inband"))
13027 confp->chan.priindication_oob = 0;
13028 else if (!strcasecmp(v->value, "passthrough"))
13029 confp->chan.priindication_oob = 2;
13030 else
13031 ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband', 'outofband' or 'passthrough' at line %d\n",
13032 v->value, v->lineno);
13033 } else if (!strcasecmp(v->name, "pritransfer")) {
13034 if (!strcasecmp(v->value, "no"))
13035 confp->chan.pritransfer = 0;
13036 else if (!strcasecmp(v->value, "ect"))
13037 confp->chan.pritransfer = 1;
13038 else if (!strcasecmp(v->value, "hangup"))
13039 confp->chan.pritransfer = 2;
13040 else
13041 ast_log(LOG_WARNING, "'%s' is not a valid pri transfer value, should be 'no' , 'ect' or 'hangup' at line %d\n",
13042 v->value, v->lineno);
13043 } else if (!strcasecmp(v->name, "priexclusive")) {
13044 confp->chan.priexclusive = ast_true(v->value);
13045 } else if (!strcasecmp(v->name, "internationalprefix")) {
13046 ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
13047 } else if (!strcasecmp(v->name, "nationalprefix")) {
13048 ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
13049 } else if (!strcasecmp(v->name, "localprefix")) {
13050 ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
13051 } else if (!strcasecmp(v->name, "privateprefix")) {
13052 ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
13053 } else if (!strcasecmp(v->name, "unknownprefix")) {
13054 ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
13055 } else if (!strcasecmp(v->name, "nocid")) {
13056 ast_copy_string(confp->pri.nocid, v->value, sizeof(confp->pri.nocid));
13057 } else if (!strcasecmp(v->name, "withheldcid")) {
13058 ast_copy_string(confp->pri.withheldcid, v->value, sizeof(confp->pri.withheldcid));
13059 } else if (!strcasecmp(v->name, "pin")) {
13060 ast_copy_string(gsm_modem_pin, v->value, sizeof(gsm_modem_pin) - 1);
13061 } else if (!strcasecmp(v->name, "exten")) {
13062 ast_copy_string(gsm_modem_exten, v->value, sizeof(gsm_modem_exten) - 1);
13063 } else if (!strcasecmp(v->name, "resetinterval")) {
13064 if (!strcasecmp(v->value, "never"))
13065 confp->pri.resetinterval = -1;
13066 else if (atoi(v->value) >= 60)
13067 confp->pri.resetinterval = atoi(v->value);
13068 else
13069 ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
13070 v->value, v->lineno);
13071 } else if (!strcasecmp(v->name, "minunused")) {
13072 confp->pri.minunused = atoi(v->value);
13073 } else if (!strcasecmp(v->name, "minidle")) {
13074 confp->pri.minidle = atoi(v->value);
13075 } else if (!strcasecmp(v->name, "idleext")) {
13076 ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
13077 } else if (!strcasecmp(v->name, "idledial")) {
13078 ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
13079 } else if (!strcasecmp(v->name, "overlapdial")) {
13080 confp->pri.overlapdial = ast_true(v->value);
13081 #ifdef HAVE_PRI_INBANDDISCONNECT
13082 } else if (!strcasecmp(v->name, "inbanddisconnect")) {
13083 confp->pri.inbanddisconnect = ast_true(v->value);
13084 #endif
13085 } else if (!strcasecmp(v->name, "pritimer")) {
13086 #ifdef PRI_GETSET_TIMERS
13087 char *timerc, *c;
13088 int timer, timeridx;
13089 c = v->value;
13090 timerc = strsep(&c, ",");
13091 if (timerc) {
13092 timer = atoi(c);
13093 if (!timer)
13094 ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer\n", timerc);
13095 else {
13096 if ((timeridx = pri_timer2idx(timerc)) >= 0)
13097 pritimers[timeridx] = timer;
13098 else
13099 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer\n", timerc);
13101 } else
13102 ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string\n", v->value);
13104 } else if (!strcasecmp(v->name, "facilityenable")) {
13105 confp->pri.facilityenable = ast_true(v->value);
13106 #endif /* PRI_GETSET_TIMERS */
13107 #endif /* HAVE_PRI */
13108 } else if (!strcasecmp(v->name, "cadence")) {
13109 /* setup to scan our argument */
13110 int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
13111 int i;
13112 struct dahdi_ring_cadence new_cadence;
13113 int cid_location = -1;
13114 int firstcadencepos = 0;
13115 char original_args[80];
13116 int cadence_is_ok = 1;
13118 ast_copy_string(original_args, v->value, sizeof(original_args));
13119 /* 16 cadences allowed (8 pairs) */
13120 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]);
13122 /* Cadence must be even (on/off) */
13123 if (element_count % 2 == 1) {
13124 ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
13125 cadence_is_ok = 0;
13128 /* Ring cadences cannot be negative */
13129 for (i = 0; i < element_count; i++) {
13130 if (c[i] == 0) {
13131 ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
13132 cadence_is_ok = 0;
13133 break;
13134 } else if (c[i] < 0) {
13135 if (i % 2 == 1) {
13136 /* Silence duration, negative possibly okay */
13137 if (cid_location == -1) {
13138 cid_location = i;
13139 c[i] *= -1;
13140 } else {
13141 ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
13142 cadence_is_ok = 0;
13143 break;
13145 } else {
13146 if (firstcadencepos == 0) {
13147 firstcadencepos = i; /* only recorded to avoid duplicate specification */
13148 /* duration will be passed negative to the DAHDI driver */
13149 } else {
13150 ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
13151 cadence_is_ok = 0;
13152 break;
13158 /* Substitute our scanned cadence */
13159 for (i = 0; i < 16; i++) {
13160 new_cadence.ringcadence[i] = c[i];
13163 if (cadence_is_ok) {
13164 /* ---we scanned it without getting annoyed; now some sanity checks--- */
13165 if (element_count < 2) {
13166 ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
13167 } else {
13168 if (cid_location == -1) {
13169 /* user didn't say; default to first pause */
13170 cid_location = 1;
13171 } else {
13172 /* convert element_index to cidrings value */
13173 cid_location = (cid_location + 1) / 2;
13175 /* ---we like their cadence; try to install it--- */
13176 if (!user_has_defined_cadences++)
13177 /* this is the first user-defined cadence; clear the default user cadences */
13178 num_cadence = 0;
13179 if ((num_cadence+1) >= NUM_CADENCE_MAX)
13180 ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
13181 else {
13182 cadences[num_cadence] = new_cadence;
13183 cidrings[num_cadence++] = cid_location;
13184 if (option_verbose > 2)
13185 ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
13189 } else if (!strcasecmp(v->name, "ringtimeout")) {
13190 ringt_base = (atoi(v->value) * 8) / READ_SIZE;
13191 } else if (!strcasecmp(v->name, "prewink")) {
13192 confp->timing.prewinktime = atoi(v->value);
13193 } else if (!strcasecmp(v->name, "preflash")) {
13194 confp->timing.preflashtime = atoi(v->value);
13195 } else if (!strcasecmp(v->name, "wink")) {
13196 confp->timing.winktime = atoi(v->value);
13197 } else if (!strcasecmp(v->name, "flash")) {
13198 confp->timing.flashtime = atoi(v->value);
13199 } else if (!strcasecmp(v->name, "start")) {
13200 confp->timing.starttime = atoi(v->value);
13201 } else if (!strcasecmp(v->name, "rxwink")) {
13202 confp->timing.rxwinktime = atoi(v->value);
13203 } else if (!strcasecmp(v->name, "rxflash")) {
13204 confp->timing.rxflashtime = atoi(v->value);
13205 } else if (!strcasecmp(v->name, "debounce")) {
13206 confp->timing.debouncetime = atoi(v->value);
13207 } else if (!strcasecmp(v->name, "toneduration")) {
13208 int toneduration;
13209 int ctlfd;
13210 int res;
13211 struct dahdi_dialparams dps;
13213 #ifdef HAVE_ZAPTEL
13214 ctlfd = open("/dev/zap/ctl", O_RDWR);
13215 #else
13216 ctlfd = open("/dev/dahdi/ctl", O_RDWR);
13217 #endif
13219 if (ctlfd == -1) {
13220 ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration\n");
13221 return -1;
13224 toneduration = atoi(v->value);
13225 if (toneduration > -1) {
13226 memset(&dps, 0, sizeof(dps));
13228 dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
13229 res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
13230 if (res < 0) {
13231 ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
13232 return -1;
13235 close(ctlfd);
13236 } else if (!strcasecmp(v->name, "defaultcic")) {
13237 ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
13238 } else if (!strcasecmp(v->name, "defaultozz")) {
13239 ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
13241 } else if (!skipchannels)
13242 ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
13244 if (dahdichan[0]) {
13245 /* The user has set 'dahdichan' */
13246 /*< \todo pass proper line number instead of 0 */
13247 if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
13248 return -1;
13251 /*< \todo why check for the pseudo in the per-channel section.
13252 * Any actual use for manual setup of the pseudo channel? */
13253 if (!found_pseudo && reload == 0) {
13254 /* Make sure pseudo isn't a member of any groups if
13255 we're automatically making it. */
13257 confp->chan.group = 0;
13258 confp->chan.callgroup = 0;
13259 confp->chan.pickupgroup = 0;
13261 tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
13263 if (tmp) {
13264 if (option_verbose > 2)
13265 ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
13266 } else {
13267 ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
13270 return 0;
13273 static int setup_dahdi(int reload)
13275 struct ast_config *cfg;
13276 struct ast_variable *v;
13277 struct dahdi_chan_conf conf = dahdi_chan_conf_default();
13278 int res;
13280 #ifdef HAVE_PRI
13281 char *c;
13282 int spanno;
13283 int i, x;
13284 int logicalspan;
13285 int trunkgroup;
13286 int dchannels[NUM_DCHANS];
13287 #endif
13289 #ifdef HAVE_ZAPTEL
13290 int load_from_zapata_conf = 1;
13291 #else
13292 int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
13293 #endif
13295 if (load_from_zapata_conf) {
13296 if (!(cfg = ast_config_load("zapata.conf"))) {
13297 ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
13298 return 0;
13300 } else {
13301 if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
13302 ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
13303 return 0;
13307 /* It's a little silly to lock it, but we mind as well just to be sure */
13308 ast_mutex_lock(&iflock);
13309 #ifdef HAVE_PRI
13310 if (reload != 1) {
13311 /* Process trunkgroups first */
13312 v = ast_variable_browse(cfg, "trunkgroups");
13313 while (v) {
13314 if (!strcasecmp(v->name, "trunkgroup")) {
13315 trunkgroup = atoi(v->value);
13316 if (trunkgroup > 0) {
13317 if ((c = strchr(v->value, ','))) {
13318 i = 0;
13319 memset(dchannels, 0, sizeof(dchannels));
13320 while (c && (i < NUM_DCHANS)) {
13321 dchannels[i] = atoi(c + 1);
13322 if (dchannels[i] < 0) {
13323 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);
13324 } else
13325 i++;
13326 c = strchr(c + 1, ',');
13328 if (i) {
13329 if (pri_create_trunkgroup(trunkgroup, dchannels)) {
13330 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);
13331 } else if (option_verbose > 1)
13332 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");
13333 } else
13334 ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13335 } else
13336 ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
13337 } else
13338 ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
13339 } else if (!strcasecmp(v->name, "spanmap")) {
13340 spanno = atoi(v->value);
13341 if (spanno > 0) {
13342 if ((c = strchr(v->value, ','))) {
13343 trunkgroup = atoi(c + 1);
13344 if (trunkgroup > 0) {
13345 if ((c = strchr(c + 1, ',')))
13346 logicalspan = atoi(c + 1);
13347 else
13348 logicalspan = 0;
13349 if (logicalspan >= 0) {
13350 if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
13351 ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13352 } else if (option_verbose > 1)
13353 ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
13354 } else
13355 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);
13356 } else
13357 ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
13358 } else
13359 ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
13360 } else
13361 ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
13362 } else {
13363 ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
13365 v = v->next;
13368 #endif
13370 /* Copy the default jb config over global_jbconf */
13371 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
13373 v = ast_variable_browse(cfg, "channels");
13374 res = process_dahdi(&conf, "", v, reload, 0);
13375 ast_mutex_unlock(&iflock);
13376 ast_config_destroy(cfg);
13377 if (res)
13378 return res;
13379 cfg = ast_config_load("users.conf");
13380 if (cfg) {
13381 char *cat;
13382 const char *chans;
13383 process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
13384 for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
13385 if (!strcasecmp(cat, "general"))
13386 continue;
13387 chans = ast_variable_retrieve(cfg, cat, "dahdichan");
13388 if (!ast_strlen_zero(chans)) {
13389 struct dahdi_chan_conf sect_conf;
13390 memcpy(&sect_conf, &conf, sizeof(sect_conf));
13392 process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
13395 ast_config_destroy(cfg);
13397 #ifdef HAVE_PRI
13398 if (reload != 1) {
13399 for (x = 0; x < NUM_SPANS; x++) {
13400 pris[x].debugfd = -1;
13401 if (pris[x].pvts[0]) {
13402 if (start_pri(pris + x)) {
13403 ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
13404 return -1;
13405 } else if (option_verbose > 1)
13406 ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
13410 #endif
13411 /* And start the monitor for the first time */
13412 restart_monitor();
13413 return 0;
13416 #define local_astman_register(a, b, c, d) do { \
13417 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) { \
13418 ast_manager_register("DAHDI" a, b, dahdi_ ## c, d); \
13420 ast_manager_register("Zap" a, b, zap_ ## c, d); \
13421 } while (0)
13423 static int load_module(void)
13425 int res;
13427 #ifdef HAVE_PRI
13428 int y,i;
13429 memset(pris, 0, sizeof(pris));
13430 for (y = 0; y < NUM_SPANS; y++) {
13431 ast_mutex_init(&pris[y].lock);
13432 pris[y].offset = -1;
13433 pris[y].master = AST_PTHREADT_NULL;
13434 for (i = 0; i < NUM_DCHANS; i++)
13435 pris[y].fds[i] = -1;
13437 pri_set_error(dahdi_pri_error);
13438 pri_set_message(dahdi_pri_message);
13439 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13440 ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
13441 dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
13443 ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
13444 zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
13445 #endif
13446 #ifdef HAVE_GSMAT
13447 gsm_set_error(dahdi_gsm_error);
13448 gsm_set_message(dahdi_gsm_message);
13449 #endif
13450 if ((res = setup_dahdi(0))) {
13451 return AST_MODULE_LOAD_DECLINE;
13453 if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
13454 chan_tech = &dahdi_tech;
13455 } else {
13456 chan_tech = &zap_tech;
13458 if (ast_channel_register(chan_tech)) {
13459 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
13460 __unload_module();
13461 return -1;
13463 #ifdef HAVE_PRI
13464 ast_string_field_init(&inuse, 16);
13465 ast_string_field_set(&inuse, name, "GR-303InUse");
13466 ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
13467 ast_register_application(zapCD_app, app_zapCD, zapCD_synopsis, zapCD_tdesc);
13468 ast_register_application(zapInband_app, app_zapInband, zapInband_synopsis, zapInband_tdesc);
13469 #endif
13470 ast_register_application(zapEC_app, app_zapEC, zapEC_synopsis, zapEC_tdesc);
13471 ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13472 #ifdef HAVE_GSMAT
13473 ast_cli_register(&gsm_send_sms);
13474 ast_cli_register(&gsm_send_pdu);
13475 ast_cli_register(&gsm_show_status);
13476 ast_cli_register_multiple(zap_gsm_cli, sizeof(zap_gsm_cli) / sizeof(zap_gsm_cli[0]));
13477 #endif
13479 memset(round_robin, 0, sizeof(round_robin));
13480 local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
13481 local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
13482 local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
13483 local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
13484 local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
13485 local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
13486 local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
13488 ast_cond_init(&ss_thread_complete, NULL);
13490 return res;
13493 #ifdef HAVE_PRI
13494 static int dahdi_tdd_sendtext(struct ast_channel *c, const char *text);
13496 static int dahdi_pri_sendtext(struct ast_channel *c, const char *text) {
13497 struct dahdi_pvt *p = c->tech_pvt;
13498 if (!p) return -1;
13499 if (!p->pri) return -1;
13500 if (strlen(text)) {
13501 if (p->pri) {
13502 if (!pri_grab(p, p->pri)) {
13503 // ast_log(LOG_NOTICE, "Sending Display IE '%s'\n", text);
13504 pri_information_display(p->pri->pri,p->call,(char *)text);
13505 pri_rel(p->pri);
13506 } else ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
13509 return 0;
13511 #endif
13513 static int dahdi_sendtext(struct ast_channel *c, const char *text) {
13514 struct dahdi_pvt *p = c->tech_pvt;
13515 if (!p) return -1;
13516 if (p->sig == SIG_PRI) {
13517 #ifdef HAVE_PRI
13518 return dahdi_pri_sendtext(c, text);
13519 #endif
13520 } else if (p->sig == SIG_GSM) {
13521 } else {
13522 return dahdi_tdd_sendtext(c, text);
13524 return -1;
13527 static int dahdi_sendmessage(struct ast_channel *c, const char *dest, const char *text, int ispdu) {
13528 struct dahdi_pvt *p = c->tech_pvt;
13529 if (!p) return -1;
13530 if (p->sig == SIG_PRI) {
13531 #ifdef HAVE_PRI
13532 if (ispdu) {
13533 ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP ISDN channel\n");
13534 return -1;
13536 return dahdi_pri_sendtext(c, text);
13537 #endif
13538 } else if (p->sig == SIG_GSM) {
13539 #ifdef HAVE_GSMAT
13540 return dahdi_gsm_sendtext(c, dest, text, ispdu);
13541 #endif
13542 } else {
13543 if (ispdu) {
13544 ast_log(LOG_WARNING, "Dont know how to send PDU on ZAP channel\n");
13545 return -1;
13547 return dahdi_tdd_sendtext(c, text);
13549 return -1;
13552 static int dahdi_tdd_sendtext(struct ast_channel *c, const char *text)
13554 #define END_SILENCE_LEN 400
13555 #define HEADER_MS 50
13556 #define TRAILER_MS 5
13557 #define HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
13558 #define ASCII_BYTES_PER_CHAR 80
13560 unsigned char *buf,*mybuf;
13561 struct dahdi_pvt *p = c->tech_pvt;
13562 struct pollfd fds[1];
13563 int size,res,fd,len,x;
13564 int bytes=0;
13565 /* Initial carrier (imaginary) */
13566 float cr = 1.0;
13567 float ci = 0.0;
13568 float scont = 0.0;
13569 int index;
13571 index = dahdi_get_index(c, p, 0);
13572 if (index < 0) {
13573 ast_log(LOG_WARNING, "Huh? I don't exist?\n");
13574 return -1;
13576 if (!text[0]) return(0); /* if nothing to send, dont */
13577 if ((!p->tdd) && (!p->mate)) return(0); /* if not in TDD mode, just return */
13578 if (p->mate)
13579 buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
13580 else
13581 buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
13582 if (!buf)
13583 return -1;
13584 mybuf = buf;
13585 if (p->mate) {
13586 int codec = AST_LAW(p);
13587 for (x = 0; x < HEADER_MS; x++) { /* 50 ms of Mark */
13588 PUT_CLID_MARKMS;
13590 /* Put actual message */
13591 for (x = 0; text[x]; x++) {
13592 PUT_CLID(text[x]);
13594 for (x = 0; x < TRAILER_MS; x++) { /* 5 ms of Mark */
13595 PUT_CLID_MARKMS;
13597 len = bytes;
13598 buf = mybuf;
13599 } else {
13600 len = tdd_generate(p->tdd, buf, text);
13601 if (len < 1) {
13602 ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
13603 free(mybuf);
13604 return -1;
13607 memset(buf + len, 0x7f, END_SILENCE_LEN);
13608 len += END_SILENCE_LEN;
13609 fd = p->subs[index].dfd;
13610 while (len) {
13611 if (ast_check_hangup(c)) {
13612 free(mybuf);
13613 return -1;
13615 size = len;
13616 if (size > READ_SIZE)
13617 size = READ_SIZE;
13618 fds[0].fd = fd;
13619 fds[0].events = POLLOUT | POLLPRI;
13620 fds[0].revents = 0;
13621 res = poll(fds, 1, -1);
13622 if (!res) {
13623 ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
13624 continue;
13626 /* if got exception */
13627 if (fds[0].revents & POLLPRI) {
13628 ast_free(mybuf);
13629 return -1;
13631 if (!(fds[0].revents & POLLOUT)) {
13632 ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
13633 continue;
13635 res = write(fd, buf, size);
13636 if (res != size) {
13637 if (res == -1) {
13638 free(mybuf);
13639 return -1;
13641 if (option_debug)
13642 ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
13643 break;
13645 len -= size;
13646 buf += size;
13648 free(mybuf);
13649 return(0);
13653 static int reload(void)
13655 int res = 0;
13657 res = setup_dahdi(1);
13658 if (res) {
13659 ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
13660 return -1;
13662 return 0;
13665 /* This is a workaround so that menuselect displays a proper description
13666 * AST_MODULE_INFO(, , "DAHDI Telephony"
13669 #ifdef DAHDI_PRI
13670 #define tdesc "DAHDI Telephony w/PRI"
13671 #else
13672 #define tdesc "DAHDI Telephony"
13673 #endif
13675 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
13676 .load = load_module,
13677 .unload = unload_module,
13678 .reload = reload,