Thu Oct 8 00:59:22 2009

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI Pseudo TDM interface. More...

#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <sys/signal.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <libpri.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/file.h"
#include "asterisk/ulaw.h"
#include "asterisk/alaw.h"
#include "asterisk/callerid.h"
#include "asterisk/adsi.h"
#include "asterisk/cli.h"
#include "asterisk/cdr.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/tdd.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/astdb.h"
#include "asterisk/manager.h"
#include "asterisk/causes.h"
#include "asterisk/term.h"
#include "asterisk/utils.h"
#include "asterisk/transcap.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"
#include "asterisk/dahdi_compat.h"
#include "asterisk/tonezone_compat.h"

Go to the source code of this file.

Data Structures

struct  dahdi_chan_conf
 Channel configuration from chan_dahdi.conf . This struct is used for parsing the [channels] section of chan_dahdi.conf. Generally there is a field here for every possible configuration item. More...
struct  dahdi_distRings
struct  dahdi_pri
struct  dahdi_pvt
struct  dahdi_subchannel
struct  distRingData
struct  ringContextData

Defines

#define ASCII_BYTES_PER_CHAR   80
#define AST_LAW(p)   (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)
#define CALLWAITING_REPEAT_SAMPLES   ( (10000 * 8) / READ_SIZE)
#define CALLWAITING_SILENT_SAMPLES   ( (300 * 8) / READ_SIZE)
#define CANBUSYDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CANPROGRESSDETECT(p)   (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)
#define CHAN_PSEUDO   -2
#define CHANNEL_PSEUDO   -12
#define CIDCW_EXPIRE_SAMPLES   ( (500 * 8) / READ_SIZE)
#define CONF_USER_REAL   (1 << 0)
#define CONF_USER_THIRDCALL   (1 << 1)
#define DAHDI_EVENT_DTMFDOWN   0
#define DAHDI_EVENT_DTMFUP   0
#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
#define DCHAN_NOTINALARM   (1 << 1)
#define DCHAN_PROVISIONED   (1 << 0)
#define DCHAN_UP   (1 << 2)
#define DEFAULT_CIDRINGS   1
 Typically, how many rings before we should send Caller*ID.
#define DEFAULT_PRI_DEBUG   0
#define DEFAULT_RINGT   ( (8000 * 8) / READ_SIZE)
#define END_SILENCE_LEN   400
#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define FORMAT2   "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
#define GET_CHANNEL(p)   ((p)->bearer ? (p)->bearer->channel : p->channel)
#define HANGUP   1
#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#define HEADER_MS   50
#define ISTRUNK(p)
#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)
#define local_astman_header(m, hdr, zap)   astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)
#define local_astman_register(a, b, c, d)
#define local_astman_unregister(a)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_CHANNELS   672
#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ( (2000) )
#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))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PRI_CHANNEL(p)   ((p) & 0xff)
#define PRI_EXPLICIT(p)   (((p) >> 16) & 0x01)
#define PRI_SPAN(p)   (((p) >> 8) & 0xff)
#define PVT_TO_CHANNEL(p)   (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
#define READ_SIZE   160
#define sig2str   dahdi_sig2str
#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)
#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "DAHDI Telephony w/PRI"
#define TRAILER_MS   5
#define TRANSFER   0

Functions

static int __action_dialoffhook (struct mansession *s, const struct message *m, int zap_mode)
static int __action_dnd (struct mansession *s, const struct message *m, int zap_mode, int dnd)
static int __action_restart (struct mansession *s, const struct message *m, int zap_mode)
static int __action_showchannels (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transfer (struct mansession *s, const struct message *m, int zap_mode)
static int __action_transferhangup (struct mansession *s, const struct message *m, int zap_mode)
static struct ast_frame__dahdi_exception (struct ast_channel *ast)
static void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static char * alarm2str (int alarm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static void apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static void build_status (char *s, size_t len, int status, int active)
static int bump_gains (struct dahdi_pvt *p)
static struct dahdi_pvtchandup (struct dahdi_pvt *src)
static int check_for_conference (struct dahdi_pvt *p)
static char * complete_span_4 (const char *line, const char *word, int pos, int state)
static char * complete_span_5 (const char *line, const char *word, int pos, int state)
static char * complete_span_helper (const char *line, const char *word, int pos, int state, int rpos)
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
static int dahdi_action_dialoffhook (struct mansession *s, const struct message *m)
static int dahdi_action_dndoff (struct mansession *s, const struct message *m)
static int dahdi_action_dndon (struct mansession *s, const struct message *m)
static int dahdi_action_restart (struct mansession *s, const struct message *m)
static int dahdi_action_showchannels (struct mansession *s, const struct message *m)
static int dahdi_action_transfer (struct mansession *s, const struct message *m)
static int dahdi_action_transferhangup (struct mansession *s, const struct message *m)
static int dahdi_answer (struct ast_channel *ast)
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)
static int dahdi_call (struct ast_channel *ast, char *rdest, int timeout)
static int dahdi_callwait (struct ast_channel *ast)
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static void dahdi_close (int fd)
static void dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num)
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
static int dahdi_destroy_channel (int fd, int argc, char **argv)
static int dahdi_destroy_channel_bynum (int channel)
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void dahdi_disable_ec (struct dahdi_pvt *p)
static void dahdi_enable_ec (struct dahdi_pvt *p)
static struct ast_framedahdi_exception (struct ast_channel *ast)
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_func_read (struct ast_channel *chan, char *function, char *data, char *buf, size_t len)
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events.
static int dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
static void dahdi_handle_dtmfup (struct ast_channel *ast, int index, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
static struct ast_channeldahdi_new (struct dahdi_pvt *, int, int, int, int, int)
static int dahdi_open (char *fn)
static void dahdi_pri_error (struct pri *pri, char *s)
static void dahdi_pri_message (struct pri *pri, char *s)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, struct dahdi_pri *pri)
static struct ast_framedahdi_read (struct ast_channel *ast)
static struct ast_channeldahdi_request (const char *type, int format, void *data, int *cause)
static int dahdi_restart (void)
static int dahdi_restart_cmd (int fd, int argc, char **argv)
static int dahdi_ring_phone (struct dahdi_pvt *p)
static int dahdi_send_keypad_facility_exec (struct ast_channel *chan, void *data)
static int dahdi_sendtext (struct ast_channel *c, const char *text)
static int dahdi_set_hook (int fd, int hs)
static int dahdi_setlaw (int dfd, int law)
static int dahdi_setlinear (int dfd, int linear)
static int dahdi_setoption (struct ast_channel *chan, int option, void *data, int datalen)
static int dahdi_show_channel (int fd, int argc, char **argv)
static int dahdi_show_channels (int fd, int argc, char **argv)
static int dahdi_show_status (int fd, int argc, char *argv[])
static char * dahdi_sig2str (int sig)
static void dahdi_softhangup_all (void)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static void destroy_all_channels (void)
static int destroy_channel (struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt **pvt)
static char * dialplan2str (int dialplan)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_idle_thread (void *vchan)
static void * do_monitor (void *data)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, int law)
static struct dahdi_pvtfind_channel (int channel)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alarms)
static int handle_dahdi_show_cadences (int fd, int argc, char *argv[])
static int handle_init_event (struct dahdi_pvt *i, int event)
static int handle_pri_debug (int fd, int argc, char *argv[])
static int handle_pri_no_debug (int fd, int argc, char *argv[])
static int handle_pri_really_debug (int fd, int argc, char *argv[])
static int handle_pri_set_debug_file (int fd, int argc, char **argv)
static int handle_pri_show_debug (int fd, int argc, char *argv[])
static int handle_pri_show_span (int fd, int argc, char *argv[])
static int handle_pri_show_spans (int fd, int argc, char *argv[])
static int handle_pri_version (int fd, int agc, char *argv[])
static int has_voicemail (struct dahdi_pvt *p)
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
static int load_module (void)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static int pri_active_dchan_fd (struct dahdi_pri *pri)
static int pri_assign_bearer (struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
static int pri_check_restart (struct dahdi_pri *pri)
static int pri_create_spanmap (int span, int trunkgroup, int logicalspan)
static int pri_create_trunkgroup (int trunkgroup, int *channels)
static void * pri_dchannel (void *vpri)
static struct dahdi_pvtpri_find_crv (struct dahdi_pri *pri, int crv)
static int pri_find_dchan (struct dahdi_pri *pri)
static int pri_find_empty_chan (struct dahdi_pri *pri, int backwards)
static int pri_find_principle (struct dahdi_pri *pri, int channel)
static int pri_fixup_principle (struct dahdi_pri *pri, int principle, q931_call *c)
static int pri_grab (struct dahdi_pvt *pvt, struct dahdi_pri *pri)
static int pri_hangup_all (struct dahdi_pvt *p, struct dahdi_pri *pri)
static int pri_is_up (struct dahdi_pri *pri)
static char * pri_order (int level)
static void pri_rel (struct dahdi_pri *pri)
static int pri_resolve_span (int *span, int channel, int offset, struct dahdi_spaninfo *si)
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int skipchannels)
static char * redirectingreason2str (int redirectingreason)
static int reload (void)
static int reset_conf (struct dahdi_pvt *p)
static int restart_monitor (void)
static int restore_conference (struct dahdi_pvt *p)
static int restore_gains (struct dahdi_pvt *p)
static int save_conference (struct dahdi_pvt *p)
static int send_callerid (struct dahdi_pvt *p)
static int send_cwcidspill (struct dahdi_pvt *p)
static int send_keypad_facility_exec (struct ast_channel *chan, void *data)
static int set_actual_gain (int fd, int chan, float rxgain, float txgain, int law)
static int set_actual_rxgain (int fd, int chan, float gain, int law)
static int set_actual_txgain (int fd, int chan, float gain, int law)
static int setup_dahdi (int reload)
static void * ss_thread (void *data)
static int start_pri (struct dahdi_pri *pri)
static void swap_subs (struct dahdi_pvt *p, int a, int b)
static int unalloc_sub (struct dahdi_pvt *p, int x)
static int unload_module (void)
static int update_conf (struct dahdi_pvt *p)
static void wakeup_sub (struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
static int zap_action_dialoffhook (struct mansession *s, const struct message *m)
static int zap_action_dndoff (struct mansession *s, const struct message *m)
static int zap_action_dndon (struct mansession *s, const struct message *m)
static int zap_action_restart (struct mansession *s, const struct message *m)
static int zap_action_showchannels (struct mansession *s, const struct message *m)
static int zap_action_transfer (struct mansession *s, const struct message *m)
static int zap_action_transferhangup (struct mansession *s, const struct message *m)
static int zap_send_keypad_facility_exec (struct ast_channel *chan, void *data)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "6989f2ec67f8497e38c12890500c525b" , .load = load_module, .unload = unload_module, .reload = reload, }
struct {
   int   alarm
   char *   name
alarms []
static const struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static struct ast_channel_techchan_tech
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static struct ast_cli_entry cli_zap_destroy_channel_deprecated
static struct ast_cli_entry cli_zap_restart_deprecated
static struct ast_cli_entry cli_zap_show_cadences_deprecated
static struct ast_cli_entry cli_zap_show_channel_deprecated
static struct ast_cli_entry cli_zap_show_channels_deprecated
static struct ast_cli_entry cli_zap_show_status_deprecated
static struct ast_cli_entry dahdi_cli []
static struct ast_cli_entry dahdi_pri_cli []
static char dahdi_restart_usage []
static char * dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility"
static char * dahdi_send_keypad_facility_descrip
static char * dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI"
static char dahdi_show_cadences_usage []
static char dahdi_show_status_usage []
static struct ast_channel_tech dahdi_tech
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static char destroy_channel_usage []
static int distinctiveringaftercid = 0
static struct dahdi_distRings drings
static char * events []
static int firstdigittimeout = 16000
 Wait up to 16 seconds for first digit (FXO logic).
static int gendigittimeout = 8000
 How long to wait for following digits (FXO logic).
static struct ast_jb_conf global_jbconf
static int ifcount = 0
static struct dahdi_pvtifend
static struct dahdi_pvtiflist
static ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
 Protect the interface list (of dahdi_pvt's).
static struct ast_channel inuse
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static const char pri_debug_help []
static const char pri_no_debug_help []
static const char pri_really_debug_help []
static const char pri_show_span_help []
static const char pri_show_spans_help []
static int pridebugfd = -1
static ast_mutex_t pridebugfdlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static char pridebugfilename [1024] = ""
static struct dahdi_pri pris [NUM_SPANS]
static char progzone [10] = ""
static ast_mutex_t restart_lock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
dahdi_pvtround_robin [32]
static char show_channel_usage []
static char show_channels_usage []
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static ast_mutex_t ss_thread_lock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static char * subnames []
static const char tdesc []
static int user_has_defined_cadences = 0
static char * zap_send_keypad_facility_app = "ZapSendKeypadFacility"
static char * zap_send_keypad_facility_descrip
static char * zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI"
static struct ast_channel_tech zap_tech


Detailed Description

DAHDI Pseudo TDM interface.

Author:
Mark Spencer <markster@digium.com>
Connects to the DAHDI telephony library as well as libpri. Libpri is optional and needed only if you are going to use ISDN connections.

You need to install libraries before you attempt to compile and install the DAHDI channel.

See also
Todo:
Deprecate the "musiconhold" configuration option post 1.4

Definition in file chan_dahdi.c.


Define Documentation

#define ASCII_BYTES_PER_CHAR   80

Referenced by dahdi_sendtext().

#define AST_LAW (  )     (((p)->law == DAHDI_LAW_ALAW) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW)

Definition at line 151 of file chan_dahdi.c.

Referenced by dahdi_call(), dahdi_callwait(), dahdi_sendtext(), send_cwcidspill(), and ss_thread().

#define CALLWAITING_REPEAT_SAMPLES   ( (10000 * 8) / READ_SIZE)

10,000 ms

Definition at line 283 of file chan_dahdi.c.

Referenced by dahdi_callwait().

#define CALLWAITING_SILENT_SAMPLES   ( (300 * 8) / READ_SIZE)

300 ms

Definition at line 282 of file chan_dahdi.c.

#define CANBUSYDETECT (  )     (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)

Definition at line 1114 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CANPROGRESSDETECT (  )     (ISTRUNK(p) || (p->sig & (SIG_EM | SIG_EM_E1 | SIG_SF)) /* || (p->sig & __DAHDI_SIG_FXO) */)

Definition at line 1115 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

#define CHAN_PSEUDO   -2

Definition at line 191 of file chan_dahdi.c.

Referenced by build_channels(), dahdi_new(), dahdi_request(), enable_dtmf_detect(), and mkintf().

#define CHANNEL_PSEUDO   -12

Definition at line 149 of file chan_dahdi.c.

#define CIDCW_EXPIRE_SAMPLES   ( (500 * 8) / READ_SIZE)

500 ms

Definition at line 284 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 418 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 419 of file chan_dahdi.c.

#define DAHDI_EVENT_DTMFDOWN   0

Definition at line 121 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DAHDI_EVENT_DTMFUP   0

Definition at line 122 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 197 of file chan_dahdi.c.

Referenced by pri_find_dchan(), and pri_is_up().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 194 of file chan_dahdi.c.

Referenced by build_status(), and start_pri().

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 193 of file chan_dahdi.c.

Referenced by build_status(), pri_create_trunkgroup(), and pri_resolve_span().

#define DCHAN_UP   (1 << 2)

Definition at line 195 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

Typically, how many rings before we should send Caller*ID.

Definition at line 147 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

#define DEFAULT_PRI_DEBUG   0

Definition at line 358 of file chan_dahdi.c.

Referenced by start_pri().

#define DEFAULT_RINGT   ( (8000 * 8) / READ_SIZE)

8,000 ms

Definition at line 286 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

#define FORMAT   "%-40.40s %-10.10s %-10d %-10d %-10d\n"

#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"

#define FORMAT2   "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"

#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"

#define GET_CHANNEL (  )     ((p)->bearer ? (p)->bearer->channel : p->channel)

Definition at line 1064 of file chan_dahdi.c.

#define HANGUP   1

Definition at line 10935 of file chan_dahdi.c.

Referenced by __action_transferhangup(), and dahdi_fake_event().

#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)

Referenced by build_alerting(), build_connect(), build_connect_acknowledge(), build_disconnect(), build_facility(), build_hold(), build_hold_acknowledge(), build_hold_reject(), build_information(), build_notify(), build_proceeding(), build_progress(), build_release(), build_release_complete(), build_restart(), build_resume(), build_resume_acknowledge(), build_resume_reject(), build_retrieve(), build_retrieve_acknowledge(), build_retrieve_reject(), build_setup(), build_setup_acknowledge(), build_status(), build_status_enquiry(), build_suspend(), build_suspend_acknowledge(), build_suspend_reject(), build_timeout(), build_user_information(), dahdi_sendtext(), parse_alerting(), parse_connect(), parse_disconnect(), parse_facility(), parse_information(), parse_proceeding(), parse_progress(), parse_release(), parse_release_complete(), parse_restart(), parse_setup(), parse_setup_acknowledge(), and parse_status().

#define HEADER_MS   50

Referenced by dahdi_sendtext().

#define ISTRUNK (  ) 

Value:

((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
         (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))

Definition at line 1111 of file chan_dahdi.c.

Referenced by dahdi_indicate(), dahdi_show_channel(), and ss_thread().

#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)

Definition at line 10965 of file chan_dahdi.c.

Referenced by __action_dialoffhook(), __action_dnd(), __action_restart(), __action_showchannels(), __action_transfer(), and __action_transferhangup().

#define local_astman_header ( m,
hdr,
zap   )     astman_get_header(m, (!zap) ? "DAHDI" hdr : "Zap" hdr)

Definition at line 10966 of file chan_dahdi.c.

Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().

#define local_astman_register ( a,
b,
c,
 ) 

Definition at line 12211 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 11186 of file chan_dahdi.c.

Referenced by __unload_module().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 279 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 280 of file chan_dahdi.c.

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'dahdichan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

Definition at line 11353 of file chan_dahdi.c.

Referenced by process_dahdi().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 189 of file chan_dahdi.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 421 of file chan_dahdi.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

Definition at line 285 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define NEED_MFDETECT (  )     (((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))

Signaling types that need to use MF detection should be placed in this macro.

Definition at line 154 of file chan_dahdi.c.

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 1089 of file chan_dahdi.c.

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 188 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), mkintf(), pri_active_dchan_fd(), pri_create_trunkgroup(), pri_find_dchan(), and pri_is_up().

#define NUM_SPANS   32

Definition at line 187 of file chan_dahdi.c.

Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_trunkgroup(), pri_resolve_span(), setup_dahdi(), and unload_module().

#define POLARITY_IDLE   0

Definition at line 376 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), dahdi_hangup(), and unalloc_sub().

#define POLARITY_REV   1

Definition at line 377 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and handle_init_event().

#define PRI_CHANNEL (  )     ((p) & 0xff)

Definition at line 299 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PRI_EXPLICIT (  )     (((p) >> 16) & 0x01)

Definition at line 301 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PRI_SPAN (  )     (((p) >> 8) & 0xff)

Definition at line 300 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PVT_TO_CHANNEL (  )     (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))

Definition at line 298 of file chan_dahdi.c.

Referenced by dahdi_call(), dahdi_indicate(), dahdi_write(), and pri_check_restart().

#define READ_SIZE   160

Chunk size to read -- we use 20ms chunks to make things happy.

Definition at line 277 of file chan_dahdi.c.

Referenced by dahdi_callwait(), dahdi_open(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), my_dahdi_write(), process_dahdi(), and send_cwcidspill().

#define sig2str   dahdi_sig2str

Definition at line 1585 of file chan_dahdi.c.

Referenced by __action_showchannels(), build_channels(), dahdi_handle_event(), dahdi_show_channel(), handle_init_event(), and mkintf().

#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)

Definition at line 167 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_EM   DAHDI_SIG_EM

Definition at line 162 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_EM_E1   DAHDI_SIG_EM_E1

Definition at line 183 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)

Definition at line 163 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)

Definition at line 166 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)

Definition at line 164 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

Definition at line 165 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

Definition at line 168 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)

Definition at line 169 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)

Definition at line 170 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXOGS   DAHDI_SIG_FXOGS

Definition at line 175 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXOKS   DAHDI_SIG_FXOKS

Definition at line 176 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().

#define SIG_FXOLS   DAHDI_SIG_FXOLS

Definition at line 174 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_new(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXSGS   DAHDI_SIG_FXSGS

Definition at line 172 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_FXSKS   DAHDI_SIG_FXSKS

Definition at line 173 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_request(), dahdi_sig2str(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().

#define SIG_FXSLS   DAHDI_SIG_FXSLS

Definition at line 171 of file chan_dahdi.c.

Referenced by available(), dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)

Definition at line 184 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().

#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)

Definition at line 185 of file chan_dahdi.c.

Referenced by dahdi_sig2str(), handle_init_event(), mkintf(), and process_dahdi().

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 177 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), process_dahdi(), and ss_thread().

#define SIG_SF   DAHDI_SIG_SF

Definition at line 178 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)

Definition at line 182 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)

Definition at line 180 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().

#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)

Definition at line 181 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), and ss_thread().

#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)

Definition at line 179 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_handle_event(), dahdi_sig2str(), handle_init_event(), process_dahdi(), and ss_thread().

#define SMDI_MD_WAIT_TIMEOUT   1500

Definition at line 104 of file chan_dahdi.c.

Referenced by ss_thread().

#define SUB_CALLWAIT   1

Call-Waiting call on hold

Definition at line 372 of file chan_dahdi.c.

Referenced by available(), dahdi_bridge(), dahdi_call(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_read(), dahdi_request(), dahdi_show_channel(), features_hangup(), and ss_thread().

#define SUB_REAL   0

Active call

Definition at line 371 of file chan_dahdi.c.

Referenced by __dahdi_exception(), attempt_transfer(), available(), bump_gains(), chandup(), check_for_conference(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_confmute(), dahdi_destroy_channel_bynum(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_read(), dahdi_request(), dahdi_ring_phone(), dahdi_setoption(), dahdi_train_ec(), dahdi_unlink(), destroy_dahdi_pvt(), disable_dtmf_detect(), do_monitor(), enable_dtmf_detect(), features_hangup(), features_request(), get_alarms(), handle_init_event(), mkintf(), pri_assign_bearer(), pri_fixup_principle(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), and ss_thread().

#define SUB_THREEWAY   2

Three-way call

Definition at line 373 of file chan_dahdi.c.

Referenced by attempt_transfer(), available(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), features_hangup(), and ss_thread().

#define tdesc   "DAHDI Telephony w/PRI"

Definition at line 12393 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 10934 of file chan_dahdi.c.

Referenced by __action_transfer(), and dahdi_fake_event().


Function Documentation

static int __action_dialoffhook ( struct mansession s,
const struct message m,
int  zap_mode 
) [static]

Definition at line 11064 of file chan_dahdi.c.

References AST_FRAME_DTMF, ast_strlen_zero(), astman_get_header(), astman_send_error(), dahdi_pvt::channel, dahdi_queue_frame(), f, find_channel(), local_astman_ack, local_astman_header, dahdi_pvt::owner, and s.

Referenced by dahdi_action_dialoffhook(), and zap_action_dialoffhook().

11065 {
11066    struct dahdi_pvt *p = NULL;
11067    const char *channel = local_astman_header(m, "Channel", zap_mode);
11068    const char *number = astman_get_header(m, "Number");
11069    int i;
11070 
11071    if (ast_strlen_zero(channel)) {
11072       astman_send_error(s, m, "No channel specified");
11073       return 0;
11074    }
11075    if (ast_strlen_zero(number)) {
11076       astman_send_error(s, m, "No number specified");
11077       return 0;
11078    }
11079    if (!(p = find_channel(atoi(channel)))) {
11080       astman_send_error(s, m, "No such channel");
11081       return 0;
11082    }
11083    if (!p->owner) {
11084       astman_send_error(s, m, "Channel does not have an owner");
11085       return 0;
11086    }
11087    for (i = 0; i < strlen(number); i++) {
11088       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
11089 
11090       dahdi_queue_frame(p, &f, NULL); 
11091    }
11092    local_astman_ack(s, m, "DialOffHook", zap_mode);
11093 
11094    return 0;
11095 }

static int __action_dnd ( struct mansession s,
const struct message m,
int  zap_mode,
int  dnd 
) [static]

Definition at line 10968 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, find_channel(), local_astman_ack, local_astman_header, and s.

Referenced by dahdi_action_dndoff(), dahdi_action_dndon(), zap_action_dndoff(), and zap_action_dndon().

10969 {
10970    struct dahdi_pvt *p = NULL;
10971    const char *channel = local_astman_header(m, "Channel", zap_mode);
10972 
10973    if (ast_strlen_zero(channel)) {
10974       astman_send_error(s, m, "No channel specified");
10975       return 0;
10976    }
10977    if (!(p = find_channel(atoi(channel)))) {
10978       astman_send_error(s, m, "No such channel");
10979       return 0;
10980    }
10981    p->dnd = dnd;
10982    local_astman_ack(s, m, "DND", zap_mode);
10983 
10984    return 0;
10985 }

static int __action_restart ( struct mansession s,
const struct message m,
int  zap_mode 
) [static]

Definition at line 11162 of file chan_dahdi.c.

References astman_send_error(), dahdi_restart(), local_astman_ack, and s.

Referenced by dahdi_action_restart(), and zap_action_restart().

11163 {
11164    if (dahdi_restart() != 0) {
11165       if (zap_mode) {
11166          astman_send_error(s, m, "Failed to restart Zap");
11167       } else {
11168          astman_send_error(s, m, "Failed to restart DAHDI");
11169       }
11170       return 1;
11171    }
11172    local_astman_ack(s, m, "Restart: Success", zap_mode);
11173    return 0;
11174 }

static int __action_showchannels ( struct mansession s,
const struct message m,
int  zap_mode 
) [static]

Definition at line 11107 of file chan_dahdi.c.

References alarm, alarm2str(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), astman_append(), astman_get_header(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_chan_name, dahdi_pvt::dnd, get_alarms(), iflist, iflock, local_astman_ack, dahdi_pvt::next, s, dahdi_pvt::sig, and sig2str.

Referenced by dahdi_action_showchannels(), and zap_action_showchannels().

11108 {
11109    struct dahdi_pvt *tmp = NULL;
11110    const char *id = astman_get_header(m, "ActionID");
11111    char idText[256] = "";
11112 
11113    local_astman_ack(s, m, " channel status will follow", zap_mode);
11114    if (!ast_strlen_zero(id))
11115       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
11116 
11117    ast_mutex_lock(&iflock);
11118    
11119    tmp = iflist;
11120    while (tmp) {
11121       if (tmp->channel > 0) {
11122          int alarm = get_alarms(tmp);
11123          astman_append(s,
11124                   "Event: %sShowChannels\r\n"
11125                   "Channel: %d\r\n"
11126                   "Signalling: %s\r\n"
11127                   "Context: %s\r\n"
11128                   "DND: %s\r\n"
11129                   "Alarm: %s\r\n"
11130                   "%s"
11131                   "\r\n",
11132                   dahdi_chan_name,
11133                   tmp->channel, sig2str(tmp->sig), tmp->context, 
11134                   tmp->dnd ? "Enabled" : "Disabled",
11135                   alarm2str(alarm), idText);
11136       } 
11137 
11138       tmp = tmp->next;
11139    }
11140 
11141    ast_mutex_unlock(&iflock);
11142    
11143    astman_append(s, 
11144             "Event: %sShowChannelsComplete\r\n"
11145             "%s"
11146             "\r\n",
11147             dahdi_chan_name,
11148             idText);
11149    return 0;
11150 }

static int __action_transfer ( struct mansession s,
const struct message m,
int  zap_mode 
) [static]

Definition at line 11007 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), local_astman_ack, local_astman_header, s, and TRANSFER.

Referenced by dahdi_action_transfer(), and zap_action_transfer().

11008 {
11009    struct dahdi_pvt *p = NULL;
11010    const char *channel = local_astman_header(m, "Channel", zap_mode);
11011 
11012    if (ast_strlen_zero(channel)) {
11013       astman_send_error(s, m, "No channel specified");
11014       return 0;
11015    }
11016    if (!(p = find_channel(atoi(channel)))) {
11017       astman_send_error(s, m, "No such channel");
11018       return 0;
11019    }
11020    dahdi_fake_event(p,TRANSFER);
11021    local_astman_ack(s, m, "Transfer", zap_mode);
11022 
11023    return 0;
11024 }

static int __action_transferhangup ( struct mansession s,
const struct message m,
int  zap_mode 
) [static]

Definition at line 11036 of file chan_dahdi.c.

References ast_strlen_zero(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), HANGUP, local_astman_ack, local_astman_header, and s.

Referenced by dahdi_action_transferhangup(), and zap_action_transferhangup().

11037 {
11038    struct dahdi_pvt *p = NULL;
11039    const char *channel = local_astman_header(m, "Channel", zap_mode);
11040 
11041    if (ast_strlen_zero(channel)) {
11042       astman_send_error(s, m, "No channel specified");
11043       return 0;
11044    }
11045    if (!(p = find_channel(atoi(channel)))) {
11046       astman_send_error(s, m, "No such channel");
11047       return 0;
11048    }
11049    dahdi_fake_event(p, HANGUP);
11050    local_astman_ack(s, m, "Hangup", zap_mode);
11051    return 0;
11052 }

static struct ast_frame* __dahdi_exception ( struct ast_channel ast  )  [static]

Definition at line 4959 of file chan_dahdi.c.

References ast_bridged_channel(), AST_CONTROL_UNHOLD, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_handle_event(), dahdi_ring_phone(), dahdi_set_hook(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, update_conf(), and VERBOSE_PREFIX_3.

Referenced by dahdi_exception(), and dahdi_read().

04960 {
04961    struct dahdi_pvt *p = ast->tech_pvt;
04962    int res;
04963    int usedindex=-1;
04964    int index;
04965    struct ast_frame *f;
04966 
04967 
04968    index = dahdi_get_index(ast, p, 1);
04969    
04970    p->subs[index].f.frametype = AST_FRAME_NULL;
04971    p->subs[index].f.datalen = 0;
04972    p->subs[index].f.samples = 0;
04973    p->subs[index].f.mallocd = 0;
04974    p->subs[index].f.offset = 0;
04975    p->subs[index].f.subclass = 0;
04976    p->subs[index].f.delivery = ast_tv(0,0);
04977    p->subs[index].f.src = "dahdi_exception";
04978    p->subs[index].f.data = NULL;
04979    
04980    
04981    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
04982       /* If nobody owns us, absorb the event appropriately, otherwise
04983          we loop indefinitely.  This occurs when, during call waiting, the
04984          other end hangs up our channel so that it no longer exists, but we
04985          have neither FLASH'd nor ONHOOK'd to signify our desire to
04986          change to the other channel. */
04987       if (p->fake_event) {
04988          res = p->fake_event;
04989          p->fake_event = 0;
04990       } else
04991          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
04992       /* Switch to real if there is one and this isn't something really silly... */
04993       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
04994          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
04995          ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
04996          p->owner = p->subs[SUB_REAL].owner;
04997          if (p->owner && ast_bridged_channel(p->owner))
04998             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04999          p->subs[SUB_REAL].needunhold = 1;
05000       }
05001       switch (res) {
05002       case DAHDI_EVENT_ONHOOK:
05003          dahdi_disable_ec(p);
05004          if (p->owner) {
05005             if (option_verbose > 2) 
05006                ast_verbose(VERBOSE_PREFIX_3 "Channel %s still has call, ringing phone\n", p->owner->name);
05007             dahdi_ring_phone(p);
05008             p->callwaitingrepeat = 0;
05009             p->cidcwexpire = 0;
05010          } else
05011             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05012          update_conf(p);
05013          break;
05014       case DAHDI_EVENT_RINGOFFHOOK:
05015          dahdi_enable_ec(p);
05016          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05017          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05018             p->subs[SUB_REAL].needanswer = 1;
05019             p->dialing = 0;
05020          }
05021          break;
05022       case DAHDI_EVENT_HOOKCOMPLETE:
05023       case DAHDI_EVENT_RINGERON:
05024       case DAHDI_EVENT_RINGEROFF:
05025          /* Do nothing */
05026          break;
05027       case DAHDI_EVENT_WINKFLASH:
05028          gettimeofday(&p->flashtime, NULL);
05029          if (p->owner) {
05030             if (option_verbose > 2) 
05031                ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05032             if (p->owner->_state != AST_STATE_UP) {
05033                /* Answer if necessary */
05034                usedindex = dahdi_get_index(p->owner, p, 0);
05035                if (usedindex > -1) {
05036                   p->subs[usedindex].needanswer = 1;
05037                }
05038                ast_setstate(p->owner, AST_STATE_UP);
05039             }
05040             p->callwaitingrepeat = 0;
05041             p->cidcwexpire = 0;
05042             if (ast_bridged_channel(p->owner))
05043                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05044             p->subs[SUB_REAL].needunhold = 1;
05045          } else
05046             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05047          update_conf(p);
05048          break;
05049       default:
05050          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05051       }
05052       f = &p->subs[index].f;
05053       return f;
05054    }
05055    if (!(p->radio || (p->oprmode < 0)) && option_debug) 
05056       ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05057    /* If it's not us, return NULL immediately */
05058    if (ast != p->owner) {
05059       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05060       f = &p->subs[index].f;
05061       return f;
05062    }
05063    f = dahdi_handle_event(ast);
05064    return f;
05065 }

static void __reg_module ( void   )  [static]

Definition at line 12402 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 11193 of file chan_dahdi.c.

References ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, dahdi_close_pri_fd(), dahdi_pri_cli, destroy_all_channels(), iflist, iflock, local_astman_unregister, master, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, and pris.

Referenced by load_module(), and unload_module().

11194 {
11195    struct dahdi_pvt *p;
11196 
11197 #ifdef HAVE_PRI
11198    int i, j;
11199    for (i = 0; i < NUM_SPANS; i++) {
11200       if (pris[i].master != AST_PTHREADT_NULL) 
11201          pthread_cancel(pris[i].master);
11202    }
11203    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11204 
11205    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11206       ast_unregister_application(dahdi_send_keypad_facility_app);
11207    }
11208    ast_unregister_application(zap_send_keypad_facility_app);
11209 #endif
11210    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11211    local_astman_unregister("DialOffHook");
11212    local_astman_unregister("Hangup");
11213    local_astman_unregister("Transfer");
11214    local_astman_unregister("DNDoff");
11215    local_astman_unregister("DNDon");
11216    local_astman_unregister("ShowChannels");
11217    local_astman_unregister("Restart");
11218    ast_channel_unregister(chan_tech);
11219    ast_mutex_lock(&iflock);
11220    /* Hangup all interfaces if they have an owner */
11221    p = iflist;
11222    while (p) {
11223       if (p->owner)
11224          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
11225       p = p->next;
11226    }
11227    ast_mutex_unlock(&iflock);
11228    ast_mutex_lock(&monlock);
11229    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11230       pthread_cancel(monitor_thread);
11231       pthread_kill(monitor_thread, SIGURG);
11232       pthread_join(monitor_thread, NULL);
11233    }
11234    monitor_thread = AST_PTHREADT_STOP;
11235    ast_mutex_unlock(&monlock);
11236 
11237    destroy_all_channels();
11238 #ifdef HAVE_PRI      
11239    for (i = 0; i < NUM_SPANS; i++) {
11240       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
11241          pthread_join(pris[i].master, NULL);
11242       for (j = 0; j < NUM_DCHANS; j++) {
11243          dahdi_close_pri_fd(&(pris[i]), j);
11244       }
11245    }
11246 #endif
11247    ast_cond_destroy(&ss_thread_complete);
11248    return 0;
11249 }

static void __unreg_module ( void   )  [static]

Definition at line 12402 of file chan_dahdi.c.

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1496 of file chan_dahdi.c.

References alarms, and name.

Referenced by __action_showchannels(), and handle_alarms().

01497 {
01498    int x;
01499    for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
01500       if (alarms[x].alarm & alarm)
01501          return alarms[x].name;
01502    }
01503    return alarm ? "Unknown Alarm" : "No Alarm";
01504 }

static int alloc_sub ( struct dahdi_pvt p,
int  x 
) [static]

Definition at line 1298 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_close_sub(), DAHDI_FILE_PSEUDO, dahdi_open(), dahdi_subchannel::dfd, errno, LOG_DEBUG, LOG_WARNING, option_debug, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), dahdi_request(), and ss_thread().

01299 {
01300    struct dahdi_bufferinfo bi;
01301    int res;
01302    if (p->subs[x].dfd < 0) {
01303       p->subs[x].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
01304       if (p->subs[x].dfd > -1) {
01305          res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01306          if (!res) {
01307             bi.txbufpolicy = p->buf_policy;
01308             bi.rxbufpolicy = p->buf_policy;
01309             bi.numbufs = p->buf_no;
01310             res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01311             if (res < 0) {
01312                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01313             }
01314          } else 
01315             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01316          if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01317             ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01318             dahdi_close_sub(p, x);
01319             return -1;
01320          }
01321          if (option_debug)
01322             ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01323          return 0;
01324       } else
01325          ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01326       return -1;
01327    }
01328    ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01329    return -1;
01330 }

static void apply_plan_to_number ( char *  buf,
size_t  size,
const struct dahdi_pri pri,
const char *  number,
const int  plan 
) [static]

Definition at line 8845 of file chan_dahdi.c.

References ast_strlen_zero(), dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.

08846 {
08847    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
08848       if (size) {
08849          *buf = '\0';
08850       }
08851       return;
08852    }
08853 
08854    switch (plan) {
08855    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
08856       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08857       break;
08858    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
08859       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08860       break;
08861    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
08862       snprintf(buf, size, "%s%s", pri->localprefix, number);
08863       break;
08864    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
08865       snprintf(buf, size, "%s%s", pri->privateprefix, number);
08866       break;
08867    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
08868       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08869       break;
08870    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
08871       snprintf(buf, size, "%s", number);
08872       break;
08873    }
08874 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 3906 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_indicate(), ast_log(), ast_mutex_unlock, ast_queue_control(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, dahdi_subchannel::dfd, ast_channel::lock, LOG_DEBUG, ast_channel::name, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().

Referenced by dahdi_handle_event(), handle_onhook_message(), handle_request(), handle_soft_key_event_message(), and local_attended_transfer().

03907 {
03908    /* In order to transfer, we need at least one of the channels to
03909       actually be in a call bridge.  We can't conference two applications
03910       together (but then, why would we want to?) */
03911    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
03912       /* The three-way person we're about to transfer to could still be in MOH, so
03913          stop if now if appropriate */
03914       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
03915          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
03916       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
03917          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
03918       }
03919       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
03920          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
03921       }
03922        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
03923          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03924                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
03925          return -1;
03926       }
03927       /* Orphan the channel after releasing the lock */
03928       ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
03929       unalloc_sub(p, SUB_THREEWAY);
03930    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03931       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03932       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
03933          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
03934       }
03935       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
03936          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
03937       }
03938       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
03939          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
03940                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
03941          return -1;
03942       }
03943       /* Three-way is now the REAL */
03944       swap_subs(p, SUB_THREEWAY, SUB_REAL);
03945       ast_mutex_unlock(&p->subs[SUB_REAL].owner->lock);
03946       unalloc_sub(p, SUB_THREEWAY);
03947       /* Tell the caller not to hangup */
03948       return 1;
03949    } else {
03950       ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
03951                p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
03952       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
03953       return -1;
03954    }
03955    return 0;
03956 }

static int available ( struct dahdi_pvt p,
int  channelmatch,
ast_group_t  groupmatch,
int *  busy,
int *  channelmatched,
int *  groupmatched 
) [inline, static]

Definition at line 8112 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::callwaiting, dahdi_pvt::channel, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, LOG_DEBUG, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::radio, dahdi_pvt::resetting, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

Referenced by __ast_string_field_index_build_va(), and dahdi_request().

08113 {
08114    int res;
08115    struct dahdi_params par;
08116 
08117    /* First, check group matching */
08118    if (groupmatch) {
08119       if ((p->group & groupmatch) != groupmatch)
08120          return 0;
08121       *groupmatched = 1;
08122    }
08123    /* Check to see if we have a channel match */
08124    if (channelmatch != -1) {
08125       if (p->channel != channelmatch)
08126          return 0;
08127       *channelmatched = 1;
08128    }
08129    /* We're at least busy at this point */
08130    if (busy) {
08131       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
08132          *busy = 1;
08133    }
08134    /* If do not disturb, definitely not */
08135    if (p->dnd)
08136       return 0;
08137    /* If guard time, definitely not */
08138    if (p->guardtime && (time(NULL) < p->guardtime)) 
08139       return 0;
08140       
08141    /* If no owner definitely available */
08142    if (!p->owner) {
08143 #ifdef HAVE_PRI
08144       /* Trust PRI */
08145       if (p->pri) {
08146          if (p->resetting || p->call)
08147             return 0;
08148          else
08149             return 1;
08150       }
08151 #endif
08152       if (!(p->radio || (p->oprmode < 0)))
08153       {
08154          if (!p->sig || (p->sig == SIG_FXSLS))
08155             return 1;
08156          /* Check hook state */
08157          if (p->subs[SUB_REAL].dfd > -1) {
08158             memset(&par, 0, sizeof(par));
08159             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
08160          } else {
08161             /* Assume not off hook on CVRS */
08162             res = 0;
08163             par.rxisoffhook = 0;
08164          }
08165          if (res) {
08166             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
08167          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
08168             /* When "onhook" that means no battery on the line, and thus
08169               it is out of service..., if it's on a TDM card... If it's a channel
08170               bank, there is no telling... */
08171             if (par.rxbits > -1)
08172                return 1;
08173             if (par.rxisoffhook)
08174                return 1;
08175             else
08176 #ifdef DAHDI_CHECK_HOOKSTATE
08177                return 0;
08178 #else
08179                return 1;
08180 #endif
08181          } else if (par.rxisoffhook) {
08182             ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
08183             /* Not available when the other end is off hook */
08184             return 0;
08185          }
08186       }
08187       return 1;
08188    }
08189 
08190    /* If it's not an FXO, forget about call wait */
08191    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
08192       return 0;
08193 
08194    if (!p->callwaiting) {
08195       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
08196       return 0;
08197    }
08198 
08199    if (p->subs[SUB_CALLWAIT].dfd > -1) {
08200       /* If there is already a call waiting call, then we can't take a second one */
08201       return 0;
08202    }
08203    
08204    if ((p->owner->_state != AST_STATE_UP) &&
08205        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
08206       /* If the current call is not up, then don't allow the call */
08207       return 0;
08208    }
08209    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
08210       /* Can't take a call wait when the three way calling hasn't been merged yet. */
08211       return 0;
08212    }
08213    /* We're cool */
08214    return 1;
08215 }

static int build_channels ( struct dahdi_chan_conf conf,
int  iscrv,
const char *  value,
int  reload,
int  lineno,
int *  found_pseudo 
) [static]

Definition at line 11261 of file chan_dahdi.c.

References ast_log(), ast_strdupa, ast_verbose(), dahdi_chan_conf::chan, CHAN_PSEUDO, HAVE_PRI, LOG_ERROR, mkintf(), NUM_SPANS, option_verbose, dahdi_pri::pri, pris, dahdi_pvt::sig, sig2str, dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.

Referenced by process_dahdi().

11262 {
11263    char *c, *chan;
11264    int x, start, finish;
11265    struct dahdi_pvt *tmp;
11266 #ifdef HAVE_PRI
11267    struct dahdi_pri *pri;
11268    int trunkgroup, y;
11269 #endif
11270    
11271    if ((reload == 0) && (conf->chan.sig < 0)) {
11272       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
11273       return -1;
11274    }
11275 
11276    c = ast_strdupa(value);
11277 
11278 #ifdef HAVE_PRI
11279    pri = NULL;
11280    if (iscrv) {
11281       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
11282          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
11283          return -1;
11284       }
11285       if (trunkgroup < 1) {
11286          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
11287          return -1;
11288       }
11289       c += y;
11290       for (y = 0; y < NUM_SPANS; y++) {
11291          if (pris[y].trunkgroup == trunkgroup) {
11292             pri = pris + y;
11293             break;
11294          }
11295       }
11296       if (!pri) {
11297          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
11298          return -1;
11299       }
11300    }
11301 #endif         
11302 
11303    while ((chan = strsep(&c, ","))) {
11304       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
11305          /* Range */
11306       } else if (sscanf(chan, "%30d", &start)) {
11307          /* Just one */
11308          finish = start;
11309       } else if (!strcasecmp(chan, "pseudo")) {
11310          finish = start = CHAN_PSEUDO;
11311          if (found_pseudo)
11312             *found_pseudo = 1;
11313       } else {
11314          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
11315          return -1;
11316       }
11317       if (finish < start) {
11318          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
11319          x = finish;
11320          finish = start;
11321          start = x;
11322       }
11323 
11324       for (x = start; x <= finish; x++) {
11325 #ifdef HAVE_PRI
11326          tmp = mkintf(x, conf, pri, reload);
11327 #else       
11328          tmp = mkintf(x, conf, NULL, reload);
11329 #endif         
11330 
11331          if (tmp) {
11332             if (option_verbose > 2) {
11333 #ifdef HAVE_PRI
11334                if (pri)
11335                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
11336                else
11337 #endif
11338                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
11339             }
11340          } else {
11341             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
11342                (reload == 1) ? "reconfigure" : "register", value);
11343             return -1;
11344          }
11345       }
11346    }
11347 
11348    return 0;
11349 }

static void build_status ( char *  s,
size_t  len,
int  status,
int  active 
) [static]

Definition at line 10238 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

10239 {
10240    if (!s || len < 1) {
10241       return;
10242    }
10243    s[0] = '\0';
10244    if (status & DCHAN_PROVISIONED)
10245       strncat(s, "Provisioned, ", len - strlen(s) - 1);
10246    if (!(status & DCHAN_NOTINALARM))
10247       strncat(s, "In Alarm, ", len - strlen(s) - 1);
10248    if (status & DCHAN_UP)
10249       strncat(s, "Up", len - strlen(s) - 1);
10250    else
10251       strncat(s, "Down", len - strlen(s) - 1);
10252    if (active)
10253       strncat(s, ", Active", len - strlen(s) - 1);
10254    else
10255       strncat(s, ", Standby", len - strlen(s) - 1);
10256    s[len - 1] = '\0';
10257 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 1945 of file chan_dahdi.c.

References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.

Referenced by ss_thread().

01946 {
01947    int res;
01948 
01949    /* Bump receive gain by 5.0db */
01950    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + 5.0, p->txgain, p->law);
01951    if (res) {
01952       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
01953       return -1;
01954    }
01955 
01956    return 0;
01957 }

static struct dahdi_pvt* chandup ( struct dahdi_pvt src  )  [static]

Definition at line 8217 of file chan_dahdi.c.

References ast_log(), ast_malloc, ast_mutex_init, DAHDI_FILE_PSEUDO, dahdi_open(), destroy_dahdi_pvt(), errno, iflist, LOG_ERROR, dahdi_pvt::next, dahdi_pvt::prev, and SUB_REAL.

Referenced by dahdi_request().

08218 {
08219    struct dahdi_pvt *p;
08220    struct dahdi_bufferinfo bi;
08221    int res;
08222    
08223    if ((p = ast_malloc(sizeof(*p)))) {
08224       memcpy(p, src, sizeof(struct dahdi_pvt));
08225       ast_mutex_init(&p->lock);
08226       p->subs[SUB_REAL].dfd = dahdi_open(DAHDI_FILE_PSEUDO);
08227       /* Allocate a DAHDI structure */
08228       if (p->subs[SUB_REAL].dfd < 0) {
08229          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
08230          destroy_dahdi_pvt(&p);
08231          return NULL;
08232       }
08233       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08234       if (!res) {
08235          bi.txbufpolicy = p->buf_policy;
08236          bi.rxbufpolicy = p->buf_policy;
08237          bi.numbufs = p->buf_no;
08238          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08239          if (res < 0) {
08240             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
08241          }
08242       } else
08243          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
08244    }
08245    p->destroy = 1;
08246    p->next = iflist;
08247    p->prev = NULL;
08248    iflist = p;
08249    if (iflist->next)
08250       iflist->next->prev = p;
08251    return p;
08252 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 3958 of file chan_dahdi.c.

References ast_log(), ast_verbose(), dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, option_verbose, SUB_REAL, dahdi_pvt::subs, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event().

03959 {
03960    struct dahdi_confinfo ci;
03961    /* Fine if we already have a master, etc */
03962    if (p->master || (p->confno > -1))
03963       return 0;
03964    memset(&ci, 0, sizeof(ci));
03965    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
03966       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
03967       return 0;
03968    }
03969    /* If we have no master and don't have a confno, then 
03970       if we're in a conference, it's probably a MeetMe room or
03971       some such, so don't let us 3-way out! */
03972    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
03973       if (option_verbose > 2) 
03974          ast_verbose(VERBOSE_PREFIX_3 "Avoiding 3-way call when in an external conference\n");
03975       return 1;
03976    }
03977    return 0;
03978 }

static char* complete_span_4 ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 10105 of file chan_dahdi.c.

References complete_span_helper().

10106 {
10107    return complete_span_helper(line,word,pos,state,3);
10108 }

static char* complete_span_5 ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 10110 of file chan_dahdi.c.

References complete_span_helper().

10111 {
10112    return complete_span_helper(line,word,pos,state,4);
10113 }

static char* complete_span_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos 
) [static]

Definition at line 10086 of file chan_dahdi.c.

References asprintf, ast_log(), errno, NUM_SPANS, and pris.

Referenced by complete_span_4(), and complete_span_5().

10087 {
10088    int which, span;
10089    char *ret = NULL;
10090 
10091    if (pos != rpos)
10092       return ret;
10093 
10094    for (which = span = 0; span < NUM_SPANS; span++) {
10095       if (pris[span].pri && ++which > state) {
10096          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
10097             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
10098          }
10099          break;
10100       }
10101    }
10102    return ret;
10103 }

static int conf_add ( struct dahdi_pvt p,
struct dahdi_subchannel c,
int  index,
int  slavechannel 
) [static]

Definition at line 1587 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::confno, dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, LOG_DEBUG, and LOG_WARNING.

Referenced by update_conf().

01588 {
01589    /* If the conference already exists, and we're already in it
01590       don't bother doing anything */
01591    struct dahdi_confinfo zi;
01592    
01593    memset(&zi, 0, sizeof(zi));
01594    zi.chan = 0;
01595 
01596    if (slavechannel > 0) {
01597       /* If we have only one slave, do a digital mon */
01598       zi.confmode = DAHDI_CONF_DIGITALMON;
01599       zi.confno = slavechannel;
01600    } else {
01601       if (!index) {
01602          /* Real-side and pseudo-side both participate in conference */
01603          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01604             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01605       } else
01606          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01607       zi.confno = p->confno;
01608    }
01609    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01610       return 0;
01611    if (c->dfd < 0)
01612       return 0;
01613    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01614       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01615       return -1;
01616    }
01617    if (slavechannel < 1) {
01618       p->confno = zi.confno;
01619    }
01620    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01621    ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01622    return 0;
01623 }

static int conf_del ( struct dahdi_pvt p,
struct dahdi_subchannel c,
int  index 
) [static]

Definition at line 1636 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::curconf, dahdi_subchannel::dfd, errno, isourconf(), LOG_DEBUG, and LOG_WARNING.

Referenced by dahdi_unlink(), and update_conf().

01637 {
01638    struct dahdi_confinfo zi;
01639    if (/* Can't delete if there's no dfd */
01640       (c->dfd < 0) ||
01641       /* Don't delete from the conference if it's not our conference */
01642       !isourconf(p, c)
01643       /* Don't delete if we don't think it's conferenced at all (implied) */
01644       ) return 0;
01645    memset(&zi, 0, sizeof(zi));
01646    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01647       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01648       return -1;
01649    }
01650    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01651    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01652    return 0;
01653 }

static int dahdi_action_dialoffhook ( struct mansession s,
const struct message m 
) [static]

Definition at line 11102 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

11103 {
11104    return __action_dialoffhook(s, m, 0);
11105 }

static int dahdi_action_dndoff ( struct mansession s,
const struct message m 
) [static]

Definition at line 11002 of file chan_dahdi.c.

References __action_dnd(), and s.

11003 {
11004    return __action_dnd(s, m, 0, 0);
11005 }

static int dahdi_action_dndon ( struct mansession s,
const struct message m 
) [static]

Definition at line 10992 of file chan_dahdi.c.

References __action_dnd(), and s.

10993 {
10994    return __action_dnd(s, m, 0, 1);
10995 }

static int dahdi_action_restart ( struct mansession s,
const struct message m 
) [static]

Definition at line 11181 of file chan_dahdi.c.

References __action_restart(), and s.

11182 {
11183    return __action_restart(s, m, 0);
11184 }

static int dahdi_action_showchannels ( struct mansession s,
const struct message m 
) [static]

Definition at line 11157 of file chan_dahdi.c.

References __action_showchannels(), and s.

11158 {
11159    return __action_showchannels(s, m, 0);
11160 }

static int dahdi_action_transfer ( struct mansession s,
const struct message m 
) [static]

Definition at line 11031 of file chan_dahdi.c.

References __action_transfer(), and s.

11032 {
11033    return __action_transfer(s, m, 0);
11034 }

static int dahdi_action_transferhangup ( struct mansession s,
const struct message m 
) [static]

Definition at line 11059 of file chan_dahdi.c.

References __action_transferhangup(), and s.

11060 {
11061    return __action_transferhangup(s, m, 0);
11062 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 3150 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_pvt::channel, dahdi_enable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_train_ec(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.

03151 {
03152    struct dahdi_pvt *p = ast->tech_pvt;
03153    int res = 0;
03154    int index;
03155    int oldstate = ast->_state;
03156    ast_setstate(ast, AST_STATE_UP);
03157    ast_mutex_lock(&p->lock);
03158    index = dahdi_get_index(ast, p, 0);
03159    if (index < 0)
03160       index = SUB_REAL;
03161    /* nothing to do if a radio channel */
03162    if ((p->radio || (p->oprmode < 0))) {
03163       ast_mutex_unlock(&p->lock);
03164       return 0;
03165    }
03166    switch (p->sig) {
03167    case SIG_FXSLS:
03168    case SIG_FXSGS:
03169    case SIG_FXSKS:
03170       p->ringt = 0;
03171       /* Fall through */
03172    case SIG_EM:
03173    case SIG_EM_E1:
03174    case SIG_EMWINK:
03175    case SIG_FEATD:
03176    case SIG_FEATDMF:
03177    case SIG_FEATDMF_TA:
03178    case SIG_E911:
03179    case SIG_FGC_CAMA:
03180    case SIG_FGC_CAMAMF:
03181    case SIG_FEATB:
03182    case SIG_SF:
03183    case SIG_SFWINK:
03184    case SIG_SF_FEATD:
03185    case SIG_SF_FEATDMF:
03186    case SIG_SF_FEATB:
03187    case SIG_FXOLS:
03188    case SIG_FXOGS:
03189    case SIG_FXOKS:
03190       /* Pick up the line */
03191       ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
03192       if (p->hanguponpolarityswitch) {
03193          gettimeofday(&p->polaritydelaytv, NULL);
03194       }
03195       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03196       tone_zone_play_tone(p->subs[index].dfd, -1);
03197       p->dialing = 0;
03198       if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03199          if (oldstate == AST_STATE_RINGING) {
03200             ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
03201             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03202             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03203             p->owner = p->subs[SUB_REAL].owner;
03204          }
03205       }
03206       if (p->sig & __DAHDI_SIG_FXS) {
03207          dahdi_enable_ec(p);
03208          dahdi_train_ec(p);
03209       }
03210       break;
03211 #ifdef HAVE_PRI
03212    case SIG_PRI:
03213       /* Send a pri acknowledge */
03214       if (!pri_grab(p, p->pri)) {
03215          p->proceeding = 1;
03216          p->dialing = 0;
03217          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03218          pri_rel(p->pri);
03219       } else {
03220          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03221          res = -1;
03222       }
03223       break;
03224 #endif
03225    case 0:
03226       ast_mutex_unlock(&p->lock);
03227       return 0;
03228    default:
03229       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03230       res = -1;
03231    }
03232    ast_mutex_unlock(&p->lock);
03233    return res;
03234 }

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 
) [static]

Definition at line 3559 of file chan_dahdi.c.

References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_read(), AST_STATE_RINGING, ast_verbose(), ast_waitfor_n(), ast_write(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_subchannel::inthreeway, dahdi_pvt::lock, ast_channel::lock, LOG_DEBUG, LOG_NOTICE, master, ast_channel::name, option_verbose, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, update_conf(), and VERBOSE_PREFIX_3.

03560 {
03561    struct ast_channel *who;
03562    struct dahdi_pvt *p0, *p1, *op0, *op1;
03563    struct dahdi_pvt *master = NULL, *slave = NULL;
03564    struct ast_frame *f;
03565    int inconf = 0;
03566    int nothingok = 1;
03567    int ofd0, ofd1;
03568    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
03569    int os0 = -1, os1 = -1;
03570    int priority = 0;
03571    struct ast_channel *oc0, *oc1;
03572    enum ast_bridge_result res;
03573 
03574 #ifdef PRI_2BCT
03575    int triedtopribridge = 0;
03576    q931_call *q931c0 = NULL, *q931c1 = NULL;
03577 #endif
03578 
03579    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
03580       There is code below to handle it properly until DTMF is actually seen,
03581       but due to currently unresolved issues it's ignored...
03582    */
03583 
03584    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
03585       return AST_BRIDGE_FAILED_NOWARN;
03586 
03587    ast_mutex_lock(&c0->lock);
03588    while (ast_mutex_trylock(&c1->lock)) {
03589       DEADLOCK_AVOIDANCE(&c0->lock);
03590    }
03591 
03592    p0 = c0->tech_pvt;
03593    p1 = c1->tech_pvt;
03594    /* cant do pseudo-channels here */
03595    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
03596       ast_mutex_unlock(&c0->lock);
03597       ast_mutex_unlock(&c1->lock);
03598       return AST_BRIDGE_FAILED_NOWARN;
03599    }
03600 
03601    oi0 = dahdi_get_index(c0, p0, 0);
03602    oi1 = dahdi_get_index(c1, p1, 0);
03603    if ((oi0 < 0) || (oi1 < 0)) {
03604       ast_mutex_unlock(&c0->lock);
03605       ast_mutex_unlock(&c1->lock);
03606       return AST_BRIDGE_FAILED;
03607    }
03608 
03609    op0 = p0 = c0->tech_pvt;
03610    op1 = p1 = c1->tech_pvt;
03611    ofd0 = c0->fds[0];
03612    ofd1 = c1->fds[0];
03613    oc0 = p0->owner;
03614    oc1 = p1->owner;
03615 
03616    if (ast_mutex_trylock(&p0->lock)) {
03617       /* Don't block, due to potential for deadlock */
03618       ast_mutex_unlock(&c0->lock);
03619       ast_mutex_unlock(&c1->lock);
03620       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03621       return AST_BRIDGE_RETRY;
03622    }
03623    if (ast_mutex_trylock(&p1->lock)) {
03624       /* Don't block, due to potential for deadlock */
03625       ast_mutex_unlock(&p0->lock);
03626       ast_mutex_unlock(&c0->lock);
03627       ast_mutex_unlock(&c1->lock);
03628       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
03629       return AST_BRIDGE_RETRY;
03630    }
03631 
03632    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03633       if (p0->owner && p1->owner) {
03634          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
03635          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
03636             master = p0;
03637             slave = p1;
03638             inconf = 1;
03639          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
03640             master = p1;
03641             slave = p0;
03642             inconf = 1;
03643          } else {
03644             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
03645             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
03646                p0->channel,
03647                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03648                p0->subs[SUB_REAL].inthreeway, p0->channel,
03649                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
03650                p1->subs[SUB_REAL].inthreeway);
03651          }
03652          nothingok = 0;
03653       }
03654    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
03655       if (p1->subs[SUB_THREEWAY].inthreeway) {
03656          master = p1;
03657          slave = p0;
03658          nothingok = 0;
03659       }
03660    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
03661       if (p0->subs[SUB_THREEWAY].inthreeway) {
03662          master = p0;
03663          slave = p1;
03664          nothingok = 0;
03665       }
03666    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
03667       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
03668          don't put us in anything */
03669       if (p1->subs[SUB_CALLWAIT].inthreeway) {
03670          master = p1;
03671          slave = p0;
03672          nothingok = 0;
03673       }
03674    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
03675       /* Same as previous */
03676       if (p0->subs[SUB_CALLWAIT].inthreeway) {
03677          master = p0;
03678          slave = p1;
03679          nothingok = 0;
03680       }
03681    }
03682    ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
03683       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
03684    if (master && slave) {
03685       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
03686          in an active threeway call with a channel that is ringing, we should
03687          indicate ringing. */
03688       if ((oi1 == SUB_THREEWAY) && 
03689           p1->subs[SUB_THREEWAY].inthreeway && 
03690           p1->subs[SUB_REAL].owner && 
03691           p1->subs[SUB_REAL].inthreeway && 
03692           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03693          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
03694          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
03695          os1 = p1->subs[SUB_REAL].owner->_state;
03696       } else {
03697          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
03698          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
03699       }
03700       if ((oi0 == SUB_THREEWAY) && 
03701           p0->subs[SUB_THREEWAY].inthreeway && 
03702           p0->subs[SUB_REAL].owner && 
03703           p0->subs[SUB_REAL].inthreeway && 
03704           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
03705          ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
03706          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
03707          os0 = p0->subs[SUB_REAL].owner->_state;
03708       } else {
03709          ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
03710          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
03711       }
03712       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
03713          if (!p0->echocanbridged || !p1->echocanbridged) {
03714             /* Disable echo cancellation if appropriate */
03715             dahdi_disable_ec(p0);
03716             dahdi_disable_ec(p1);
03717          }
03718       }
03719       dahdi_link(slave, master);
03720       master->inconference = inconf;
03721    } else if (!nothingok)
03722       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
03723 
03724    update_conf(p0);
03725    update_conf(p1);
03726    t0 = p0->subs[SUB_REAL].inthreeway;
03727    t1 = p1->subs[SUB_REAL].inthreeway;
03728 
03729    ast_mutex_unlock(&p0->lock);
03730    ast_mutex_unlock(&p1->lock);
03731 
03732    ast_mutex_unlock(&c0->lock);
03733    ast_mutex_unlock(&c1->lock);
03734 
03735    /* Native bridge failed */
03736    if ((!master || !slave) && !nothingok) {
03737       dahdi_enable_ec(p0);
03738       dahdi_enable_ec(p1);
03739       return AST_BRIDGE_FAILED;
03740    }
03741    
03742    if (option_verbose > 2) 
03743       ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03744 
03745    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03746       disable_dtmf_detect(op0);
03747 
03748    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03749       disable_dtmf_detect(op1);
03750 
03751    for (;;) {
03752       struct ast_channel *c0_priority[2] = {c0, c1};
03753       struct ast_channel *c1_priority[2] = {c1, c0};
03754 
03755       /* Here's our main loop...  Start by locking things, looking for private parts, 
03756          and then balking if anything is wrong */
03757       ast_mutex_lock(&c0->lock);
03758       while (ast_mutex_trylock(&c1->lock)) {
03759          DEADLOCK_AVOIDANCE(&c0->lock);
03760       }
03761 
03762       p0 = c0->tech_pvt;
03763       p1 = c1->tech_pvt;
03764 
03765       if (op0 == p0)
03766          i0 = dahdi_get_index(c0, p0, 1);
03767       if (op1 == p1)
03768          i1 = dahdi_get_index(c1, p1, 1);
03769       ast_mutex_unlock(&c0->lock);
03770       ast_mutex_unlock(&c1->lock);
03771 
03772       if (!timeoutms || 
03773           (op0 != p0) ||
03774           (op1 != p1) || 
03775           (ofd0 != c0->fds[0]) || 
03776           (ofd1 != c1->fds[0]) ||
03777           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
03778           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
03779           (oc0 != p0->owner) || 
03780           (oc1 != p1->owner) ||
03781           (t0 != p0->subs[SUB_REAL].inthreeway) ||
03782           (t1 != p1->subs[SUB_REAL].inthreeway) ||
03783           (oi0 != i0) ||
03784           (oi1 != i1)) {
03785          ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
03786             op0->channel, oi0, op1->channel, oi1);
03787          res = AST_BRIDGE_RETRY;
03788          goto return_from_bridge;
03789       }
03790 
03791 #ifdef PRI_2BCT
03792       q931c0 = p0->call;
03793       q931c1 = p1->call;
03794       if (p0->transfer && p1->transfer 
03795           && q931c0 && q931c1 
03796           && !triedtopribridge) {
03797          pri_channel_bridge(q931c0, q931c1);
03798          triedtopribridge = 1;
03799       }
03800 #endif
03801 
03802       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
03803       if (!who) {
03804          ast_log(LOG_DEBUG, "Ooh, empty read...\n");
03805          continue;
03806       }
03807       f = ast_read(who);
03808       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
03809          *fo = f;
03810          *rc = who;
03811          res = AST_BRIDGE_COMPLETE;
03812          goto return_from_bridge;
03813       }
03814       if (f->frametype == AST_FRAME_DTMF) {
03815          if ((who == c0) && p0->pulsedial) {
03816             ast_write(c1, f);
03817          } else if ((who == c1) && p1->pulsedial) {
03818             ast_write(c0, f);
03819          } else {
03820             *fo = f;
03821             *rc = who;
03822             res = AST_BRIDGE_COMPLETE;
03823             goto return_from_bridge;
03824          }
03825       }
03826       ast_frfree(f);
03827       
03828       /* Swap who gets priority */
03829       priority = !priority;
03830    }
03831 
03832 return_from_bridge:
03833    if (op0 == p0)
03834       dahdi_enable_ec(p0);
03835 
03836    if (op1 == p1)
03837       dahdi_enable_ec(p1);
03838 
03839    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
03840       enable_dtmf_detect(op0);
03841 
03842    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
03843       enable_dtmf_detect(op1);
03844 
03845    dahdi_unlink(slave, master, 1);
03846 
03847    return res;
03848 }

static int dahdi_call ( struct ast_channel ast,
char *  rdest,
int  timeout 
) [static]

Definition at line 2133 of file chan_dahdi.c.

References ast_channel::_state, ast_callerid_generate(), ast_copy_string(), AST_LAW, ast_log(), ast_malloc, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_transfercapability2str(), ast_verbose(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialednone, dahdi_pvt::dialing, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, free, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, IS_DIGITAL, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::logicalspan, MAX_CALLERID_SIZE, ast_channel::name, dahdi_pri::nationalprefix, dahdi_subchannel::needbusy, dahdi_subchannel::needringing, dahdi_pri::nodetype, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pvt::owner, pbx_builtin_getvar_helper(), dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), PRI_TRANS_CAP_DIGITAL, dahdi_pvt::priexclusive, dahdi_pvt::pulse, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::rxgain, s, send_callerid(), dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::stripmsd, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pvt::txgain, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.

02134 {
02135    struct dahdi_pvt *p = ast->tech_pvt;
02136    int x, res, index,mysig;
02137    char *c, *n, *l;
02138 #ifdef HAVE_PRI
02139    char *s = NULL;
02140 #endif
02141    char dest[256]; /* must be same length as p->dialdest */
02142    ast_mutex_lock(&p->lock);
02143    ast_copy_string(dest, rdest, sizeof(dest));
02144    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02145    if ((ast->_state == AST_STATE_BUSY)) {
02146       p->subs[SUB_REAL].needbusy = 1;
02147       ast_mutex_unlock(&p->lock);
02148       return 0;
02149    }
02150    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02151       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02152       ast_mutex_unlock(&p->lock);
02153       return -1;
02154    }
02155    p->dialednone = 0;
02156    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02157    {
02158       /* Special pseudo -- automatically up */
02159       ast_setstate(ast, AST_STATE_UP); 
02160       ast_mutex_unlock(&p->lock);
02161       return 0;
02162    }
02163    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02164    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02165    if (res)
02166       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02167    p->outgoing = 1;
02168 
02169    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02170 
02171    mysig = p->sig;
02172    if (p->outsigmod > -1)
02173       mysig = p->outsigmod;
02174 
02175    switch (mysig) {
02176    case SIG_FXOLS:
02177    case SIG_FXOGS:
02178    case SIG_FXOKS:
02179       if (p->owner == ast) {
02180          /* Normal ring, on hook */
02181          
02182          /* Don't send audio while on hook, until the call is answered */
02183          p->dialing = 1;
02184          if (p->use_callerid) {
02185             /* Generate the Caller-ID spill if desired */
02186             if (p->cidspill) {
02187                ast_log(LOG_WARNING, "cidspill already exists??\n");
02188                free(p->cidspill);
02189             }
02190             p->callwaitcas = 0;
02191             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02192                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02193                p->cidpos = 0;
02194                send_callerid(p);
02195             }
02196          }
02197          /* Choose proper cadence */
02198          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02199             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02200                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02201             p->cidrings = cidrings[p->distinctivering - 1];
02202          } else {
02203             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02204                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02205             p->cidrings = p->sendcalleridafter;
02206          }
02207 
02208          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02209          c = strchr(dest, '/');
02210          if (c)
02211             c++;
02212          if (c && (strlen(c) < p->stripmsd)) {
02213             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02214             c = NULL;
02215          }
02216          if (c) {
02217             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02218             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02219             ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
02220          } else {
02221             p->dop.dialstr[0] = '\0';
02222          }
02223          x = DAHDI_RING;
02224          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02225             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02226             ast_mutex_unlock(&p->lock);
02227             return -1;
02228          }
02229          p->dialing = 1;
02230       } else {
02231          /* Call waiting call */
02232          p->callwaitrings = 0;
02233          if (ast->cid.cid_num)
02234             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02235          else
02236             p->callwait_num[0] = '\0';
02237          if (ast->cid.cid_name)
02238             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02239          else
02240             p->callwait_name[0] = '\0';
02241          /* Call waiting tone instead */
02242          if (dahdi_callwait(ast)) {
02243             ast_mutex_unlock(&p->lock);
02244             return -1;
02245          }
02246          /* Make ring-back */
02247          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02248             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02249             
02250       }
02251       n = ast->cid.cid_name;
02252       l = ast->cid.cid_num;
02253       if (l)
02254          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02255       else
02256          p->lastcid_num[0] = '\0';
02257       if (n)
02258          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02259       else
02260          p->lastcid_name[0] = '\0';
02261       ast_setstate(ast, AST_STATE_RINGING);
02262       index = dahdi_get_index(ast, p, 0);
02263       if (index > -1) {
02264          p->subs[index].needringing = 1;
02265       }
02266       break;
02267    case SIG_FXSLS:
02268    case SIG_FXSGS:
02269    case SIG_FXSKS:
02270    case SIG_EMWINK:
02271    case SIG_EM:
02272    case SIG_EM_E1:
02273    case SIG_FEATD:
02274    case SIG_FEATDMF:
02275    case SIG_E911:
02276    case SIG_FGC_CAMA:
02277    case SIG_FGC_CAMAMF:
02278    case SIG_FEATB:
02279    case SIG_SFWINK:
02280    case SIG_SF:
02281    case SIG_SF_FEATD:
02282    case SIG_SF_FEATDMF:
02283    case SIG_FEATDMF_TA:
02284    case SIG_SF_FEATB:
02285       c = strchr(dest, '/');
02286       if (c)
02287          c++;
02288       else
02289          c = "";
02290       if (strlen(c) < p->stripmsd) {
02291          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02292          ast_mutex_unlock(&p->lock);
02293          return -1;
02294       }
02295 #ifdef HAVE_PRI
02296       /* Start the trunk, if not GR-303 */
02297       if (!p->pri) {
02298 #endif
02299          x = DAHDI_START;
02300          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02301          if (res < 0) {
02302             if (errno != EINPROGRESS) {
02303                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02304                ast_mutex_unlock(&p->lock);
02305                return -1;
02306             }
02307          }
02308 #ifdef HAVE_PRI
02309       }
02310 #endif
02311       ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
02312       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02313 
02314       c += p->stripmsd;
02315 
02316       switch (mysig) {
02317       case SIG_FEATD:
02318          l = ast->cid.cid_num;
02319          if (l) 
02320             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02321          else
02322             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02323          break;
02324       case SIG_FEATDMF:
02325          l = ast->cid.cid_num;
02326          if (l) 
02327             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02328          else
02329             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02330          break;
02331       case SIG_FEATDMF_TA:
02332       {
02333          const char *cic, *ozz;
02334 
02335          /* If you have to go through a Tandem Access point you need to use this */
02336          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02337          if (!ozz)
02338             ozz = defaultozz;
02339          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02340          if (!cic)
02341             cic = defaultcic;
02342          if (!ozz || !cic) {
02343             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02344             ast_mutex_unlock(&p->lock);
02345             return -1;
02346          }
02347          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02348          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02349          p->whichwink = 0;
02350       }
02351          break;
02352       case SIG_E911:
02353          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02354          break;
02355       case SIG_FGC_CAMA:
02356          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02357          break;
02358       case SIG_FGC_CAMAMF:
02359       case SIG_FEATB:
02360          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02361          break;
02362       default:
02363          if (p->pulse)
02364             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02365          else
02366             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02367          break;
02368       }
02369 
02370       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02371          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02372          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02373          p->echorest[sizeof(p->echorest) - 1] = '\0';
02374          p->echobreak = 1;
02375          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02376       } else
02377          p->echobreak = 0;
02378       if (!res) {
02379          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02380             int saveerr = errno;
02381 
02382             x = DAHDI_ONHOOK;
02383             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02384             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02385             ast_mutex_unlock(&p->lock);
02386             return -1;
02387          }
02388       } else
02389          ast_log(LOG_DEBUG, "Deferring dialing...\n");
02390       p->dialing = 1;
02391       if (ast_strlen_zero(c))
02392          p->dialednone = 1;
02393       ast_setstate(ast, AST_STATE_DIALING);
02394       break;
02395    case 0:
02396       /* Special pseudo -- automatically up*/
02397       ast_setstate(ast, AST_STATE_UP);
02398       break;      
02399    case SIG_PRI:
02400       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02401       p->dialdest[0] = '\0';
02402       p->dialing = 1;
02403       break;
02404    default:
02405       ast_log(LOG_DEBUG, "not yet implemented\n");
02406       ast_mutex_unlock(&p->lock);
02407       return -1;
02408    }
02409 #ifdef HAVE_PRI
02410    if (p->pri) {
02411       struct pri_sr *sr;
02412 #ifdef SUPPORT_USERUSER
02413       const char *useruser;
02414 #endif
02415       int pridialplan;
02416       int dp_strip;
02417       int prilocaldialplan;
02418       int ldp_strip;
02419       int exclusive;
02420       const char *rr_str;
02421       int redirect_reason;
02422 
02423       c = strchr(dest, '/');
02424       if (c) {
02425          c++;
02426       } else {
02427          c = "";
02428       }
02429 
02430       l = NULL;
02431       n = NULL;
02432       if (!p->hidecallerid) {
02433          l = ast->cid.cid_num;
02434          if (!p->hidecalleridname) {
02435             n = ast->cid.cid_name;
02436          }
02437       }
02438 
02439 
02440       if (strlen(c) < p->stripmsd) {
02441          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02442          ast_mutex_unlock(&p->lock);
02443          return -1;
02444       }
02445       if (mysig != SIG_FXSKS) {
02446          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02447          s = strchr(c + p->stripmsd, 'w');
02448          if (s) {
02449             if (strlen(s) > 1)
02450                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02451             else
02452                p->dop.dialstr[0] = '\0';
02453             *s = '\0';
02454          } else {
02455             p->dop.dialstr[0] = '\0';
02456          }
02457       }
02458       if (pri_grab(p, p->pri)) {
02459          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02460          ast_mutex_unlock(&p->lock);
02461          return -1;
02462       }
02463       if (!(p->call = pri_new_call(p->pri->pri))) {
02464          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02465          pri_rel(p->pri);
02466          ast_mutex_unlock(&p->lock);
02467          return -1;
02468       }
02469       if (!(sr = pri_sr_new())) {
02470          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02471          pri_destroycall(p->pri->pri, p->call);
02472          p->call = NULL;
02473          pri_rel(p->pri);
02474          ast_mutex_unlock(&p->lock);
02475          return -1;
02476       }
02477       if (p->bearer || (mysig == SIG_FXSKS)) {
02478          if (p->bearer) {
02479             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);
02480             p->bearer->call = p->call;
02481          } else
02482             ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
02483          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02484       }
02485       p->digital = IS_DIGITAL(ast->transfercapability);
02486 
02487       /* Should the picked channel be used exclusively? */
02488       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
02489          exclusive = 1;
02490       } else {
02491          exclusive = 0;
02492       }
02493       
02494       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02495       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02496                (p->digital ? -1 : 
02497                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02498       if (p->pri->facilityenable)
02499          pri_facility_enable(p->pri->pri);
02500 
02501       if (option_verbose > 2)
02502          ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02503       dp_strip = 0;
02504       pridialplan = p->pri->dialplan - 1;
02505       if (pridialplan == -2) { /* compute dynamically */
02506          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02507             dp_strip = strlen(p->pri->internationalprefix);
02508             pridialplan = PRI_INTERNATIONAL_ISDN;
02509          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02510             dp_strip = strlen(p->pri->nationalprefix);
02511             pridialplan = PRI_NATIONAL_ISDN;
02512          } else {
02513             pridialplan = PRI_LOCAL_ISDN;
02514          }
02515       }
02516       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
02517 
02518       ldp_strip = 0;
02519       prilocaldialplan = p->pri->localdialplan - 1;
02520       if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
02521          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02522             ldp_strip = strlen(p->pri->internationalprefix);
02523             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
02524          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02525             ldp_strip = strlen(p->pri->nationalprefix);
02526             prilocaldialplan = PRI_NATIONAL_ISDN;
02527          } else {
02528             prilocaldialplan = PRI_LOCAL_ISDN;
02529          }
02530       }
02531       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
02532          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
02533       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
02534          if (!strcasecmp(rr_str, "UNKNOWN"))
02535             redirect_reason = 0;
02536          else if (!strcasecmp(rr_str, "BUSY"))
02537             redirect_reason = 1;
02538          else if (!strcasecmp(rr_str, "NO_REPLY"))
02539             redirect_reason = 2;
02540          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
02541             redirect_reason = 15;
02542          else
02543             redirect_reason = PRI_REDIR_UNCONDITIONAL;
02544       } else
02545          redirect_reason = PRI_REDIR_UNCONDITIONAL;
02546       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
02547 
02548 #ifdef SUPPORT_USERUSER
02549       /* User-user info */
02550       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
02551 
02552       if (useruser)
02553          pri_sr_set_useruser(sr, useruser);
02554 #endif
02555 
02556       if (pri_setup(p->pri->pri, p->call, sr)) {
02557          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
02558             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
02559          pri_rel(p->pri);
02560          ast_mutex_unlock(&p->lock);
02561          pri_sr_free(sr);
02562          return -1;
02563       }
02564       pri_sr_free(sr);
02565       ast_setstate(ast, AST_STATE_DIALING);
02566       pri_rel(p->pri);
02567    }
02568 #endif      
02569    ast_mutex_unlock(&p->lock);
02570    return 0;
02571 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 2105 of file chan_dahdi.c.

References ast_gen_cas(), AST_LAW, ast_log(), ast_malloc, dahdi_pvt::callwaitcas, CALLWAITING_REPEAT_SAMPLES, dahdi_pvt::callwaitingcallerid, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, free, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.

Referenced by dahdi_call(), and dahdi_read().

02106 {
02107    struct dahdi_pvt *p = ast->tech_pvt;
02108    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02109    if (p->cidspill) {
02110       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02111       free(p->cidspill);
02112    }
02113    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02114       return -1;
02115    save_conference(p);
02116    /* Silence */
02117    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02118    if (!p->callwaitrings && p->callwaitingcallerid) {
02119       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02120       p->callwaitcas = 1;
02121       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02122    } else {
02123       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02124       p->callwaitcas = 0;
02125       p->cidlen = 2400 + READ_SIZE * 4;
02126    }
02127    p->cidpos = 0;
02128    send_callerid(p);
02129    
02130    return 0;
02131 }

static struct dahdi_chan_conf dahdi_chan_conf_default ( void   )  [static]

returns a new dahdi_chan_conf with default values (by-value)

Definition at line 924 of file chan_dahdi.c.

References CID_SIG_BELL, CID_START_RING, DEFAULT_CIDRINGS, dahdi_pri::nsf, and dahdi_chan_conf::pri.

Referenced by setup_dahdi().

00924                                                             {
00925    /* recall that if a field is not included here it is initialized
00926     * to 0 or equivalent
00927     */
00928    struct dahdi_chan_conf conf = {
00929 #ifdef HAVE_PRI
00930       .pri = {
00931          .nsf = PRI_NSF_NONE,
00932          .switchtype = PRI_SWITCH_NI2,
00933          .dialplan = PRI_NATIONAL_ISDN + 1,
00934          .localdialplan = PRI_NATIONAL_ISDN + 1,
00935          .nodetype = PRI_CPE,
00936 
00937          .minunused = 2,
00938          .idleext = "",
00939          .idledial = "",
00940          .internationalprefix = "",
00941          .nationalprefix = "",
00942          .localprefix = "",
00943          .privateprefix = "",
00944          .unknownprefix = "",
00945 
00946          .resetinterval = 3600
00947       },
00948 #endif
00949       .chan = {
00950          .context = "default",
00951          .cid_num = "",
00952          .cid_name = "",
00953          .mohinterpret = "default",
00954          .mohsuggest = "",
00955          .transfertobusy = 1,
00956 
00957          .cid_signalling = CID_SIG_BELL,
00958          .cid_start = CID_START_RING,
00959          .dahditrcallerid = 0,
00960          .use_callerid = 1,
00961          .sig = -1,
00962          .outsigmod = -1,
00963 
00964          .tonezone = -1,
00965 
00966          .echocancel = 1,
00967 
00968          .busycount = 3,
00969          .busycompare = 0,
00970          .busytonelength = 0,
00971          .busyquietlength = 0,
00972          .busyfuzziness = 0,
00973          .silencethreshold = 0,
00974 
00975          .accountcode = "",
00976 
00977          .mailbox = "",
00978 
00979 
00980          .polarityonanswerdelay = 600,
00981 
00982          .sendcalleridafter = DEFAULT_CIDRINGS,
00983 
00984          .buf_policy = DAHDI_POLICY_IMMEDIATE,
00985          .buf_no = numbufs
00986       },
00987       .timing = {
00988          .prewinktime = -1,
00989          .preflashtime = -1,
00990          .winktime = -1,
00991          .flashtime = -1,
00992          .starttime = -1,
00993          .rxwinktime = -1,
00994          .rxflashtime = -1,
00995          .debouncetime = -1
00996       },
00997       .smdi_port = "/dev/ttyS0",
00998    };
00999 
01000    return conf;
01001 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 1268 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

01269 {
01270    if (fd > 0)
01271       close(fd);
01272 }

static void dahdi_close_pri_fd ( struct dahdi_pri pri,
int  fd_num 
) [static]

Definition at line 1281 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

Referenced by __unload_module(), dahdi_restart(), and start_pri().

01282 {
01283    dahdi_close(pri->fds[fd_num]);
01284    pri->fds[fd_num] = -1;
01285 }

static void dahdi_close_sub ( struct dahdi_pvt chan_pvt,
int  sub_num 
) [static]

Definition at line 1274 of file chan_dahdi.c.

References dahdi_close(), dahdi_subchannel::dfd, and dahdi_pvt::subs.

Referenced by alloc_sub(), destroy_dahdi_pvt(), and unalloc_sub().

01275 {
01276    dahdi_close(chan_pvt->subs[sub_num].dfd);
01277    chan_pvt->subs[sub_num].dfd = -1;
01278 }

static int dahdi_confmute ( struct dahdi_pvt p,
int  muted 
) [inline, static]

Definition at line 1989 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, LOG_WARNING, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_dtmfup(), dahdi_handle_event(), dahdi_hangup(), and dahdi_new().

01990 {
01991    int x, y, res;
01992    x = muted;
01993    if (p->sig == SIG_PRI) {
01994       y = 1;
01995       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
01996       if (res)
01997          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
01998    }
01999    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02000    if (res < 0)
02001       ast_log(LOG_WARNING, "dahdi confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02002    return res;
02003 }

static int dahdi_destroy_channel ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10407 of file chan_dahdi.c.

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

10408 {
10409    int channel;
10410    
10411    if (argc != 4)
10412       return RESULT_SHOWUSAGE;
10413    
10414    channel = atoi(argv[3]);
10415 
10416    return dahdi_destroy_channel_bynum(channel);
10417 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 7044 of file chan_dahdi.c.

References ast_module_unref(), dahdi_pvt::channel, destroy_channel(), iflist, dahdi_pvt::next, dahdi_pvt::prev, RESULT_FAILURE, RESULT_SUCCESS, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel(), and handle_init_event().

07045 {
07046    struct dahdi_pvt *tmp = NULL;
07047    struct dahdi_pvt *prev = NULL;
07048 
07049    tmp = iflist;
07050    while (tmp) {
07051       if (tmp->channel == channel) {
07052          int x = DAHDI_FLASH;
07053          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 */
07054          destroy_channel(prev, tmp, 1);
07055          ast_module_unref(ast_module_info->self);
07056          return RESULT_SUCCESS;
07057       }
07058       prev = tmp;
07059       tmp = tmp->next;
07060    }
07061    return RESULT_FAILURE;
07062 }

static int dahdi_digit_begin ( struct ast_channel ast,
char  digit 
) [static]

Definition at line 1365 of file chan_dahdi.c.

References ast_channel::_state, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, dahdi_get_index(), dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::pulse, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

01366 {
01367    struct dahdi_pvt *pvt;
01368    int index;
01369    int dtmf = -1;
01370    
01371    pvt = chan->tech_pvt;
01372 
01373    ast_mutex_lock(&pvt->lock);
01374 
01375    index = dahdi_get_index(chan, pvt, 0);
01376 
01377    if ((index != SUB_REAL) || !pvt->owner)
01378       goto out;
01379 
01380 #ifdef HAVE_PRI
01381    if ((pvt->sig == SIG_PRI) && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01382       if (pvt->setup_ack) {
01383          if (!pri_grab(pvt, pvt->pri)) {
01384             pri_information(pvt->pri->pri, pvt->call, digit);
01385             pri_rel(pvt->pri);
01386          } else
01387             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01388       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01389          int res;
01390          ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01391          res = strlen(pvt->dialdest);
01392          pvt->dialdest[res++] = digit;
01393          pvt->dialdest[res] = '\0';
01394       }
01395       goto out;
01396    }
01397 #endif
01398    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01399       goto out;
01400 
01401    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01402       int res;
01403       struct dahdi_dialoperation zo = {
01404          .op = DAHDI_DIAL_OP_APPEND,
01405          .dialstr[0] = 'T',
01406          .dialstr[1] = digit,
01407          .dialstr[2] = 0,
01408       };
01409       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01410          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01411       else
01412          pvt->dialing = 1;
01413    } else {
01414       ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
01415       pvt->dialing = 1;
01416       pvt->begindigit = digit;
01417    }
01418 
01419 out:
01420    ast_mutex_unlock(&pvt->lock);
01421 
01422    return 0;
01423 }

static int dahdi_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
) [static]

Definition at line 1425 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::begindigit, dahdi_get_index(), dahdi_pvt::dialing, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

01426 {
01427    struct dahdi_pvt *pvt;
01428    int res = 0;
01429    int index;
01430    int x;
01431    
01432    pvt = chan->tech_pvt;
01433 
01434    ast_mutex_lock(&pvt->lock);
01435    
01436    index = dahdi_get_index(chan, pvt, 0);
01437 
01438    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01439       goto out;
01440 
01441 #ifdef HAVE_PRI
01442    /* This means that the digit was already sent via PRI signalling */
01443    if (pvt->sig == SIG_PRI && !pvt->begindigit)
01444       goto out;
01445 #endif
01446 
01447    if (pvt->begindigit) {
01448       x = -1;
01449       ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
01450       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01451       pvt->dialing = 0;
01452       pvt->begindigit = 0;
01453    }
01454 
01455 out:
01456    ast_mutex_unlock(&pvt->lock);
01457 
01458    return res;
01459 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1820 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), dahdi_hangup(), dahdi_setoption(), and handle_init_event().

01821 {
01822    int x;
01823    int res;
01824    if (p->echocancel) {
01825       x = 0;
01826       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01827       if (res)
01828          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
01829       else if (option_debug)
01830          ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
01831    }
01832    p->echocanon = 0;
01833 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1770 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::sig, SIG_PRI, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_handle_event(), dahdi_setoption(), handle_init_event(), and ss_thread().

01771 {
01772    int x;
01773    int res;
01774    if (!p)
01775       return;
01776    if (p->echocanon) {
01777       ast_log(LOG_DEBUG, "Echo cancellation already on\n");
01778       return;
01779    }
01780    if (p->digital) {
01781       ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
01782       return;
01783    }
01784    if (p->echocancel) {
01785       if (p->sig == SIG_PRI) {
01786          x = 1;
01787          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
01788          if (res)
01789             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
01790       }
01791       x = p->echocancel;
01792       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL, &x);
01793       if (res) 
01794          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
01795       else {
01796          p->echocanon = 1;
01797          if (option_debug)
01798             ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
01799       }
01800    } else if (option_debug)
01801       ast_log(LOG_DEBUG, "No echo cancellation requested\n");
01802 }

static struct ast_frame * dahdi_exception ( struct ast_channel ast  )  [static]

Definition at line 5067 of file chan_dahdi.c.

References __dahdi_exception(), ast_mutex_lock, ast_mutex_unlock, f, dahdi_pvt::lock, and ast_channel::tech_pvt.

05068 {
05069    struct dahdi_pvt *p = ast->tech_pvt;
05070    struct ast_frame *f;
05071    ast_mutex_lock(&p->lock);
05072    f = __dahdi_exception(ast);
05073    ast_mutex_unlock(&p->lock);
05074    return f;
05075 }

static int dahdi_fake_event ( struct dahdi_pvt p,
int  mode 
) [static]

Definition at line 10937 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::fake_event, HANGUP, ast_channel::name, dahdi_pvt::owner, and TRANSFER.

Referenced by __action_transfer(), and __action_transferhangup().

10938 {
10939    if (p) {
10940       switch (mode) {
10941          case TRANSFER:
10942             p->fake_event = DAHDI_EVENT_WINKFLASH;
10943             break;
10944          case HANGUP:
10945             p->fake_event = DAHDI_EVENT_ONHOOK;
10946             break;
10947          default:
10948             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10949       }
10950    }
10951    return 0;
10952 }

static int dahdi_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 3850 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, dahdi_pvt::channel, dahdi_unlink(), dahdi_pvt::lock, LOG_DEBUG, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, and ast_channel::tech_pvt.

03851 {
03852    struct dahdi_pvt *p = newchan->tech_pvt;
03853    int x;
03854    ast_mutex_lock(&p->lock);
03855    ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
03856    if (p->owner == oldchan) {
03857       p->owner = newchan;
03858    }
03859    for (x = 0; x < 3; x++)
03860       if (p->subs[x].owner == oldchan) {
03861          if (!x)
03862             dahdi_unlink(NULL, p, 0);
03863          p->subs[x].owner = newchan;
03864       }
03865    if (newchan->_state == AST_STATE_RINGING) 
03866       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
03867    update_conf(p);
03868    ast_mutex_unlock(&p->lock);
03869    return 0;
03870 }

static int dahdi_func_read ( struct ast_channel chan,
char *  function,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 3422 of file chan_dahdi.c.

References ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::lock, dahdi_pvt::rxgain, ast_channel::tech_pvt, and dahdi_pvt::txgain.

03423 {
03424    struct dahdi_pvt *p = chan->tech_pvt;
03425    
03426    if (!strcasecmp(data, "rxgain")) {
03427       ast_mutex_lock(&p->lock);
03428       snprintf(buf, len, "%f", p->rxgain);
03429       ast_mutex_unlock(&p->lock);   
03430    } else if (!strcasecmp(data, "txgain")) {
03431       ast_mutex_lock(&p->lock);
03432       snprintf(buf, len, "%f", p->txgain);
03433       ast_mutex_unlock(&p->lock);   
03434    } else {
03435       ast_copy_string(buf, "", len);
03436    }
03437    return 0;
03438 }

static int dahdi_get_event ( int  fd  )  [inline, static]

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 256 of file chan_dahdi.c.

Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().

00257 {
00258    int j;
00259    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00260       return -1;
00261    return j;
00262 }

static int dahdi_get_index ( struct ast_channel ast,
struct dahdi_pvt p,
int  nullok 
) [static]

Definition at line 1117 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_answer(), dahdi_bridge(), dahdi_call(), dahdi_digit_begin(), dahdi_digit_end(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_read(), dahdi_sendtext(), dahdi_setoption(), dahdi_write(), and ss_thread().

01118 {
01119    int res;
01120    if (p->subs[SUB_REAL].owner == ast)
01121       res = 0;
01122    else if (p->subs[SUB_CALLWAIT].owner == ast)
01123       res = 1;
01124    else if (p->subs[SUB_THREEWAY].owner == ast)
01125       res = 2;
01126    else {
01127       res = -1;
01128       if (!nullok)
01129          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01130    }
01131    return res;
01132 }

static void dahdi_handle_dtmfup ( struct ast_channel ast,
int  index,
struct ast_frame **  dest 
) [static]

Definition at line 4014 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, ast_channel::cid, ast_callerid::cid_num, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, ast_channel::context, dahdi_confmute(), ast_channel::exten, dahdi_subchannel::f, f, dahdi_pvt::faxhandled, ast_frame::frametype, free, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, option_debug, option_verbose, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event(), and dahdi_read().

04015 {
04016    struct dahdi_pvt *p = ast->tech_pvt;
04017    struct ast_frame *f = *dest;
04018 
04019    if (option_debug)
04020       ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04021 
04022    if (p->confirmanswer) {
04023       if (option_debug)
04024          ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
04025       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04026          of a DTMF digit */
04027       p->subs[index].f.frametype = AST_FRAME_CONTROL;
04028       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04029       *dest = &p->subs[index].f;
04030       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04031       p->confirmanswer = 0;
04032    } else if (p->callwaitcas) {
04033       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04034          if (option_debug)
04035             ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
04036          if (p->cidspill)
04037             free(p->cidspill);
04038          send_cwcidspill(p);
04039       }
04040       if ((f->subclass != 'm') && (f->subclass != 'u')) 
04041          p->callwaitcas = 0;
04042       p->subs[index].f.frametype = AST_FRAME_NULL;
04043       p->subs[index].f.subclass = 0;
04044       *dest = &p->subs[index].f;
04045    } else if (f->subclass == 'f') {
04046       /* Fax tone -- Handle and return NULL */
04047       if ((p->callprogress & 0x6) && !p->faxhandled) {
04048          p->faxhandled = 1;
04049          if (strcmp(ast->exten, "fax")) {
04050             const char *target_context = S_OR(ast->macrocontext, ast->context);
04051 
04052             /* We need to unlock 'ast' here because ast_exists_extension has the
04053              * potential to start autoservice on the channel. Such action is prone
04054              * to deadlock.
04055              */
04056             ast_mutex_unlock(&p->lock);
04057             ast_channel_unlock(ast);
04058             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04059                ast_channel_lock(ast);
04060                ast_mutex_lock(&p->lock);
04061                if (option_verbose > 2)
04062                   ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
04063                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04064                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04065                if (ast_async_goto(ast, target_context, "fax", 1))
04066                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04067             } else {
04068                ast_channel_lock(ast);
04069                ast_mutex_lock(&p->lock);
04070                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04071             }
04072          } else if (option_debug)
04073             ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
04074       } else if (option_debug)
04075             ast_log(LOG_DEBUG, "Fax already handled\n");
04076       dahdi_confmute(p, 0);
04077       p->subs[index].f.frametype = AST_FRAME_NULL;
04078       p->subs[index].f.subclass = 0;
04079       *dest = &p->subs[index].f;
04080    } else if (f->subclass == 'm') {
04081       /* Confmute request */
04082       dahdi_confmute(p, 1);
04083       p->subs[index].f.frametype = AST_FRAME_NULL;
04084       p->subs[index].f.subclass = 0;
04085       *dest = &p->subs[index].f;    
04086    } else if (f->subclass == 'u') {
04087       /* Unmute */
04088       dahdi_confmute(p, 0);
04089       p->subs[index].f.frametype = AST_FRAME_NULL;
04090       p->subs[index].f.subclass = 0;
04091       *dest = &p->subs[index].f;    
04092    } else
04093       dahdi_confmute(p, 0);
04094 }

static struct ast_frame* dahdi_handle_event ( struct ast_channel ast  )  [static]

Definition at line 4116 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_hangup(), ast_log(), ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_pthread_create, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verbose(), attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, dahdi_pvt::channel, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), DAHDI_EVENT_DTMFDOWN, DAHDI_EVENT_DTMFUP, dahdi_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pvt::dop, dahdi_pvt::echobreak, dahdi_pvt::echocanon, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, LOG_NOTICE, ast_frame::mallocd, manager_event(), MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, ast_channel::name, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), dahdi_pvt::unknown_alarm, update_conf(), VERBOSE_PREFIX_3, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

04117 {
04118    int res, x;
04119    int index, mysig;
04120    char *c;
04121    struct dahdi_pvt *p = ast->tech_pvt;
04122    pthread_t threadid;
04123    pthread_attr_t attr;
04124    struct ast_channel *chan;
04125    struct ast_frame *f;
04126 
04127    index = dahdi_get_index(ast, p, 0);
04128    mysig = p->sig;
04129    if (p->outsigmod > -1)
04130       mysig = p->outsigmod;
04131    p->subs[index].f.frametype = AST_FRAME_NULL;
04132    p->subs[index].f.subclass = 0;
04133    p->subs[index].f.datalen = 0;
04134    p->subs[index].f.samples = 0;
04135    p->subs[index].f.mallocd = 0;
04136    p->subs[index].f.offset = 0;
04137    p->subs[index].f.src = "dahdi_handle_event";
04138    p->subs[index].f.data = NULL;
04139    f = &p->subs[index].f;
04140 
04141    if (index < 0)
04142       return &p->subs[index].f;
04143    if (p->fake_event) {
04144       res = p->fake_event;
04145       p->fake_event = 0;
04146    } else
04147       res = dahdi_get_event(p->subs[index].dfd);
04148 
04149    if (option_debug)
04150       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04151 
04152    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04153       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04154 
04155       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04156 #ifdef HAVE_PRI
04157       if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
04158          /* absorb event */
04159       } else {
04160 #endif
04161          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04162          p->subs[index].f.subclass = res & 0xff;
04163 #ifdef HAVE_PRI
04164       }
04165 #endif
04166       dahdi_handle_dtmfup(ast, index, &f);
04167       return f;
04168    }
04169 
04170    if (res & DAHDI_EVENT_DTMFDOWN) {
04171       if (option_debug)
04172          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04173       /* Mute conference */
04174       dahdi_confmute(p, 1);
04175       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04176       p->subs[index].f.subclass = res & 0xff;
04177       return &p->subs[index].f;
04178    }
04179 
04180    switch (res) {
04181 #ifdef DAHDI_EVENT_EC_DISABLED
04182       case DAHDI_EVENT_EC_DISABLED:
04183          if (option_verbose > 2) 
04184             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04185          p->echocanon = 0;
04186          break;
04187 #endif
04188       case DAHDI_EVENT_BITSCHANGED:
04189          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04190       case DAHDI_EVENT_PULSE_START:
04191          /* Stop tone if there's a pulse start and the PBX isn't started */
04192          if (!ast->pbx)
04193             tone_zone_play_tone(p->subs[index].dfd, -1);
04194          break;   
04195       case DAHDI_EVENT_DIALCOMPLETE:
04196          if (p->inalarm) break;
04197          if ((p->radio || (p->oprmode < 0))) break;
04198          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
04199             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04200             return NULL;
04201          }
04202          if (!x) { /* if not still dialing in driver */
04203             dahdi_enable_ec(p);
04204             if (p->echobreak) {
04205                dahdi_train_ec(p);
04206                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04207                p->dop.op = DAHDI_DIAL_OP_REPLACE;
04208                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04209                p->echobreak = 0;
04210             } else {
04211                p->dialing = 0;
04212                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04213                   /* if thru with dialing after offhook */
04214                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04215                      ast_setstate(ast, AST_STATE_UP);
04216                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
04217                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04218                      break;
04219                   } else { /* if to state wait for offhook to dial rest */
04220                      /* we now wait for off hook */
04221                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04222                   }
04223                }
04224                if (ast->_state == AST_STATE_DIALING) {
04225                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04226                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
04227                   } 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)))) {
04228                      ast_setstate(ast, AST_STATE_RINGING);
04229                   } else if (!p->answeronpolarityswitch) {
04230                      ast_setstate(ast, AST_STATE_UP);
04231                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
04232                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04233                      /* If aops=0 and hops=1, this is necessary */
04234                      p->polarity = POLARITY_REV;
04235                   } else {
04236                      /* Start clean, so we can catch the change to REV polarity when party answers */
04237                      p->polarity = POLARITY_IDLE;
04238                   }
04239                }
04240             }
04241          }
04242          break;
04243       case DAHDI_EVENT_ALARM:
04244 #ifdef HAVE_PRI
04245          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04246             /* T309 is not enabled : hangup calls when alarm occurs */
04247             if (p->call) {
04248                if (p->pri && p->pri->pri) {
04249                   if (!pri_grab(p, p->pri)) {
04250                      pri_hangup(p->pri->pri, p->call, -1);
04251                      pri_destroycall(p->pri->pri, p->call);
04252                      p->call = NULL;
04253                      pri_rel(p->pri);
04254                   } else
04255                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04256                } else
04257                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04258             }
04259             if (p->owner)
04260                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04261          }
04262          if (p->bearer)
04263             p->bearer->inalarm = 1;
04264          else
04265 #endif
04266          p->inalarm = 1;
04267          res = get_alarms(p);
04268          handle_alarms(p, res);
04269 #ifdef HAVE_LIBPRI
04270          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04271             /* fall through intentionally */
04272          } else {
04273             break;
04274          }
04275 #endif
04276       case DAHDI_EVENT_ONHOOK:
04277          if (p->radio) {
04278             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04279             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04280             break;
04281          }
04282          if (p->oprmode < 0)
04283          {
04284             if (p->oprmode != -1) break;
04285             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04286             {
04287                /* Make sure it starts ringing */
04288                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04289                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04290                save_conference(p->oprpeer);
04291                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04292             }
04293             break;
04294          }
04295          switch (p->sig) {
04296          case SIG_FXOLS:
04297          case SIG_FXOGS:
04298          case SIG_FXOKS:
04299             p->onhooktime = time(NULL);
04300             p->msgstate = -1;
04301             /* Check for some special conditions regarding call waiting */
04302             if (index == SUB_REAL) {
04303                /* The normal line was hung up */
04304                if (p->subs[SUB_CALLWAIT].owner) {
04305                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
04306                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04307                   if (option_verbose > 2) 
04308                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04309                   unalloc_sub(p, SUB_CALLWAIT); 
04310 #if 0
04311                   p->subs[index].needanswer = 0;
04312                   p->subs[index].needringing = 0;
04313 #endif                  
04314                   p->callwaitingrepeat = 0;
04315                   p->cidcwexpire = 0;
04316                   p->owner = NULL;
04317                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04318                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04319                      p->dialing = 1;
04320                   dahdi_ring_phone(p);
04321                } else if (p->subs[SUB_THREEWAY].owner) {
04322                   unsigned int mssinceflash;
04323                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04324                      the private structure -- not especially easy or clean */
04325                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04326                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04327                      ast_mutex_unlock(&p->lock);
04328                      DEADLOCK_AVOIDANCE(&ast->lock);
04329                      /* We can grab ast and p in that order, without worry.  We should make sure
04330                         nothing seriously bad has happened though like some sort of bizarre double
04331                         masquerade! */
04332                      ast_mutex_lock(&p->lock);
04333                      if (p->owner != ast) {
04334                         ast_log(LOG_WARNING, "This isn't good...\n");
04335                         return NULL;
04336                      }
04337                   }
04338                   if (!p->subs[SUB_THREEWAY].owner) {
04339                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04340                      return NULL;
04341                   }
04342                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04343                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04344                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04345                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04346                         hanging up.  Hangup both channels now */
04347                      if (p->subs[SUB_THREEWAY].owner)
04348                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04349                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04350                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04351                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04352                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04353                      if (p->transfer) {
04354                         /* In any case this isn't a threeway call anymore */
04355                         p->subs[SUB_REAL].inthreeway = 0;
04356                         p->subs[SUB_THREEWAY].inthreeway = 0;
04357                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04358                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04359                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04360                            /* Swap subs and dis-own channel */
04361                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04362                            p->owner = NULL;
04363                            /* Ring the phone */
04364                            dahdi_ring_phone(p);
04365                         } else {
04366                            if ((res = attempt_transfer(p)) < 0) {
04367                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04368                               if (p->subs[SUB_THREEWAY].owner)
04369                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04370                            } else if (res) {
04371                               /* Don't actually hang up at this point */
04372                               if (p->subs[SUB_THREEWAY].owner)
04373                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04374                               break;
04375                            }
04376                         }
04377                      } else {
04378                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04379                         if (p->subs[SUB_THREEWAY].owner)
04380                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04381                      }
04382                   } else {
04383                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04384                      /* Swap subs and dis-own channel */
04385                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04386                      p->owner = NULL;
04387                      /* Ring the phone */
04388                      dahdi_ring_phone(p);
04389                   }
04390                }
04391             } else {
04392                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04393             }
04394             /* Fall through */
04395          default:
04396             dahdi_disable_ec(p);
04397             return NULL;
04398          }
04399          break;
04400       case DAHDI_EVENT_RINGOFFHOOK:
04401          if (p->inalarm) break;
04402          if (p->oprmode < 0)
04403          {
04404             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04405             {
04406                /* Make sure it stops ringing */
04407                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04408                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04409                restore_conference(p->oprpeer);
04410             }
04411             break;
04412          }
04413          if (p->radio)
04414          {
04415             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04416             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04417             break;
04418          }
04419          /* for E911, its supposed to wait for offhook then dial
04420             the second half of the dial string */
04421          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04422             c = strchr(p->dialdest, '/');
04423             if (c)
04424                c++;
04425             else
04426                c = p->dialdest;
04427             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04428             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04429             if (strlen(p->dop.dialstr) > 4) {
04430                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04431                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04432                p->echorest[sizeof(p->echorest) - 1] = '\0';
04433                p->echobreak = 1;
04434                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04435             } else
04436                p->echobreak = 0;
04437             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04438                int saveerr = errno;
04439 
04440                x = DAHDI_ONHOOK;
04441                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04442                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04443                return NULL;
04444                }
04445             p->dialing = 1;
04446             return &p->subs[index].f;
04447          }
04448          switch (p->sig) {
04449          case SIG_FXOLS:
04450          case SIG_FXOGS:
04451          case SIG_FXOKS:
04452             switch (ast->_state) {
04453             case AST_STATE_RINGING:
04454                dahdi_enable_ec(p);
04455                dahdi_train_ec(p);
04456                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04457                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04458                /* Make sure it stops ringing */
04459                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04460                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04461                if (p->cidspill) {
04462                   /* Cancel any running CallerID spill */
04463                   free(p->cidspill);
04464                   p->cidspill = NULL;
04465                }
04466                p->dialing = 0;
04467                p->callwaitcas = 0;
04468                if (p->confirmanswer) {
04469                   /* Ignore answer if "confirm answer" is enabled */
04470                   p->subs[index].f.frametype = AST_FRAME_NULL;
04471                   p->subs[index].f.subclass = 0;
04472                } else if (!ast_strlen_zero(p->dop.dialstr)) {
04473                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
04474                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04475                   if (res < 0) {
04476                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04477                      p->dop.dialstr[0] = '\0';
04478                      return NULL;
04479                   } else {
04480                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04481                      p->subs[index].f.frametype = AST_FRAME_NULL;
04482                      p->subs[index].f.subclass = 0;
04483                      p->dialing = 1;
04484                   }
04485                   p->dop.dialstr[0] = '\0';
04486                   ast_setstate(ast, AST_STATE_DIALING);
04487                } else
04488                   ast_setstate(ast, AST_STATE_UP);
04489                return &p->subs[index].f;
04490             case AST_STATE_DOWN:
04491                ast_setstate(ast, AST_STATE_RING);
04492                ast->rings = 1;
04493                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04494                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04495                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04496                return &p->subs[index].f;
04497             case AST_STATE_UP:
04498                /* Make sure it stops ringing */
04499                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04500                /* Okay -- probably call waiting*/
04501                if (ast_bridged_channel(p->owner))
04502                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04503                p->subs[index].needunhold = 1;
04504                break;
04505             case AST_STATE_RESERVED:
04506                /* Start up dialtone */
04507                if (has_voicemail(p))
04508                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04509                else
04510                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04511                break;
04512             default:
04513                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04514             }
04515             break;
04516          case SIG_FXSLS:
04517          case SIG_FXSGS:
04518          case SIG_FXSKS:
04519             if (ast->_state == AST_STATE_RING) {
04520                p->ringt = p->ringt_base;
04521             }
04522 
04523             /* Fall through */
04524          case SIG_EM:
04525          case SIG_EM_E1:
04526          case SIG_EMWINK:
04527          case SIG_FEATD:
04528          case SIG_FEATDMF:
04529          case SIG_FEATDMF_TA:
04530          case SIG_E911:
04531          case SIG_FGC_CAMA:
04532          case SIG_FGC_CAMAMF:
04533          case SIG_FEATB:
04534          case SIG_SF:
04535          case SIG_SFWINK:
04536          case SIG_SF_FEATD:
04537          case SIG_SF_FEATDMF:
04538          case SIG_SF_FEATB:
04539             if (ast->_state == AST_STATE_PRERING)
04540                ast_setstate(ast, AST_STATE_RING);
04541             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04542                if (option_debug)
04543                   ast_log(LOG_DEBUG, "Ring detected\n");
04544                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04545                p->subs[index].f.subclass = AST_CONTROL_RING;
04546             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04547                if (option_debug)
04548                   ast_log(LOG_DEBUG, "Line answered\n");
04549                if (p->confirmanswer) {
04550                   p->subs[index].f.frametype = AST_FRAME_NULL;
04551                   p->subs[index].f.subclass = 0;
04552                } else {
04553                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
04554                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04555                   ast_setstate(ast, AST_STATE_UP);
04556                }
04557             } else if (ast->_state != AST_STATE_RING)
04558                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04559             break;
04560          default:
04561             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04562          }
04563          break;
04564 #ifdef DAHDI_EVENT_RINGBEGIN
04565       case DAHDI_EVENT_RINGBEGIN:
04566          switch (p->sig) {
04567          case SIG_FXSLS:
04568          case SIG_FXSGS:
04569          case SIG_FXSKS:
04570             if (ast->_state == AST_STATE_RING) {
04571                p->ringt = p->ringt_base;
04572             }
04573             break;
04574          }
04575          break;
04576 #endif         
04577       case DAHDI_EVENT_RINGEROFF:
04578          if (p->inalarm) break;
04579          if ((p->radio || (p->oprmode < 0))) break;
04580          ast->rings++;
04581          if ((ast->rings > p->cidrings) && (p->cidspill)) {
04582             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
04583             free(p->cidspill);
04584             p->cidspill = NULL;
04585             p->callwaitcas = 0;
04586          }
04587          p->subs[index].f.frametype = AST_FRAME_CONTROL;
04588          p->subs[index].f.subclass = AST_CONTROL_RINGING;
04589          break;
04590       case DAHDI_EVENT_RINGERON:
04591          break;
04592       case DAHDI_EVENT_NOALARM:
04593          p->inalarm = 0;
04594 #ifdef HAVE_PRI
04595          /* Extremely unlikely but just in case */
04596          if (p->bearer)
04597             p->bearer->inalarm = 0;
04598 #endif            
04599          if (!p->unknown_alarm) {
04600             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04601             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04602                "Channel: %d\r\n", p->channel);
04603          } else {
04604             p->unknown_alarm = 0;
04605          }
04606          break;
04607       case DAHDI_EVENT_WINKFLASH:
04608          if (p->inalarm) break;
04609          if (p->radio) break;
04610          if (p->oprmode < 0) break;
04611          if (p->oprmode > 1)
04612          {
04613             struct dahdi_params par;
04614 
04615             memset(&par, 0, sizeof(par));
04616             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
04617             {
04618                if (!par.rxisoffhook)
04619                {
04620                   /* Make sure it stops ringing */
04621                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04622                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
04623                   save_conference(p);
04624                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04625                }
04626             }
04627             break;
04628          }
04629          /* Remember last time we got a flash-hook */
04630          gettimeofday(&p->flashtime, NULL);
04631          switch (mysig) {
04632          case SIG_FXOLS:
04633          case SIG_FXOGS:
04634          case SIG_FXOKS:
04635             ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
04636                index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04637             p->callwaitcas = 0;
04638 
04639             if (index != SUB_REAL) {
04640                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", index, p->channel);
04641                goto winkflashdone;
04642             }
04643             
04644             if (p->subs[SUB_CALLWAIT].owner) {
04645                /* Swap to call-wait */
04646                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
04647                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04648                p->owner = p->subs[SUB_REAL].owner;
04649                ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
04650                if (p->owner->_state == AST_STATE_RINGING) {
04651                   ast_setstate(p->owner, AST_STATE_UP);
04652                   p->subs[SUB_REAL].needanswer = 1;
04653                }
04654                p->callwaitingrepeat = 0;
04655                p->cidcwexpire = 0;
04656                /* Start music on hold if appropriate */
04657                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04658                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04659                      S_OR(p->mohsuggest, NULL),
04660                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04661                }
04662                p->subs[SUB_CALLWAIT].needhold = 1;
04663                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04664                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
04665                      S_OR(p->mohsuggest, NULL),
04666                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04667                }
04668                p->subs[SUB_REAL].needunhold = 1;
04669             } else if (!p->subs[SUB_THREEWAY].owner) {
04670                if (!p->threewaycalling) {
04671                   /* Just send a flash if no 3-way calling */
04672                   p->subs[SUB_REAL].needflash = 1;
04673                   goto winkflashdone;
04674                } else if (!check_for_conference(p)) {
04675                   char cid_num[256];
04676                   char cid_name[256];
04677 
04678                   cid_num[0] = 0;
04679                   cid_name[0] = 0;
04680                   if (p->dahditrcallerid && p->owner) {
04681                      if (p->owner->cid.cid_num)
04682                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
04683                      if (p->owner->cid.cid_name)
04684                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
04685                   }
04686                   /* XXX This section needs much more error checking!!! XXX */
04687                   /* Start a 3-way call if feasible */
04688                   if (!((ast->pbx) ||
04689                         (ast->_state == AST_STATE_UP) ||
04690                         (ast->_state == AST_STATE_RING))) {
04691                      ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
04692                         goto winkflashdone;
04693                   }
04694                   if (alloc_sub(p, SUB_THREEWAY)) {
04695                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
04696                      goto winkflashdone;
04697                   }
04698                   /* Make new channel */
04699                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
04700                   if (p->dahditrcallerid) {
04701                      if (!p->origcid_num)
04702                         p->origcid_num = ast_strdup(p->cid_num);
04703                      if (!p->origcid_name)
04704                         p->origcid_name = ast_strdup(p->cid_name);
04705                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
04706                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
04707                   }
04708                   /* Swap things around between the three-way and real call */
04709                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
04710                   /* Disable echo canceller for better dialing */
04711                   dahdi_disable_ec(p);
04712                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
04713                   if (res)
04714                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
04715                   p->owner = chan;
04716                   pthread_attr_init(&attr);
04717                   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04718                   if (!chan) {
04719                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
04720                   } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
04721                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
04722                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04723                      dahdi_enable_ec(p);
04724                      ast_hangup(chan);
04725                   } else {
04726                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04727                      int way3bridge = 0, cdr3way = 0;
04728                      
04729                      if (!other) {
04730                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04731                      } else
04732                         way3bridge = 1;
04733                      
04734                      if (p->subs[SUB_THREEWAY].owner->cdr)
04735                         cdr3way = 1;
04736                      
04737                      if (option_verbose > 2) 
04738                         ast_verbose(VERBOSE_PREFIX_3 "Started three way call on channel %d\n", p->channel);
04739                      /* Start music on hold if appropriate */
04740                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04741                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04742                            S_OR(p->mohsuggest, NULL),
04743                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04744                      }
04745                      p->subs[SUB_THREEWAY].needhold = 1;
04746                   }
04747                   pthread_attr_destroy(&attr);
04748                }
04749             } else {
04750                /* Already have a 3 way call */
04751                if (p->subs[SUB_THREEWAY].inthreeway) {
04752                   /* Call is already up, drop the last person */
04753                   if (option_debug)
04754                      ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
04755                   /* If the primary call isn't answered yet, use it */
04756                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
04757                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
04758                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04759                      p->owner = p->subs[SUB_REAL].owner;
04760                   }
04761                   /* Drop the last call and stop the conference */
04762                   if (option_verbose > 2)
04763                      ast_verbose(VERBOSE_PREFIX_3 "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
04764                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04765                   p->subs[SUB_REAL].inthreeway = 0;
04766                   p->subs[SUB_THREEWAY].inthreeway = 0;
04767                } else {
04768                   /* Lets see what we're up to */
04769                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
04770                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
04771                      int otherindex = SUB_THREEWAY;
04772                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
04773                      int way3bridge = 0, cdr3way = 0;
04774                      
04775                      if (!other) {
04776                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
04777                      } else
04778                         way3bridge = 1;
04779                      
04780                      if (p->subs[SUB_THREEWAY].owner->cdr)
04781                         cdr3way = 1;
04782 
04783                      if (option_verbose > 2)
04784                         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);
04785                      /* Put them in the threeway, and flip */
04786                      p->subs[SUB_THREEWAY].inthreeway = 1;
04787                      p->subs[SUB_REAL].inthreeway = 1;
04788                      if (ast->_state == AST_STATE_UP) {
04789                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
04790                         otherindex = SUB_REAL;
04791                      }
04792                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
04793                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
04794                      p->subs[otherindex].needunhold = 1;
04795                      p->owner = p->subs[SUB_REAL].owner;
04796                      if (ast->_state == AST_STATE_RINGING) {
04797                         ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
04798                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04799                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04800                      }
04801                   } else {
04802                      if (option_verbose > 2)
04803                         ast_verbose(VERBOSE_PREFIX_3 "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
04804                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04805                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04806                      p->owner = p->subs[SUB_REAL].owner;
04807                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
04808                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04809                      p->subs[SUB_REAL].needunhold = 1;
04810                      dahdi_enable_ec(p);
04811                   }
04812                      
04813                }
04814             }
04815          winkflashdone:              
04816             update_conf(p);
04817             break;
04818          case SIG_EM:
04819          case SIG_EM_E1:
04820          case SIG_EMWINK:
04821          case SIG_FEATD:
04822          case SIG_SF:
04823          case SIG_SFWINK:
04824          case SIG_SF_FEATD:
04825          case SIG_FXSLS:
04826          case SIG_FXSGS:
04827             if (p->dialing)
04828                ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
04829             else
04830                ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
04831             break;
04832          case SIG_FEATDMF_TA:
04833             switch (p->whichwink) {
04834             case 0:
04835                ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04836                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
04837                break;
04838             case 1:
04839                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
04840                break;
04841             case 2:
04842                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
04843                return NULL;
04844             }
04845             p->whichwink++;
04846             /* Fall through */
04847          case SIG_FEATDMF:
04848          case SIG_E911:
04849          case SIG_FGC_CAMAMF:
04850          case SIG_FGC_CAMA:
04851          case SIG_FEATB:
04852          case SIG_SF_FEATDMF:
04853          case SIG_SF_FEATB:
04854             /* FGD MF *Must* wait for wink */
04855             if (!ast_strlen_zero(p->dop.dialstr)) {
04856                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04857                if (res < 0) {
04858                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04859                   p->dop.dialstr[0] = '\0';
04860                   return NULL;
04861                } else 
04862                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04863             }
04864             p->dop.dialstr[0] = '\0';
04865             break;
04866          default:
04867             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
04868          }
04869          break;
04870       case DAHDI_EVENT_HOOKCOMPLETE:
04871          if (p->inalarm) break;
04872          if ((p->radio || (p->oprmode < 0))) break;
04873          switch (mysig) {
04874          case SIG_FXSLS:  /* only interesting for FXS */
04875          case SIG_FXSGS:
04876          case SIG_FXSKS:
04877          case SIG_EM:
04878          case SIG_EM_E1:
04879          case SIG_EMWINK:
04880          case SIG_FEATD:
04881          case SIG_SF:
04882          case SIG_SFWINK:
04883          case SIG_SF_FEATD:
04884             if (!ast_strlen_zero(p->dop.dialstr)) {
04885                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04886                if (res < 0) {
04887                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04888                   p->dop.dialstr[0] = '\0';
04889                   return NULL;
04890                } else 
04891                   ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
04892             }
04893             p->dop.dialstr[0] = '\0';
04894             p->dop.op = DAHDI_DIAL_OP_REPLACE;
04895             break;
04896          case SIG_FEATDMF:
04897          case SIG_FEATDMF_TA:
04898          case SIG_E911:
04899          case SIG_FGC_CAMA:
04900          case SIG_FGC_CAMAMF:
04901          case SIG_FEATB:
04902          case SIG_SF_FEATDMF:
04903          case SIG_SF_FEATB:
04904             ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
04905             break;
04906          default:
04907             break;
04908          }
04909          break;
04910       case DAHDI_EVENT_POLARITY:
04911          /*
04912           * If we get a Polarity Switch event, check to see
04913           * if we should change the polarity state and
04914           * mark the channel as UP or if this is an indication
04915           * of remote end disconnect.
04916           */
04917          if (p->polarity == POLARITY_IDLE) {
04918             p->polarity = POLARITY_REV;
04919             if (p->answeronpolarityswitch &&
04920                 ((ast->_state == AST_STATE_DIALING) ||
04921                 (ast->_state == AST_STATE_RINGING))) {
04922                ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
04923                ast_setstate(p->owner, AST_STATE_UP);
04924                if (p->hanguponpolarityswitch) {
04925                   gettimeofday(&p->polaritydelaytv, NULL);
04926                }
04927             } else
04928                ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
04929          } 
04930          /* Removed else statement from here as it was preventing hangups from ever happening*/
04931          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
04932          if (p->hanguponpolarityswitch &&
04933             (p->polarityonanswerdelay > 0) &&
04934                 (p->polarity == POLARITY_REV) &&
04935             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
04936                                 /* Added log_debug information below to provide a better indication of what is going on */
04937             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) );
04938          
04939             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
04940                ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
04941                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
04942                p->polarity = POLARITY_IDLE;
04943             } else {
04944                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);
04945             }
04946          } else {
04947             p->polarity = POLARITY_IDLE;
04948             ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
04949          }
04950                         /* Added more log_debug information below to provide a better indication of what is going on */
04951          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) );
04952          break;
04953       default:
04954          ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
04955    }
04956    return &p->subs[index].f;
04957 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 2815 of file chan_dahdi.c.

References ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_dsp_digitmode(), ast_dsp_free(), ast_log(), ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verbose(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, free, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mohsuggest, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, option_debug, option_verbose, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::prev, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::progress, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::realcall, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, S_OR, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), update_conf(), and VERBOSE_PREFIX_3.

Referenced by pri_dchannel().

02816 {
02817    int res;
02818    int index,x, law;
02819    /*static int restore_gains(struct dahdi_pvt *p);*/
02820    struct dahdi_pvt *p = ast->tech_pvt;
02821    struct dahdi_pvt *tmp = NULL;
02822    struct dahdi_pvt *prev = NULL;
02823    struct dahdi_params par;
02824 
02825    if (option_debug)
02826       ast_log(LOG_DEBUG, "dahdi_hangup(%s)\n", ast->name);
02827    if (!ast->tech_pvt) {
02828       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
02829       return 0;
02830    }
02831    
02832    ast_mutex_lock(&p->lock);
02833    
02834    index = dahdi_get_index(ast, p, 1);
02835 
02836    if (p->sig == SIG_PRI) {
02837       x = 1;
02838       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
02839    }
02840 
02841    x = 0;
02842    dahdi_confmute(p, 0);
02843    restore_gains(p);
02844    if (p->origcid_num) {
02845       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
02846       free(p->origcid_num);
02847       p->origcid_num = NULL;
02848    }  
02849    if (p->origcid_name) {
02850       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
02851       free(p->origcid_name);
02852       p->origcid_name = NULL;
02853    }  
02854    if (p->dsp)
02855       ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
02856    p->exten[0] = '\0';
02857 
02858    if (option_debug)
02859       ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
02860       p->channel, index, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
02861    p->ignoredtmf = 0;
02862    
02863    if (index > -1) {
02864       /* Real channel, do some fixup */
02865       p->subs[index].owner = NULL;
02866       p->subs[index].needanswer = 0;
02867       p->subs[index].needflash = 0;
02868       p->subs[index].needringing = 0;
02869       p->subs[index].needbusy = 0;
02870       p->subs[index].needcongestion = 0;
02871       p->subs[index].linear = 0;
02872       p->subs[index].needcallerid = 0;
02873       p->polarity = POLARITY_IDLE;
02874       dahdi_setlinear(p->subs[index].dfd, 0);
02875       if (index == SUB_REAL) {
02876          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
02877             ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
02878             if (p->subs[SUB_CALLWAIT].inthreeway) {
02879                /* We had flipped over to answer a callwait and now it's gone */
02880                ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
02881                /* Move to the call-wait, but un-own us until they flip back. */
02882                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02883                unalloc_sub(p, SUB_CALLWAIT);
02884                p->owner = NULL;
02885             } else {
02886                /* The three way hung up, but we still have a call wait */
02887                ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
02888                swap_subs(p, SUB_THREEWAY, SUB_REAL);
02889                unalloc_sub(p, SUB_THREEWAY);
02890                if (p->subs[SUB_REAL].inthreeway) {
02891                   /* This was part of a three way call.  Immediately make way for
02892                      another call */
02893                   ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02894                   p->owner = p->subs[SUB_REAL].owner;
02895                } else {
02896                   /* This call hasn't been completed yet...  Set owner to NULL */
02897                   ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02898                   p->owner = NULL;
02899                }
02900                p->subs[SUB_REAL].inthreeway = 0;
02901             }
02902          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
02903             /* Move to the call-wait and switch back to them. */
02904             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
02905             unalloc_sub(p, SUB_CALLWAIT);
02906             p->owner = p->subs[SUB_REAL].owner;
02907             if (p->owner->_state != AST_STATE_UP)
02908                p->subs[SUB_REAL].needanswer = 1;
02909             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
02910                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
02911          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
02912             swap_subs(p, SUB_THREEWAY, SUB_REAL);
02913             unalloc_sub(p, SUB_THREEWAY);
02914             if (p->subs[SUB_REAL].inthreeway) {
02915                /* This was part of a three way call.  Immediately make way for
02916                   another call */
02917                ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
02918                p->owner = p->subs[SUB_REAL].owner;
02919             } else {
02920                /* This call hasn't been completed yet...  Set owner to NULL */
02921                ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
02922                p->owner = NULL;
02923             }
02924             p->subs[SUB_REAL].inthreeway = 0;
02925          }
02926       } else if (index == SUB_CALLWAIT) {
02927          /* Ditch the holding callwait call, and immediately make it availabe */
02928          if (p->subs[SUB_CALLWAIT].inthreeway) {
02929             /* This is actually part of a three way, placed on hold.  Place the third part
02930                on music on hold now */
02931             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
02932                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
02933                   S_OR(p->mohsuggest, NULL),
02934                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02935             }
02936             p->subs[SUB_THREEWAY].inthreeway = 0;
02937             /* Make it the call wait now */
02938             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
02939             unalloc_sub(p, SUB_THREEWAY);
02940          } else
02941             unalloc_sub(p, SUB_CALLWAIT);
02942       } else if (index == SUB_THREEWAY) {
02943          if (p->subs[SUB_CALLWAIT].inthreeway) {
02944             /* The other party of the three way call is currently in a call-wait state.
02945                Start music on hold for them, and take the main guy out of the third call */
02946             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
02947                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
02948                   S_OR(p->mohsuggest, NULL),
02949                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
02950             }
02951             p->subs[SUB_CALLWAIT].inthreeway = 0;
02952          }
02953          p->subs[SUB_REAL].inthreeway = 0;
02954          /* If this was part of a three way call index, let us make
02955             another three way call */
02956          unalloc_sub(p, SUB_THREEWAY);
02957       } else {
02958          /* This wasn't any sort of call, but how are we an index? */
02959          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
02960       }
02961    }
02962 
02963    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
02964       p->owner = NULL;
02965       p->ringt = 0;
02966       p->distinctivering = 0;
02967       p->confirmanswer = 0;
02968       p->cidrings = 1;
02969       p->outgoing = 0;
02970       p->digital = 0;
02971       p->faxhandled = 0;
02972       p->pulsedial = 0;
02973       p->onhooktime = time(NULL);
02974 #ifdef HAVE_PRI
02975       p->proceeding = 0;
02976       p->dialing = 0;
02977       p->progress = 0;
02978       p->alerting = 0;
02979       p->setup_ack = 0;
02980 #endif      
02981       if (p->dsp) {
02982          ast_dsp_free(p->dsp);
02983          p->dsp = NULL;
02984       }
02985 
02986       law = DAHDI_LAW_DEFAULT;
02987       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
02988       if (res < 0) 
02989          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
02990       /* Perform low level hangup if no owner left */
02991 #ifdef HAVE_PRI
02992       if (p->pri) {
02993 #ifdef SUPPORT_USERUSER
02994          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
02995 #endif
02996 
02997          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
02998          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
02999             if (!pri_grab(p, p->pri)) {
03000                if (p->alreadyhungup) {
03001                   ast_log(LOG_DEBUG, "Already hungup...  Calling hangup once, and clearing call\n");
03002 
03003 #ifdef SUPPORT_USERUSER
03004                   pri_call_set_useruser(p->call, useruser);
03005 #endif
03006 
03007                   pri_hangup(p->pri->pri, p->call, -1);
03008                   p->call = NULL;
03009                   if (p->bearer) 
03010                      p->bearer->call = NULL;
03011                } else {
03012                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03013                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03014                   ast_log(LOG_DEBUG, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03015 
03016 #ifdef SUPPORT_USERUSER
03017                   pri_call_set_useruser(p->call, useruser);
03018 #endif
03019 
03020                   p->alreadyhungup = 1;
03021                   if (p->bearer)
03022                      p->bearer->alreadyhungup = 1;
03023                   if (cause) {
03024                      if (atoi(cause))
03025                         icause = atoi(cause);
03026                   }
03027                   pri_hangup(p->pri->pri, p->call, icause);
03028                }
03029                if (res < 0) 
03030                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03031                pri_rel(p->pri);        
03032             } else {
03033                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03034                res = -1;
03035             }
03036          } else {
03037             if (p->bearer)
03038                ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03039             p->call = NULL;
03040             res = 0;
03041          }
03042       }
03043 #endif
03044       if (p->sig && (p->sig != SIG_PRI))
03045          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03046       if (res < 0) {
03047          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03048       }
03049       switch (p->sig) {
03050       case SIG_FXOGS:
03051       case SIG_FXOLS:
03052       case SIG_FXOKS:
03053          memset(&par, 0, sizeof(par));
03054          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03055          if (!res) {
03056 #if 0
03057             ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03058 #endif
03059             /* If they're off hook, try playing congestion */
03060             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03061                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03062             else
03063                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03064          }
03065          break;
03066       case SIG_FXSGS:
03067       case SIG_FXSLS:
03068       case SIG_FXSKS:
03069          /* Make sure we're not made available for at least two seconds assuming
03070             we were actually used for an inbound or outbound call. */
03071          if (ast->_state != AST_STATE_RESERVED) {
03072             time(&p->guardtime);
03073             p->guardtime += 2;
03074          }
03075          break;
03076       default:
03077          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03078       }
03079       if (p->cidspill)
03080          free(p->cidspill);
03081       if (p->sig)
03082          dahdi_disable_ec(p);
03083       x = 0;
03084       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03085       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03086       p->didtdd = 0;
03087       p->cidspill = NULL;
03088       p->callwaitcas = 0;
03089       p->callwaiting = p->permcallwaiting;
03090       p->hidecallerid = p->permhidecallerid;
03091       p->dialing = 0;
03092       p->rdnis[0] = '\0';
03093       update_conf(p);
03094       reset_conf(p);
03095       /* Restore data mode */
03096       if (p->sig == SIG_PRI) {
03097          x = 0;
03098          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03099       }
03100 #ifdef HAVE_PRI
03101       if (p->bearer) {
03102          ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
03103          /* Free up the bearer channel as well, and
03104             don't use its file descriptor anymore */
03105          update_conf(p->bearer);
03106          reset_conf(p->bearer);
03107          p->bearer->owner = NULL;
03108          p->bearer->realcall = NULL;
03109          p->bearer = NULL;
03110          p->subs[SUB_REAL].dfd = -1;
03111          p->pri = NULL;
03112       }
03113 #endif
03114       if (num_restart_pending == 0)
03115          restart_monitor();
03116    }
03117 
03118    p->callwaitingrepeat = 0;
03119    p->cidcwexpire = 0;
03120    p->oprmode = 0;
03121    ast->tech_pvt = NULL;
03122    ast_mutex_unlock(&p->lock);
03123    ast_module_unref(ast_module_info->self);
03124    if (option_verbose > 2) 
03125       ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
03126 
03127    ast_mutex_lock(&iflock);
03128 
03129    if (p->restartpending) {
03130       num_restart_pending--;
03131    }
03132 
03133    tmp = iflist;
03134    prev = NULL;
03135    if (p->destroy) {
03136       while (tmp) {
03137          if (tmp == p) {
03138             destroy_channel(prev, tmp, 0);
03139             break;
03140          } else {
03141             prev = tmp;
03142             tmp = tmp->next;
03143          }
03144       }
03145    }
03146    ast_mutex_unlock(&iflock);
03147    return 0;
03148 }

static int dahdi_indicate ( struct ast_channel chan,
int  condition,
const void *  data,
size_t  datalen 
) [static]

Definition at line 5474 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, AST_CAUSE_CONGESTION, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_SOFTHANGUP_DEV, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, dahdi_pvt::call, dahdi_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, LOG_DEBUG, dahdi_pvt::mohinterpret, ast_channel::name, option_debug, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::sig, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

05475 {
05476    struct dahdi_pvt *p = chan->tech_pvt;
05477    int res=-1;
05478    int index;
05479    int func = DAHDI_FLASH;
05480    ast_mutex_lock(&p->lock);
05481    index = dahdi_get_index(chan, p, 0);
05482    if (option_debug)
05483       ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
05484    if (index == SUB_REAL) {
05485       switch (condition) {
05486       case AST_CONTROL_BUSY:
05487 #ifdef HAVE_PRI
05488          if (p->priindication_oob && p->sig == SIG_PRI) {
05489             chan->hangupcause = AST_CAUSE_USER_BUSY;
05490             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05491             res = 0;
05492          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05493             if (p->pri->pri) {      
05494                if (!pri_grab(p, p->pri)) {
05495                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05496                   pri_rel(p->pri);
05497                }
05498                else
05499                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05500             }
05501             p->progress = 1;
05502             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05503          } else
05504 #endif
05505             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_BUSY);
05506          break;
05507       case AST_CONTROL_RINGING:
05508 #ifdef HAVE_PRI
05509          if ((!p->alerting) && p->sig==SIG_PRI && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
05510             if (p->pri->pri) {      
05511                if (!pri_grab(p, p->pri)) {
05512                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05513                   pri_rel(p->pri);
05514                }
05515                else
05516                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05517             }
05518             p->alerting = 1;
05519          }
05520 #endif
05521          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_RINGTONE);
05522          if (chan->_state != AST_STATE_UP) {
05523             if ((chan->_state != AST_STATE_RING) ||
05524                ((p->sig != SIG_FXSKS) &&
05525                 (p->sig != SIG_FXSLS) &&
05526                 (p->sig != SIG_FXSGS)))
05527                ast_setstate(chan, AST_STATE_RINGING);
05528          }
05529          break;
05530       case AST_CONTROL_PROCEEDING:
05531          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
05532 #ifdef HAVE_PRI
05533          if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05534             if (p->pri->pri) {      
05535                if (!pri_grab(p, p->pri)) {
05536                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05537                   pri_rel(p->pri);
05538                }
05539                else
05540                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05541             }
05542             p->proceeding = 1;
05543             p->dialing = 0;
05544          }
05545 #endif
05546          /* don't continue in ast_indicate */
05547          res = 0;
05548          break;
05549       case AST_CONTROL_PROGRESS:
05550          ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
05551 #ifdef HAVE_PRI
05552          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
05553          if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05554             if (p->pri->pri) {      
05555                if (!pri_grab(p, p->pri)) {
05556                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05557                   pri_rel(p->pri);
05558                }
05559                else
05560                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05561             }
05562             p->progress = 1;
05563          }
05564 #endif
05565          /* don't continue in ast_indicate */
05566          res = 0;
05567          break;
05568       case AST_CONTROL_CONGESTION:
05569          chan->hangupcause = AST_CAUSE_CONGESTION;
05570 #ifdef HAVE_PRI
05571          if (p->priindication_oob && p->sig == SIG_PRI) {
05572             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
05573             chan->_softhangup |= AST_SOFTHANGUP_DEV;
05574             res = 0;
05575          } else if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05576             if (p->pri) {     
05577                if (!pri_grab(p, p->pri)) {
05578                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
05579                   pri_rel(p->pri);
05580                } else
05581                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05582             }
05583             p->progress = 1;
05584             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05585          } else
05586 #endif
05587             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
05588          break;
05589       case AST_CONTROL_HOLD:
05590 #ifdef HAVE_PRI
05591          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05592             if (!pri_grab(p, p->pri)) {
05593                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
05594                pri_rel(p->pri);
05595             } else
05596                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05597          } else
05598 #endif
05599             ast_moh_start(chan, data, p->mohinterpret);
05600          break;
05601       case AST_CONTROL_UNHOLD:
05602 #ifdef HAVE_PRI
05603          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
05604             if (!pri_grab(p, p->pri)) {
05605                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
05606                pri_rel(p->pri);
05607             } else
05608                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
05609          } else
05610 #endif
05611             ast_moh_stop(chan);
05612          break;
05613       case AST_CONTROL_RADIO_KEY:
05614          if (p->radio) 
05615              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
05616          res = 0;
05617          break;
05618       case AST_CONTROL_RADIO_UNKEY:
05619          if (p->radio)
05620              res =  dahdi_set_hook(p->subs[index].dfd, DAHDI_RINGOFF);
05621          res = 0;
05622          break;
05623       case AST_CONTROL_FLASH:
05624          /* flash hookswitch */
05625          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
05626             /* Clear out the dial buffer */
05627             p->dop.dialstr[0] = '\0';
05628             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
05629                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
05630                   chan->name, strerror(errno));
05631             } else
05632                res = 0;
05633          } else
05634             res = 0;
05635          break;
05636       case AST_CONTROL_SRCUPDATE:
05637          res = 0;
05638          break;
05639       case -1:
05640          res = tone_zone_play_tone(p->subs[index].dfd, -1);
05641          break;
05642       }
05643    } else
05644       res = 0;
05645    ast_mutex_unlock(&p->lock);
05646    return res;
05647 }

static void dahdi_link ( struct dahdi_pvt slave,
struct dahdi_pvt master 
) [static]

Definition at line 3497 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

03497                                                                           {
03498    int x;
03499    if (!slave || !master) {
03500       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
03501       return;
03502    }
03503    for (x = 0; x < MAX_SLAVES; x++) {
03504       if (!master->slaves[x]) {
03505          master->slaves[x] = slave;
03506          break;
03507       }
03508    }
03509    if (x >= MAX_SLAVES) {
03510       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
03511       master->slaves[MAX_SLAVES - 1] = slave;
03512    }
03513    if (slave->master) 
03514       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
03515    slave->master = master;
03516    
03517    ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
03518 }

static struct ast_channel * dahdi_new ( struct dahdi_pvt ,
int  ,
int  ,
int  ,
int  ,
int   
) [static]

Definition at line 5649 of file chan_dahdi.c.

References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc(), ast_copy_string(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_safe_string_alloc(), AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call_forward, dahdi_pvt::callgroup, ast_channel::callgroup, dahdi_pvt::callingpres, dahdi_pvt::callprogress, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, dahdi_pvt::cid_name, dahdi_pvt::cid_num, ast_callerid::cid_pres, ast_callerid::cid_rdnis, dahdi_pvt::cid_ton, ast_callerid::cid_ton, ast_channel::context, dahdi_pvt::context, dahdi_chan_name, dahdi_chan_name_len, dahdi_confmute(), dahdi_setlinear(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, ast_channel::fds, free, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_DEBUG, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, PRI_TRANS_CAP_DIGITAL, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, dahdi_pvt::silencethreshold, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, and ast_channel::writeformat.

Referenced by dahdi_handle_event(), dahdi_request(), handle_init_event(), and register_translator().

05650 {
05651    struct ast_channel *tmp;
05652    int deflaw;
05653    int res;
05654    int x,y;
05655    int features;
05656    char *b2 = NULL;
05657    struct dahdi_params ps;
05658    char chanprefix[*dahdi_chan_name_len + 4];
05659 
05660    if (i->subs[index].owner) {
05661       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
05662       return NULL;
05663    }
05664    y = 1;
05665    do {
05666       if (b2)
05667          free(b2);
05668 #ifdef HAVE_PRI
05669       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
05670          b2 = ast_safe_string_alloc("%d:%d-%d", i->pri->trunkgroup, i->channel, y);
05671       else
05672 #endif
05673       if (i->channel == CHAN_PSEUDO)
05674          b2 = ast_safe_string_alloc("pseudo-%ld", ast_random());
05675       else  
05676          b2 = ast_safe_string_alloc("%d-%d", i->channel, y);
05677       for (x = 0; x < 3; x++) {
05678          if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name + (!strncmp(i->subs[x].owner->name, "Zap", 3) ? 4 : 6)))
05679             break;
05680       }
05681       y++;
05682    } while (x < 3);
05683    strcpy(chanprefix, dahdi_chan_name);
05684    strcat(chanprefix, "/%s");
05685    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, chanprefix, b2);
05686    if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
05687       free(b2);
05688    if (!tmp)
05689       return NULL;
05690    tmp->tech = chan_tech;
05691    memset(&ps, 0, sizeof(ps));
05692    ps.channo = i->channel;
05693    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
05694    if (res) {
05695       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
05696       ps.curlaw = DAHDI_LAW_MULAW;
05697    }
05698    if (ps.curlaw == DAHDI_LAW_ALAW)
05699       deflaw = AST_FORMAT_ALAW;
05700    else
05701       deflaw = AST_FORMAT_ULAW;
05702    if (law) {
05703       if (law == DAHDI_LAW_ALAW)
05704          deflaw = AST_FORMAT_ALAW;
05705       else
05706          deflaw = AST_FORMAT_ULAW;
05707    }
05708    tmp->fds[0] = i->subs[index].dfd;
05709    tmp->nativeformats = deflaw;
05710    /* Start out assuming ulaw since it's smaller :) */
05711    tmp->rawreadformat = deflaw;
05712    tmp->readformat = deflaw;
05713    tmp->rawwriteformat = deflaw;
05714    tmp->writeformat = deflaw;
05715    i->subs[index].linear = 0;
05716    dahdi_setlinear(i->subs[index].dfd, i->subs[index].linear);
05717    features = 0;
05718    if (index == SUB_REAL) {
05719       if (i->busydetect && CANBUSYDETECT(i))
05720          features |= DSP_FEATURE_BUSY_DETECT;
05721       if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
05722          features |= DSP_FEATURE_CALL_PROGRESS;
05723       if ((!i->outgoing && (i->callprogress & 4)) || 
05724           (i->outgoing && (i->callprogress & 2))) {
05725          features |= DSP_FEATURE_FAX_DETECT;
05726       }
05727 #ifdef DAHDI_TONEDETECT
05728       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05729       if (ioctl(i->subs[index].dfd, DAHDI_TONEDETECT, &x)) {
05730 #endif      
05731          i->hardwaredtmf = 0;
05732          features |= DSP_FEATURE_DTMF_DETECT;
05733 #ifdef DAHDI_TONEDETECT
05734       } else if (NEED_MFDETECT(i)) {
05735          i->hardwaredtmf = 1;
05736          features |= DSP_FEATURE_DTMF_DETECT;
05737       }
05738 #endif
05739    }
05740    if (features) {
05741       if (i->dsp) {
05742          ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
05743       } else {
05744          if (i->channel != CHAN_PSEUDO)
05745             i->dsp = ast_dsp_new();
05746          else
05747             i->dsp = NULL;
05748          if (i->dsp) {
05749             i->dsp_features = features;
05750 #ifdef HAVE_PRI
05751             /* We cannot do progress detection until receives PROGRESS message */
05752             if (i->outgoing && (i->sig == SIG_PRI)) {
05753                /* Remember requested DSP features, don't treat
05754                   talking as ANSWER */
05755                i->dsp_features = features & ~DSP_PROGRESS_TALK;
05756                features = 0;
05757             }
05758 #endif
05759             ast_dsp_set_features(i->dsp, features);
05760             ast_dsp_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
05761             if (!ast_strlen_zero(progzone))
05762                ast_dsp_set_call_progress_zone(i->dsp, progzone);
05763             if (i->busydetect && CANBUSYDETECT(i)) {
05764                if(i->silencethreshold > 0)
05765                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
05766                ast_dsp_set_busy_count(i->dsp, i->busycount);
05767                if(i->busytonelength > 0)
05768                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
05769                if((i->busytonelength == i->busyquietlength) && i->busycompare)
05770                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
05771             }
05772          }
05773       }
05774    }
05775       
05776    if (state == AST_STATE_RING)
05777       tmp->rings = 1;
05778    tmp->tech_pvt = i;
05779    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
05780       /* Only FXO signalled stuff can be picked up */
05781       tmp->callgroup = i->callgroup;
05782       tmp->pickupgroup = i->pickupgroup;
05783    }
05784    if (!ast_strlen_zero(i->language))
05785       ast_string_field_set(tmp, language, i->language);
05786    if (!i->owner)
05787       i->owner = tmp;
05788    if (!ast_strlen_zero(i->accountcode))
05789       ast_string_field_set(tmp, accountcode, i->accountcode);
05790    if (i->amaflags)
05791       tmp->amaflags = i->amaflags;
05792    i->subs[index].owner = tmp;
05793    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
05794    ast_string_field_set(tmp, call_forward, i->call_forward);
05795    /* If we've been told "no ADSI" then enforce it */
05796    if (!i->adsi)
05797       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
05798    if (!ast_strlen_zero(i->exten))
05799       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
05800    if (!ast_strlen_zero(i->rdnis))
05801       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
05802    if (!ast_strlen_zero(i->dnid))
05803       tmp->cid.cid_dnid = ast_strdup(i->dnid);
05804 
05805    /* Don't use ast_set_callerid() here because it will
05806     * generate a needless NewCallerID event */
05807 #ifdef PRI_ANI
05808    if (!ast_strlen_zero(i->cid_ani))
05809       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
05810    else  
05811       tmp->cid.cid_ani = ast_strdup(i->cid_num);
05812 #else
05813    tmp->cid.cid_ani = ast_strdup(i->cid_num);
05814 #endif
05815    tmp->cid.cid_pres = i->callingpres;
05816    tmp->cid.cid_ton = i->cid_ton;
05817 #ifdef HAVE_PRI
05818    tmp->transfercapability = transfercapability;
05819    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
05820    if (transfercapability & PRI_TRANS_CAP_DIGITAL)
05821       i->digital = 1;
05822    /* Assume calls are not idle calls unless we're told differently */
05823    i->isidlecall = 0;
05824    i->alreadyhungup = 0;
05825 #endif
05826    /* clear the fake event in case we posted one before we had ast_channel */
05827    i->fake_event = 0;
05828    /* Assure there is no confmute on this channel */
05829    dahdi_confmute(i, 0);
05830    /* Configure the new channel jb */
05831    ast_jb_configure(tmp, &global_jbconf);
05832    if (startpbx) {
05833       if (ast_pbx_start(tmp)) {
05834          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
05835          ast_hangup(tmp);
05836          i->owner = NULL;
05837          return NULL;
05838       }
05839    }
05840 
05841    ast_module_ref(ast_module_info->self);
05842    
05843    return tmp;
05844 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1221 of file chan_dahdi.c.

References ast_log(), DAHDI_FILE_CHANNEL, errno, LOG_WARNING, and READ_SIZE.

Referenced by alloc_sub(), chandup(), and mkintf().

01222 {
01223    int fd;
01224    int isnum;
01225    int chan = 0;
01226    int bs;
01227    int x;
01228    isnum = 1;
01229    for (x = 0; x < strlen(fn); x++) {
01230       if (!isdigit(fn[x])) {
01231          isnum = 0;
01232          break;
01233       }
01234    }
01235    if (isnum) {
01236       chan = atoi(fn);
01237       if (chan < 1) {
01238          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01239          return -1;
01240       }
01241       fn = DAHDI_FILE_CHANNEL;
01242    }
01243    fd = open(fn, O_RDWR | O_NONBLOCK);
01244    if (fd < 0) {
01245       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01246       return -1;
01247    }
01248    if (chan) {
01249       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01250          x = errno;
01251          close(fd);
01252          errno = x;
01253          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01254          return -1;
01255       }
01256    }
01257    bs = READ_SIZE;
01258    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01259       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01260       x = errno;
01261       close(fd);
01262       errno = x;
01263       return -1;
01264    }
01265    return fd;
01266 }

static void dahdi_pri_error ( struct pri *  pri,
char *  s 
) [static]

Definition at line 8744 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.

Referenced by dahdi_restart(), and load_module().

08745 {
08746    int x, y;
08747    int dchan = -1, span = -1;
08748    int dchancount = 0;
08749 
08750    if (pri) {
08751       for (x = 0; x < NUM_SPANS; x++) {
08752          for (y = 0; y < NUM_DCHANS; y++) {
08753             if (pris[x].dchans[y])
08754                dchancount++;
08755 
08756             if (pris[x].dchans[y] == pri)
08757                dchan = y;
08758          }
08759          if (dchan >= 0) {
08760             span = x;
08761             break;
08762          }
08763          dchancount = 0;
08764       }
08765       if ((dchan >= 0) && (span >= 0)) {
08766          if (dchancount > 1)
08767             ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
08768          else
08769             ast_log(LOG_ERROR, "%s", s);
08770       } else
08771          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08772    } else
08773       ast_log(LOG_ERROR, "%s", s);
08774 
08775    ast_mutex_lock(&pridebugfdlock);
08776 
08777    if (pridebugfd >= 0) {
08778       if (write(pridebugfd, s, strlen(s)) < 0) {
08779          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08780       }
08781    }
08782 
08783    ast_mutex_unlock(&pridebugfdlock);
08784 }

static void dahdi_pri_message ( struct pri *  pri,
char *  s 
) [static]

Definition at line 8702 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verbose(), errno, LOG_ERROR, NUM_DCHANS, NUM_SPANS, pridebugfdlock, and pris.

Referenced by dahdi_restart(), and load_module().

08703 {
08704    int x, y;
08705    int dchan = -1, span = -1;
08706    int dchancount = 0;
08707 
08708    if (pri) {
08709       for (x = 0; x < NUM_SPANS; x++) {
08710          for (y = 0; y < NUM_DCHANS; y++) {
08711             if (pris[x].dchans[y])
08712                dchancount++;
08713 
08714             if (pris[x].dchans[y] == pri)
08715                dchan = y;
08716          }
08717          if (dchan >= 0) {
08718             span = x;
08719             break;
08720          }
08721          dchancount = 0;
08722       }
08723       if ((dchan >= 0) && (span >= 0)) {
08724          if (dchancount > 1)
08725             ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
08726          else
08727             ast_verbose("%s", s);
08728       } else
08729          ast_log(LOG_ERROR, "PRI debug error: could not find pri associated it with debug message output\n");
08730    } else
08731       ast_verbose("%s", s);
08732 
08733    ast_mutex_lock(&pridebugfdlock);
08734 
08735    if (pridebugfd >= 0) {
08736       if (write(pridebugfd, s, strlen(s)) < 0) {
08737          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
08738       }
08739    }
08740 
08741    ast_mutex_unlock(&pridebugfdlock);
08742 }

static void dahdi_queue_frame ( struct dahdi_pvt p,
struct ast_frame f,
struct dahdi_pri pri 
) [static]

Definition at line 1163 of file chan_dahdi.c.

References ast_mutex_trylock, ast_mutex_unlock, ast_queue_frame(), DEADLOCK_AVOIDANCE, and f.

Referenced by __action_dialoffhook().

01167 {
01168    /* We must unlock the PRI to avoid the possibility of a deadlock */
01169 #ifdef HAVE_PRI
01170    if (pri)
01171       ast_mutex_unlock(&pri->lock);
01172 #endif      
01173    for (;;) {
01174       if (p->owner) {
01175          if (ast_mutex_trylock(&p->owner->lock)) {
01176             DEADLOCK_AVOIDANCE(&p->lock);
01177          } else {
01178             ast_queue_frame(p->owner, f);
01179             ast_mutex_unlock(&p->owner->lock);
01180             break;
01181          }
01182       } else
01183          break;
01184    }
01185 #ifdef HAVE_PRI
01186    if (pri)
01187       ast_mutex_lock(&pri->lock);
01188 #endif      
01189 }

static struct ast_frame * dahdi_read ( struct ast_channel ast  )  [static]

Definition at line 5077 of file chan_dahdi.c.

References __dahdi_exception(), ast_channel::_state, ast_clear_flag, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HOLD, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_dsp_process(), AST_FLAG_BLOCKING, AST_FLAG_EXCEPTION, AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_TEXT, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_getformatname(), ast_log(), ast_mutex_trylock, ast_mutex_unlock, ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_verbose(), dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, DEADLOCK_AVOIDANCE, ast_frame::delivery, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, errno, dahdi_subchannel::f, f, dahdi_pvt::fake_event, dahdi_pvt::firstradio, ast_frame::frametype, dahdi_pvt::ignoredtmf, dahdi_pvt::inalarm, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_subchannel::linear, ast_channel::lock, dahdi_pvt::lock, LOG_DEBUG, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, option_verbose, dahdi_pvt::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::proceeding, dahdi_pvt::pulsedial, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

05078 {
05079    struct dahdi_pvt *p = ast->tech_pvt;
05080    int res;
05081    int index;
05082    void *readbuf;
05083    struct ast_frame *f;
05084 
05085    while (ast_mutex_trylock(&p->lock)) {
05086       DEADLOCK_AVOIDANCE(&ast->lock);
05087    }
05088 
05089    index = dahdi_get_index(ast, p, 0);
05090    
05091    /* Hang up if we don't really exist */
05092    if (index < 0) {
05093       ast_log(LOG_WARNING, "We dont exist?\n");
05094       ast_mutex_unlock(&p->lock);
05095       return NULL;
05096    }
05097    
05098    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05099 
05100    p->subs[index].f.frametype = AST_FRAME_NULL;
05101    p->subs[index].f.datalen = 0;
05102    p->subs[index].f.samples = 0;
05103    p->subs[index].f.mallocd = 0;
05104    p->subs[index].f.offset = 0;
05105    p->subs[index].f.subclass = 0;
05106    p->subs[index].f.delivery = ast_tv(0,0);
05107    p->subs[index].f.src = "dahdi_read";
05108    p->subs[index].f.data = NULL;
05109    
05110    /* make sure it sends initial key state as first frame */
05111    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05112    {
05113       struct dahdi_params ps;
05114 
05115       memset(&ps, 0, sizeof(ps));
05116       ps.channo = p->channel;
05117       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05118          ast_mutex_unlock(&p->lock);
05119          return NULL;
05120       }
05121       p->firstradio = 1;
05122       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05123       if (ps.rxisoffhook)
05124       {
05125          p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
05126       }
05127       else
05128       {
05129          p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
05130       }
05131       ast_mutex_unlock(&p->lock);
05132       return &p->subs[index].f;
05133    }
05134    if (p->ringt == 1) {
05135       ast_mutex_unlock(&p->lock);
05136       return NULL;
05137    }
05138    else if (p->ringt > 0) 
05139       p->ringt--;
05140 
05141    if (p->subs[index].needringing) {
05142       /* Send ringing frame if requested */
05143       p->subs[index].needringing = 0;
05144       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05145       p->subs[index].f.subclass = AST_CONTROL_RINGING;
05146       ast_setstate(ast, AST_STATE_RINGING);
05147       ast_mutex_unlock(&p->lock);
05148       return &p->subs[index].f;
05149    }
05150 
05151    if (p->subs[index].needbusy) {
05152       /* Send busy frame if requested */
05153       p->subs[index].needbusy = 0;
05154       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05155       p->subs[index].f.subclass = AST_CONTROL_BUSY;
05156       ast_mutex_unlock(&p->lock);
05157       return &p->subs[index].f;
05158    }
05159 
05160    if (p->subs[index].needcongestion) {
05161       /* Send congestion frame if requested */
05162       p->subs[index].needcongestion = 0;
05163       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05164       p->subs[index].f.subclass = AST_CONTROL_CONGESTION;
05165       ast_mutex_unlock(&p->lock);
05166       return &p->subs[index].f;
05167    }
05168 
05169    if (p->subs[index].needcallerid) {
05170       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05171                      S_OR(p->lastcid_name, NULL),
05172                      S_OR(p->lastcid_num, NULL)
05173                      );
05174       p->subs[index].needcallerid = 0;
05175    }
05176    
05177    if (p->subs[index].needanswer) {
05178       /* Send answer frame if requested */
05179       p->subs[index].needanswer = 0;
05180       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05181       p->subs[index].f.subclass = AST_CONTROL_ANSWER;
05182       ast_mutex_unlock(&p->lock);
05183       return &p->subs[index].f;
05184    }  
05185    
05186    if (p->subs[index].needflash) {
05187       /* Send answer frame if requested */
05188       p->subs[index].needflash = 0;
05189       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05190       p->subs[index].f.subclass = AST_CONTROL_FLASH;
05191       ast_mutex_unlock(&p->lock);
05192       return &p->subs[index].f;
05193    }  
05194    
05195    if (p->subs[index].needhold) {
05196       /* Send answer frame if requested */
05197       p->subs[index].needhold = 0;
05198       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05199       p->subs[index].f.subclass = AST_CONTROL_HOLD;
05200       ast_mutex_unlock(&p->lock);
05201       ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
05202       return &p->subs[index].f;
05203    }  
05204    
05205    if (p->subs[index].needunhold) {
05206       /* Send answer frame if requested */
05207       p->subs[index].needunhold = 0;
05208       p->subs[index].f.frametype = AST_FRAME_CONTROL;
05209       p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
05210       ast_mutex_unlock(&p->lock);
05211       ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
05212       return &p->subs[index].f;
05213    }  
05214    
05215    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05216       if (!p->subs[index].linear) {
05217          p->subs[index].linear = 1;
05218          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05219          if (res) 
05220             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, index);
05221       }
05222    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05223          (ast->rawreadformat == AST_FORMAT_ALAW)) {
05224       if (p->subs[index].linear) {
05225          p->subs[index].linear = 0;
05226          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05227          if (res) 
05228             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, index);
05229       }
05230    } else {
05231       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05232       ast_mutex_unlock(&p->lock);
05233       return NULL;
05234    }
05235    readbuf = ((unsigned char *)p->subs[index].buffer) + AST_FRIENDLY_OFFSET;
05236    CHECK_BLOCKING(ast);
05237    res = read(p->subs[index].dfd, readbuf, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05238    ast_clear_flag(ast, AST_FLAG_BLOCKING);
05239    /* Check for hangup */
05240    if (res < 0) {
05241       f = NULL;
05242       if (res == -1)  {
05243          if (errno == EAGAIN) {
05244             /* Return "NULL" frame if there is nobody there */
05245             ast_mutex_unlock(&p->lock);
05246             return &p->subs[index].f;
05247          } else if (errno == ELAST) {
05248             f = __dahdi_exception(ast);
05249          } else
05250             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05251       }
05252       ast_mutex_unlock(&p->lock);
05253       return f;
05254    }
05255    if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
05256       ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
05257       f = __dahdi_exception(ast);
05258       ast_mutex_unlock(&p->lock);
05259       return f;
05260    }
05261    if (p->tdd) { /* if in TDD mode, see if we receive that */
05262       int c;
05263 
05264       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05265       if (c < 0) {
05266          ast_log(LOG_DEBUG,"tdd_feed failed\n");
05267          ast_mutex_unlock(&p->lock);
05268          return NULL;
05269       }
05270       if (c) { /* if a char to return */
05271          p->subs[index].f.subclass = 0;
05272          p->subs[index].f.frametype = AST_FRAME_TEXT;
05273          p->subs[index].f.mallocd = 0;
05274          p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05275          p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET;
05276          p->subs[index].f.datalen = 1;
05277          *((char *) p->subs[index].f.data) = c;
05278          ast_mutex_unlock(&p->lock);
05279          return &p->subs[index].f;
05280       }
05281    }
05282    /* Ensure the CW timer decrements only on a single subchannel */
05283    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05284       p->callwaitingrepeat--;
05285    }
05286    if (p->cidcwexpire)
05287       p->cidcwexpire--;
05288    /* Repeat callwaiting */
05289    if (p->callwaitingrepeat == 1) {
05290       p->callwaitrings++;
05291       dahdi_callwait(ast);
05292    }
05293    /* Expire CID/CW */
05294    if (p->cidcwexpire == 1) {
05295       if (option_verbose > 2)
05296          ast_verbose(VERBOSE_PREFIX_3 "CPE does not support Call Waiting Caller*ID.\n");
05297       restore_conference(p);
05298    }
05299    if (p->subs[index].linear) {
05300       p->subs[index].f.datalen = READ_SIZE * 2;
05301    } else 
05302       p->subs[index].f.datalen = READ_SIZE;
05303 
05304    /* Handle CallerID Transmission */
05305    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05306       send_callerid(p);
05307    }
05308 
05309    p->subs[index].f.frametype = AST_FRAME_VOICE;
05310    p->subs[index].f.subclass = ast->rawreadformat;
05311    p->subs[index].f.samples = READ_SIZE;
05312    p->subs[index].f.mallocd = 0;
05313    p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
05314    p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
05315 #if 0
05316    ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
05317 #endif   
05318    if (p->dialing || /* Transmitting something */
05319       (index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05320       ((index == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05321       ) {
05322       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05323          don't send anything */
05324       p->subs[index].f.frametype = AST_FRAME_NULL;
05325       p->subs[index].f.subclass = 0;
05326       p->subs[index].f.samples = 0;
05327       p->subs[index].f.mallocd = 0;
05328       p->subs[index].f.offset = 0;
05329       p->subs[index].f.data = NULL;
05330       p->subs[index].f.datalen= 0;
05331    }
05332    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !index) {
05333       /* Perform busy detection. etc on the dahdi line */
05334       f = ast_dsp_process(ast, p->dsp, &p->subs[index].f);
05335       if (f) {
05336          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05337             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05338                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05339                   a busy  */
05340                f = NULL;
05341             }
05342          } else if (f->frametype == AST_FRAME_DTMF) {
05343 #ifdef HAVE_PRI
05344             if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
05345                /* Don't accept in-band DTMF when in overlap dial mode */
05346                f->frametype = AST_FRAME_NULL;
05347                f->subclass = 0;
05348             }
05349 #endif            
05350             /* DSP clears us of being pulse */
05351             p->pulsedial = 0;
05352          }
05353       }
05354    } else 
05355       f = &p->subs[index].f; 
05356 
05357    if (f && (f->frametype == AST_FRAME_DTMF))
05358       dahdi_handle_dtmfup(ast, index, &f);
05359 
05360    /* If we have a fake_event, trigger exception to handle it */
05361    if (p->fake_event)
05362       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05363 
05364    ast_mutex_unlock(&p->lock);
05365    return f;
05366 }

static struct ast_channel * dahdi_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 8282 of file chan_dahdi.c.

References alloc_sub(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose(), available(), dahdi_pvt::bearer, busy, ast_channel::cdrflags, CHAN_PSEUDO, chandup(), dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_pvt::digital, dahdi_pvt::distinctivering, iflist, iflock, dahdi_pvt::inalarm, dahdi_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, ast_channel::name, dahdi_pvt::next, NUM_SPANS, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), round_robin, s, dahdi_pvt::sig, SIG_FXSKS, dahdi_pri::span, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.

Referenced by pri_dchannel().

08283 {
08284    ast_group_t groupmatch = 0;
08285    int channelmatch = -1;
08286    int roundrobin = 0;
08287    int callwait = 0;
08288    int busy = 0;
08289    struct dahdi_pvt *p;
08290    struct ast_channel *tmp = NULL;
08291    char *dest=NULL;
08292    int x;
08293    char *s;
08294    char opt=0;
08295    int res=0, y=0;
08296    int backwards = 0;
08297 #ifdef HAVE_PRI
08298    int crv;
08299    int bearer = -1;
08300    int trunkgroup;
08301    struct dahdi_pri *pri=NULL;
08302 #endif   
08303    struct dahdi_pvt *exit, *start, *end;
08304    ast_mutex_t *lock;
08305    int channelmatched = 0;
08306    int groupmatched = 0;
08307    
08308    /*
08309     * data is ---v
08310     * Dial(DAHDI/pseudo[/extension])
08311     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
08312     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
08313     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
08314     *
08315     * g - channel group allocation search forward
08316     * G - channel group allocation search backward
08317     * r - channel group allocation round robin search forward
08318     * R - channel group allocation round robin search backward
08319     *
08320     * c - Wait for DTMF digit to confirm answer
08321     * r<cadance#> - Set distintive ring cadance number
08322     * d - Force bearer capability for ISDN call to digital.
08323     */
08324 
08325    /* Assume we're locking the iflock */
08326    lock = &iflock;
08327    start = iflist;
08328    end = ifend;
08329    if (data) {
08330       dest = ast_strdupa((char *)data);
08331    } else {
08332       ast_log(LOG_WARNING, "Channel requested with no data\n");
08333       return NULL;
08334    }
08335    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
08336       /* Retrieve the group number */
08337       char *stringp;
08338 
08339       stringp = dest + 1;
08340       s = strsep(&stringp, "/");
08341       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
08342          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
08343          return NULL;
08344       }
08345       groupmatch = ((ast_group_t) 1 << x);
08346       if (toupper(dest[0]) == 'G') {
08347          if (dest[0] == 'G') {
08348             backwards = 1;
08349             p = ifend;
08350          } else
08351             p = iflist;
08352       } else {
08353          if (dest[0] == 'R') {
08354             backwards = 1;
08355             p = round_robin[x]?round_robin[x]->prev:ifend;
08356             if (!p)
08357                p = ifend;
08358          } else {
08359             p = round_robin[x]?round_robin[x]->next:iflist;
08360             if (!p)
08361                p = iflist;
08362          }
08363          roundrobin = 1;
08364       }
08365    } else {
08366       char *stringp;
08367 
08368       stringp = dest;
08369       s = strsep(&stringp, "/");
08370       p = iflist;
08371       if (!strcasecmp(s, "pseudo")) {
08372          /* Special case for pseudo */
08373          x = CHAN_PSEUDO;
08374          channelmatch = x;
08375       } 
08376 #ifdef HAVE_PRI
08377       else if ((res = sscanf(s, "%30d:%30d%c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
08378          if ((trunkgroup < 1) || (crv < 1)) {
08379             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
08380             return NULL;
08381          }
08382          res--;
08383          for (x = 0; x < NUM_SPANS; x++) {
08384             if (pris[x].trunkgroup == trunkgroup) {
08385                pri = pris + x;
08386                lock = &pri->lock;
08387                start = pri->crvs;
08388                end = pri->crvend;
08389                break;
08390             }
08391          }
08392          if (!pri) {
08393             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
08394             return NULL;
08395          }
08396          channelmatch = crv;
08397          p = pris[x].crvs;
08398       }
08399 #endif   
08400       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
08401          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
08402          return NULL;
08403       } else {
08404          channelmatch = x;
08405       }
08406    }
08407    /* Search for an unowned channel */
08408    ast_mutex_lock(lock);
08409    exit = p;
08410    while (p && !tmp) {
08411       if (roundrobin)
08412          round_robin[x] = p;
08413 #if 0
08414       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
08415 #endif
08416 
08417       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
08418          if (option_debug)
08419             ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
08420             if (p->inalarm) 
08421                goto next;
08422 
08423          callwait = (p->owner != NULL);
08424 #ifdef HAVE_PRI
08425          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
08426             if (p->sig != SIG_FXSKS) {
08427                /* Gotta find an actual channel to use for this
08428                   CRV if this isn't a callwait */
08429                bearer = pri_find_empty_chan(pri, 0);
08430                if (bearer < 0) {
08431                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
08432                   p = NULL;
08433                   break;
08434                }
08435                pri_assign_bearer(p, pri, pri->pvts[bearer]);
08436             } else {
08437                if (alloc_sub(p, 0)) {
08438                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
08439                   p = NULL;
08440                   break;
08441                } else
08442                   ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
08443                p->pri = pri;
08444             }
08445          }
08446 #endif         
08447          if (p->channel == CHAN_PSEUDO) {
08448             p = chandup(p);
08449             if (!p) {
08450                break;
08451             }
08452          }
08453          if (p->owner) {
08454             if (alloc_sub(p, SUB_CALLWAIT)) {
08455                p = NULL;
08456                break;
08457             }
08458          }
08459          p->outgoing = 1;
08460          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
08461 #ifdef HAVE_PRI
08462          if (p->bearer) {
08463             /* Log owner to bearer channel, too */
08464             p->bearer->owner = tmp;
08465          }
08466 #endif         
08467          /* Make special notes */
08468          if (res > 1) {
08469             if (opt == 'c') {
08470                /* Confirm answer */
08471                p->confirmanswer = 1;
08472             } else if (opt == 'r') {
08473                /* Distinctive ring */
08474                if (res < 3)
08475                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
08476                else
08477                   p->distinctivering = y;
08478             } else if (opt == 'd') {
08479                /* If this is an ISDN call, make it digital */
08480                p->digital = 1;
08481                if (tmp)
08482                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
08483             } else {
08484                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
08485             }
08486          }
08487          /* Note if the call is a call waiting call */
08488          if (tmp && callwait)
08489             tmp->cdrflags |= AST_CDR_CALLWAIT;
08490          break;
08491       }
08492 next:
08493       if (backwards) {
08494          p = p->prev;
08495          if (!p)
08496             p = end;
08497       } else {
08498          p = p->next;
08499          if (!p)
08500             p = start;
08501       }
08502       /* stop when you roll to the one that we started from */
08503       if (p == exit)
08504          break;
08505    }
08506    ast_mutex_unlock(lock);
08507    restart_monitor();
08508    if (callwait)
08509       *cause = AST_CAUSE_BUSY;
08510    else if (!tmp) {
08511       if (channelmatched) {
08512          if (busy)
08513             *cause = AST_CAUSE_BUSY;
08514       } else if (groupmatched) {
08515          *cause = AST_CAUSE_CONGESTION;
08516       }
08517    }
08518       
08519    return tmp;
08520 }

static int dahdi_restart ( void   )  [static]

Definition at line 10448 of file chan_dahdi.c.

References ast_active_channels(), ast_cond_wait, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_verbose(), dahdi_close_pri_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, lock, master, monlock, dahdi_pvt::next, NUM_SPANS, option_debug, option_verbose, dahdi_pvt::owner, pris, restart_lock, setup_dahdi(), ss_thread_lock, and dahdi_pvt::subs.

Referenced by __action_restart(), and dahdi_restart_cmd().

10449 {
10450 #if defined(HAVE_PRI)
10451    int i, j;
10452 #endif
10453    int cancel_code;
10454    struct dahdi_pvt *p;
10455 
10456    ast_mutex_lock(&restart_lock);
10457  
10458    if (option_verbose)
10459       ast_verbose("Destroying channels and reloading DAHDI configuration.\n");
10460    dahdi_softhangup_all();
10461    if (option_verbose > 3)
10462       ast_verbose("Initial softhangup of all DAHDI channels complete.\n");
10463 
10464    #if defined(HAVE_PRI)
10465    for (i = 0; i < NUM_SPANS; i++) {
10466       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
10467          cancel_code = pthread_cancel(pris[i].master);
10468          pthread_kill(pris[i].master, SIGURG);
10469          if (option_debug > 3)
10470             ast_verbose("Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
10471             pthread_join(pris[i].master, NULL);
10472          if (option_debug > 3)
10473             ast_verbose("Joined thread of span %d\n", i);
10474       }
10475     }
10476    #endif
10477 
10478     ast_mutex_lock(&monlock);
10479     if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
10480       cancel_code = pthread_cancel(monitor_thread);
10481       pthread_kill(monitor_thread, SIGURG);
10482       if (option_debug > 3)
10483          ast_verbose("Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
10484         pthread_join(monitor_thread, NULL);
10485       if (option_debug > 3)
10486          ast_verbose("Joined monitor thread\n");
10487     }
10488    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
10489 
10490    ast_mutex_lock(&ss_thread_lock);
10491    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
10492       int x = DAHDI_FLASH;
10493       if (option_debug > 2)
10494          ast_verbose("Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
10495 
10496       for (p = iflist; p; p = p->next) {
10497          if (p->owner)
10498             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 */    
10499       }
10500       ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
10501    }
10502 
10503    /* ensure any created channels before monitor threads were stopped are hungup */
10504    dahdi_softhangup_all();
10505    if (option_verbose > 3)
10506       ast_verbose("Final softhangup of all DAHDI channels complete.\n");
10507    destroy_all_channels();
10508    if (option_debug)
10509       ast_verbose("Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
10510 
10511     ast_mutex_unlock(&monlock);
10512 
10513    #ifdef HAVE_PRI
10514    for (i = 0; i < NUM_SPANS; i++) {
10515       for (j = 0; j < NUM_DCHANS; j++)
10516             dahdi_close_pri_fd(&(pris[i]), j);
10517    }
10518 
10519    memset(pris, 0, sizeof(pris));
10520    for (i = 0; i < NUM_SPANS; i++) {
10521       ast_mutex_init(&pris[i].lock);
10522       pris[i].offset = -1;
10523       pris[i].master = AST_PTHREADT_NULL;
10524       for (j = 0; j < NUM_DCHANS; j++)
10525          pris[i].fds[j] = -1;
10526    }
10527    pri_set_error(dahdi_pri_error);
10528    pri_set_message(dahdi_pri_message);
10529    #endif
10530 
10531    if (setup_dahdi(2) != 0) {
10532       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
10533       ast_mutex_unlock(&ss_thread_lock);
10534       return 1;
10535    }
10536    ast_mutex_unlock(&ss_thread_lock);
10537    ast_mutex_unlock(&restart_lock);
10538    return 0;
10539 }

static int dahdi_restart_cmd ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10541 of file chan_dahdi.c.

References dahdi_restart(), RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10542 {
10543    if (argc != 2) {
10544       return RESULT_SHOWUSAGE;
10545    }
10546 
10547    if (dahdi_restart() != 0)
10548       return RESULT_FAILURE;
10549    return RESULT_SUCCESS;
10550 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 3872 of file chan_dahdi.c.

References ast_log(), errno, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), and dahdi_handle_event().

03873 {
03874    int x;
03875    int res;
03876    /* Make sure our transmit state is on hook */
03877    x = 0;
03878    x = DAHDI_ONHOOK;
03879    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03880    do {
03881       x = DAHDI_RING;
03882       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03883       if (res) {
03884          switch (errno) {
03885          case EBUSY:
03886          case EINTR:
03887             /* Wait just in case */
03888             usleep(10000);
03889             continue;
03890          case EINPROGRESS:
03891             res = 0;
03892             break;
03893          default:
03894             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
03895             res = 0;
03896          }
03897       }
03898    } while (res);
03899    return res;
03900 }

static int dahdi_send_keypad_facility_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 2725 of file chan_dahdi.c.

References send_keypad_facility_exec().

Referenced by load_module().

02726 {
02727    return send_keypad_facility_exec(chan, data);
02728 }

static int dahdi_sendtext ( struct ast_channel c,
const char *  text 
) [static]

Definition at line 12275 of file chan_dahdi.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_free, AST_LAW, ast_log(), ast_malloc, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, free, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, dahdi_pvt::mate, option_debug, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.

12276 {
12277 #define  END_SILENCE_LEN 400
12278 #define  HEADER_MS 50
12279 #define  TRAILER_MS 5
12280 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
12281 #define  ASCII_BYTES_PER_CHAR 80
12282 
12283    unsigned char *buf,*mybuf;
12284    struct dahdi_pvt *p = c->tech_pvt;
12285    struct pollfd fds[1];
12286    int size,res,fd,len,x;
12287    int bytes=0;
12288    /* Initial carrier (imaginary) */
12289    float cr = 1.0;
12290    float ci = 0.0;
12291    float scont = 0.0;
12292    int index;
12293 
12294    index = dahdi_get_index(c, p, 0);
12295    if (index < 0) {
12296       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
12297       return -1;
12298    }
12299    if (!text[0]) return(0); /* if nothing to send, dont */
12300    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
12301    if (p->mate) 
12302       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
12303    else
12304       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
12305    if (!buf)
12306       return -1;
12307    mybuf = buf;
12308    if (p->mate) {
12309       int codec = AST_LAW(p);
12310       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
12311          PUT_CLID_MARKMS;
12312       }
12313       /* Put actual message */
12314       for (x = 0; text[x]; x++) {
12315          PUT_CLID(text[x]);
12316       }
12317       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
12318          PUT_CLID_MARKMS;
12319       }
12320       len = bytes;
12321       buf = mybuf;
12322    } else {
12323       len = tdd_generate(p->tdd, buf, text);
12324       if (len < 1) {
12325          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
12326          free(mybuf);
12327          return -1;
12328       }
12329    }
12330    memset(buf + len, 0x7f, END_SILENCE_LEN);
12331    len += END_SILENCE_LEN;
12332    fd = p->subs[index].dfd;
12333    while (len) {
12334       if (ast_check_hangup(c)) {
12335          free(mybuf);
12336          return -1;
12337       }
12338       size = len;
12339       if (size > READ_SIZE)
12340          size = READ_SIZE;
12341       fds[0].fd = fd;
12342       fds[0].events = POLLOUT | POLLPRI;
12343       fds[0].revents = 0;
12344       res = poll(fds, 1, -1);
12345       if (!res) {
12346          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
12347          continue;
12348       }
12349         /* if got exception */
12350       if (fds[0].revents & POLLPRI) {
12351          ast_free(mybuf);
12352          return -1;
12353       }
12354       if (!(fds[0].revents & POLLOUT)) {
12355          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12356          continue;
12357       }
12358       res = write(fd, buf, size);
12359       if (res != size) {
12360          if (res == -1) {
12361             free(mybuf);
12362             return -1;
12363          }
12364          if (option_debug)
12365             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12366          break;
12367       }
12368       len -= size;
12369       buf += size;
12370    }
12371    free(mybuf);
12372    return(0);
12373 }

static int dahdi_set_hook ( int  fd,
int  hs 
) [inline, static]

Definition at line 1972 of file chan_dahdi.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by __dahdi_exception(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_wink(), handle_init_event(), and ss_thread().

01973 {
01974    int x, res;
01975 
01976    x = hs;
01977    res = ioctl(fd, DAHDI_HOOK, &x);
01978 
01979    if (res < 0) {
01980       if (errno == EINPROGRESS)
01981          return 0;
01982       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
01983       /* will expectedly fail if phone is off hook during operation, such as during a restart */
01984    }
01985 
01986    return res;
01987 }

static int dahdi_setlaw ( int  dfd,
int  law 
) [static]

Definition at line 8876 of file chan_dahdi.c.

08877 {
08878    int res;
08879    res = ioctl(dfd, DAHDI_SETLAW, &law);
08880    if (res)
08881       return res;
08882    return 0;
08883 }

static int dahdi_setlinear ( int  dfd,
int  linear 
) [static]

Definition at line 1288 of file chan_dahdi.c.

Referenced by dahdi_hangup(), dahdi_new(), dahdi_read(), dahdi_write(), send_callerid(), and ss_thread().

01289 {
01290    int res;
01291    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01292    if (res)
01293       return res;
01294    return 0;
01295 }

static int dahdi_setoption ( struct ast_channel chan,
int  option,
void *  data,
int  datalen 
) [static]

Definition at line 3236 of file chan_dahdi.c.

References ast_check_hangup(), ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_DEBUG, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, oprmode::peer, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.

03237 {
03238    char *cp;
03239    signed char *scp;
03240    int x;
03241    int index;
03242    struct dahdi_pvt *p = chan->tech_pvt, *pp;
03243    struct oprmode *oprmode;
03244    
03245 
03246    /* all supported options require data */
03247    if (!data || (datalen < 1)) {
03248       errno = EINVAL;
03249       return -1;
03250    }
03251 
03252    switch (option) {
03253    case AST_OPTION_TXGAIN:
03254       scp = (signed char *) data;
03255       index = dahdi_get_index(chan, p, 0);
03256       if (index < 0) {
03257          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03258          return -1;
03259       }
03260       if (option_debug)
03261          ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03262       return set_actual_txgain(p->subs[index].dfd, 0, p->txgain + (float) *scp, p->law);
03263    case AST_OPTION_RXGAIN:
03264       scp = (signed char *) data;
03265       index = dahdi_get_index(chan, p, 0);
03266       if (index < 0) {
03267          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03268          return -1;
03269       }
03270       if (option_debug)
03271          ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03272       return set_actual_rxgain(p->subs[index].dfd, 0, p->rxgain + (float) *scp, p->law);
03273    case AST_OPTION_TONE_VERIFY:
03274       if (!p->dsp)
03275          break;
03276       cp = (char *) data;
03277       switch (*cp) {
03278       case 1:
03279          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03280          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
03281          break;
03282       case 2:
03283          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03284          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
03285          break;
03286       default:
03287          ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03288          ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
03289          break;
03290       }
03291       break;
03292    case AST_OPTION_TDD:
03293       /* turn on or off TDD */
03294       cp = (char *) data;
03295       p->mate = 0;
03296       if (!*cp) { /* turn it off */
03297          if (option_debug)
03298             ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03299          if (p->tdd)
03300             tdd_free(p->tdd);
03301          p->tdd = 0;
03302          break;
03303       }
03304       ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
03305          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03306       dahdi_disable_ec(p);
03307       /* otherwise, turn it on */
03308       if (!p->didtdd) { /* if havent done it yet */
03309          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
03310          unsigned char *buf;
03311          int size, res, fd, len;
03312          struct pollfd fds[1];
03313 
03314          buf = mybuf;
03315          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03316          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03317          len = 40000;
03318          index = dahdi_get_index(chan, p, 0);
03319          if (index < 0) {
03320             ast_log(LOG_WARNING, "No index in TDD?\n");
03321             return -1;
03322          }
03323          fd = p->subs[index].dfd;
03324          while (len) {
03325             if (ast_check_hangup(chan))
03326                return -1;
03327             size = len;
03328             if (size > READ_SIZE)
03329                size = READ_SIZE;
03330             fds[0].fd = fd;
03331             fds[0].events = POLLPRI | POLLOUT;
03332             fds[0].revents = 0;
03333             res = poll(fds, 1, -1);
03334             if (!res) {
03335                ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
03336                continue;
03337             }
03338             /* if got exception */
03339             if (fds[0].revents & POLLPRI)
03340                return -1;
03341             if (!(fds[0].revents & POLLOUT)) {
03342                ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
03343                continue;
03344             }
03345             res = write(fd, buf, size);
03346             if (res != size) {
03347                if (res == -1) return -1;
03348                ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03349                break;
03350             }
03351             len -= size;
03352             buf += size;
03353          }
03354          p->didtdd = 1; /* set to have done it now */    
03355       }
03356       if (*cp == 2) { /* Mate mode */
03357          if (p->tdd)
03358             tdd_free(p->tdd);
03359          p->tdd = 0;
03360          p->mate = 1;
03361          break;
03362       }     
03363       if (!p->tdd) { /* if we dont have one yet */
03364          p->tdd = tdd_new(); /* allocate one */
03365       }     
03366       break;
03367    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03368       if (!p->dsp)
03369          break;
03370       cp = (char *) data;
03371       ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03372          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03373                 p->dtmfrelax = 0;
03374                 if (*cp) p->dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
03375                 ast_dsp_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03376       break;
03377    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03378       cp = (char *) data;
03379       if (!*cp) {    
03380          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03381          x = 0;
03382          dahdi_disable_ec(p);
03383       } else {    
03384          ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03385          x = 1;
03386       }
03387       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03388          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03389       break;
03390    case AST_OPTION_OPRMODE:  /* Operator services mode */
03391       oprmode = (struct oprmode *) data;
03392       pp = oprmode->peer->tech_pvt;
03393       p->oprmode = pp->oprmode = 0;
03394       /* setup peers */
03395       p->oprpeer = pp;
03396       pp->oprpeer = p;
03397       /* setup modes, if any */
03398       if (oprmode->mode) 
03399       {
03400          pp->oprmode = oprmode->mode;
03401          p->oprmode = -oprmode->mode;
03402       }
03403       ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
03404          oprmode->mode, chan->name,oprmode->peer->name);;
03405       break;
03406    case AST_OPTION_ECHOCAN:
03407       cp = (char *) data;
03408       if (*cp) {
03409          ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
03410          dahdi_enable_ec(p);
03411       } else {
03412          ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
03413          dahdi_disable_ec(p);
03414       }
03415       break;
03416    }
03417    errno = 0;
03418 
03419    return 0;
03420 }

static int dahdi_show_channel ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10613 of file chan_dahdi.c.

References ast_cli(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), dahdi_pvt::bearer, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::call, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, lock, dahdi_pvt::logicalspan, dahdi_pvt::master, ast_channel::name, dahdi_pvt::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pris, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::resetting, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_THREEWAY, and dahdi_pvt::subs.

10614 {
10615    int channel;
10616    struct dahdi_pvt *tmp = NULL;
10617    struct dahdi_confinfo ci;
10618    struct dahdi_params ps;
10619    int x;
10620    ast_mutex_t *lock;
10621    struct dahdi_pvt *start;
10622 #ifdef HAVE_PRI
10623    char *c;
10624    int trunkgroup;
10625    struct dahdi_pri *pri=NULL;
10626 #endif
10627 
10628    lock = &iflock;
10629    start = iflist;
10630 
10631    if (argc != 4)
10632       return RESULT_SHOWUSAGE;
10633 #ifdef HAVE_PRI
10634    if ((c = strchr(argv[3], ':'))) {
10635       if (sscanf(argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
10636          return RESULT_SHOWUSAGE;
10637       if ((trunkgroup < 1) || (channel < 1))
10638          return RESULT_SHOWUSAGE;
10639       for (x = 0; x < NUM_SPANS; x++) {
10640          if (pris[x].trunkgroup == trunkgroup) {
10641             pri = pris + x;
10642             break;
10643          }
10644       }
10645       if (pri) {
10646          start = pri->crvs;
10647          lock = &pri->lock;
10648       } else {
10649          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10650          return RESULT_FAILURE;
10651       }
10652    } else
10653 #endif
10654       channel = atoi(argv[3]);
10655 
10656    ast_mutex_lock(lock);
10657    tmp = start;
10658    while (tmp) {
10659       if (tmp->channel == channel) {
10660 #ifdef HAVE_PRI
10661          if (pri) 
10662             ast_cli(fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
10663          else
10664 #endif         
10665          ast_cli(fd, "Channel: %d\n", tmp->channel);
10666          ast_cli(fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
10667          ast_cli(fd, "Span: %d\n", tmp->span);
10668          ast_cli(fd, "Extension: %s\n", tmp->exten);
10669          ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
10670          ast_cli(fd, "Context: %s\n", tmp->context);
10671          ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
10672          ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
10673          ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
10674          ast_cli(fd, "Destroy: %d\n", tmp->destroy);
10675          ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
10676          ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
10677          ast_cli(fd, "Radio: %d\n", tmp->radio);
10678          ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
10679          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)" : "");
10680          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)" : "");
10681          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)" : "");
10682          ast_cli(fd, "Confno: %d\n", tmp->confno);
10683          ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
10684          ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
10685          ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
10686          ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
10687          ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
10688          ast_cli(fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
10689          ast_cli(fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
10690          ast_cli(fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
10691          ast_cli(fd, "Echo Cancellation: %d taps%s, currently %s\n", tmp->echocancel, tmp->echocanbridged ? "" : " unless TDM bridged", tmp->echocanon ? "ON" : "OFF");
10692          if (tmp->master)
10693             ast_cli(fd, "Master Channel: %d\n", tmp->master->channel);
10694          for (x = 0; x < MAX_SLAVES; x++) {
10695             if (tmp->slaves[x])
10696                ast_cli(fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
10697          }
10698 #ifdef HAVE_PRI
10699          if (tmp->pri) {
10700             ast_cli(fd, "PRI Flags: ");
10701             if (tmp->resetting)
10702                ast_cli(fd, "Resetting ");
10703             if (tmp->call)
10704                ast_cli(fd, "Call ");
10705             if (tmp->bearer)
10706                ast_cli(fd, "Bearer ");
10707             ast_cli(fd, "\n");
10708             if (tmp->logicalspan) 
10709                ast_cli(fd, "PRI Logical Span: %d\n", tmp->logicalspan);
10710             else
10711                ast_cli(fd, "PRI Logical Span: Implicit\n");
10712          }
10713             
10714 #endif
10715          memset(&ci, 0, sizeof(ci));
10716          ps.channo = tmp->channel;
10717          if (tmp->subs[SUB_REAL].dfd > -1) {
10718             memset(&ci, 0, sizeof(ci));
10719             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
10720                ast_cli(fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
10721             }
10722 #ifdef DAHDI_GETCONFMUTE
10723             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
10724                ast_cli(fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
10725             }
10726 #endif
10727             memset(&ps, 0, sizeof(ps));
10728             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
10729                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
10730             } else {
10731                ast_cli(fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
10732             }
10733          }
10734          if (ISTRUNK(tmp)) {
10735             ast_cli(fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
10736             if (!ast_strlen_zero(progzone))
10737                ast_cli(fd, "Progress Zone: %s\n", progzone);
10738             ast_cli(fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
10739             if(tmp->busydetect) {
10740                ast_cli(fd, "Busy Count: %d\n", tmp->busycount);
10741                if(tmp->busytonelength > 0) {
10742                   ast_cli(fd, "Busy Pattern:\n");
10743                   ast_cli(fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
10744                   if (tmp->busyquietlength > 0) 
10745                      ast_cli(fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
10746                   else 
10747                      ast_cli(fd, " -- Detect Tone Only\n");
10748                   if(tmp->busyfuzziness > 0)
10749                      ast_cli(fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
10750                }
10751             }
10752          }
10753          ast_mutex_unlock(lock);
10754          return RESULT_SUCCESS;
10755       }
10756       tmp = tmp->next;
10757    }
10758    
10759    ast_cli(fd, "Unable to find given channel %d\n", channel);
10760    ast_mutex_unlock(lock);
10761    return RESULT_FAILURE;
10762 }

static int dahdi_show_channels ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10552 of file chan_dahdi.c.

References ast_cli(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::channel, dahdi_pvt::context, dahdi_pvt::exten, FORMAT, FORMAT2, iflist, iflock, dahdi_pvt::language, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, NUM_SPANS, dahdi_pri::pri, pris, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10553 {
10554 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10555 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10556    struct dahdi_pvt *tmp = NULL;
10557    char tmps[20] = "";
10558    ast_mutex_t *lock;
10559    struct dahdi_pvt *start;
10560 #ifdef HAVE_PRI
10561    int trunkgroup;
10562    struct dahdi_pri *pri = NULL;
10563    int x;
10564 #endif
10565 
10566    lock = &iflock;
10567    start = iflist;
10568 
10569 #ifdef HAVE_PRI
10570    if (argc == 4) {
10571       if ((trunkgroup = atoi(argv[3])) < 1)
10572          return RESULT_SHOWUSAGE;
10573       for (x = 0; x < NUM_SPANS; x++) {
10574          if (pris[x].trunkgroup == trunkgroup) {
10575             pri = pris + x;
10576             break;
10577          }
10578       }
10579       if (pri) {
10580          start = pri->crvs;
10581          lock = &pri->lock;
10582       } else {
10583          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10584          return RESULT_FAILURE;
10585       }
10586    } else
10587 #endif
10588    if (argc != 3)
10589       return RESULT_SHOWUSAGE;
10590 
10591    ast_mutex_lock(lock);
10592 #ifdef HAVE_PRI
10593    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10594 #else
10595    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10596 #endif   
10597    
10598    tmp = start;
10599    while (tmp) {
10600       if (tmp->channel > 0) {
10601          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10602       } else
10603          ast_copy_string(tmps, "pseudo", sizeof(tmps));
10604       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10605       tmp = tmp->next;
10606    }
10607    ast_mutex_unlock(lock);
10608    return RESULT_SUCCESS;
10609 #undef FORMAT
10610 #undef FORMAT2
10611 }

static int dahdi_show_status ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10795 of file chan_dahdi.c.

References alarms, ast_cli(), ast_log(), DAHDI_FILE_CTL, errno, FORMAT, FORMAT2, RESULT_FAILURE, and dahdi_pri::span.

10795                                                              {
10796    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10797    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10798 
10799    int span;
10800    int res;
10801    char alarms[50];
10802 
10803    int ctl;
10804    struct dahdi_spaninfo s;
10805 
10806    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
10807       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
10808       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
10809       return RESULT_FAILURE;
10810    }
10811    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10812 
10813    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10814       s.spanno = span;
10815       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10816       if (res) {
10817          continue;
10818       }
10819       alarms[0] = '\0';
10820       if (s.alarms > 0) {
10821          if (s.alarms & DAHDI_ALARM_BLUE)
10822             strcat(alarms, "BLU/");
10823          if (s.alarms & DAHDI_ALARM_YELLOW)
10824             strcat(alarms, "YEL/");
10825          if (s.alarms & DAHDI_ALARM_RED)
10826             strcat(alarms, "RED/");
10827          if (s.alarms & DAHDI_ALARM_LOOPBACK)
10828             strcat(alarms, "LB/");
10829          if (s.alarms & DAHDI_ALARM_RECOVER)
10830             strcat(alarms, "REC/");
10831          if (s.alarms & DAHDI_ALARM_NOTOPEN)
10832             strcat(alarms, "NOP/");
10833          if (!strlen(alarms))
10834             strcat(alarms, "UUU/");
10835          if (strlen(alarms)) {
10836             /* Strip trailing / */
10837             alarms[strlen(alarms) - 1] = '\0';
10838          }
10839       } else {
10840          if (s.numchans)
10841             strcpy(alarms, "OK");
10842          else
10843             strcpy(alarms, "UNCONFIGURED");
10844       }
10845 
10846       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10847    }
10848    close(ctl);
10849 
10850    return RESULT_SUCCESS;
10851 #undef FORMAT
10852 #undef FORMAT2
10853 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 1525 of file chan_dahdi.c.

References SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, and SIG_SFWINK.

01526 {
01527    static char buf[256];
01528    switch (sig) {
01529    case SIG_EM:
01530       return "E & M Immediate";
01531    case SIG_EMWINK:
01532       return "E & M Wink";
01533    case SIG_EM_E1:
01534       return "E & M E1";
01535    case SIG_FEATD:
01536       return "Feature Group D (DTMF)";
01537    case SIG_FEATDMF:
01538       return "Feature Group D (MF)";
01539    case SIG_FEATDMF_TA:
01540       return "Feature Groud D (MF) Tandem Access";
01541    case SIG_FEATB:
01542       return "Feature Group B (MF)";
01543    case SIG_E911:
01544       return "E911 (MF)";
01545    case SIG_FGC_CAMA:
01546       return "FGC/CAMA (Dialpulse)";
01547    case SIG_FGC_CAMAMF:
01548       return "FGC/CAMA (MF)";
01549    case SIG_FXSLS:
01550       return "FXS Loopstart";
01551    case SIG_FXSGS:
01552       return "FXS Groundstart";
01553    case SIG_FXSKS:
01554       return "FXS Kewlstart";
01555    case SIG_FXOLS:
01556       return "FXO Loopstart";
01557    case SIG_FXOGS:
01558       return "FXO Groundstart";
01559    case SIG_FXOKS:
01560       return "FXO Kewlstart";
01561    case SIG_PRI:
01562       return "ISDN PRI";
01563    case SIG_SF:
01564       return "SF (Tone) Immediate";
01565    case SIG_SFWINK:
01566       return "SF (Tone) Wink";
01567    case SIG_SF_FEATD:
01568       return "SF (Tone) with Feature Group D (DTMF)";
01569    case SIG_SF_FEATDMF:
01570       return "SF (Tone) with Feature Group D (MF)";
01571    case SIG_SF_FEATB:
01572       return "SF (Tone) with Feature Group B (MF)";
01573    case SIG_GR303FXOKS:
01574       return "GR-303 with FXOKS";
01575    case SIG_GR303FXSKS:
01576       return "GR-303 with FXSKS";
01577    case 0:
01578       return "Pseudo";
01579    default:
01580       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01581       return buf;
01582    }
01583 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 10419 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock, ast_mutex_unlock, AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_verbose(), iflist, iflock, dahdi_pvt::lock, ast_channel::name, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

10420 {
10421    struct dahdi_pvt *p;
10422 retry:
10423    ast_mutex_lock(&iflock);
10424     for (p = iflist; p; p = p->next) {
10425       ast_mutex_lock(&p->lock);
10426         if (p->owner && !p->restartpending) {
10427          if (ast_channel_trylock(p->owner)) {
10428             if (option_debug > 2)
10429                ast_verbose("Avoiding deadlock\n");
10430             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10431             ast_mutex_unlock(&p->lock);
10432             ast_mutex_unlock(&iflock);
10433             goto retry;
10434          }
10435          if (option_debug > 2)
10436             ast_verbose("Softhanging up on %s\n", p->owner->name);
10437          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10438          p->restartpending = 1;
10439          num_restart_pending++;
10440          ast_channel_unlock(p->owner);
10441       }
10442       ast_mutex_unlock(&p->lock);
10443     }
10444    ast_mutex_unlock(&iflock);
10445 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1804 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, LOG_DEBUG, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_answer(), and dahdi_handle_event().

01805 {
01806    int x;
01807    int res;
01808    if (p && p->echocancel && p->echotraining) {
01809       x = p->echotraining;
01810       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
01811       if (res)
01812          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
01813       else {
01814          ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
01815       }
01816    } else
01817       ast_log(LOG_DEBUG, "No echo training requested\n");
01818 }

static void dahdi_unlink ( struct dahdi_pvt slave,
struct dahdi_pvt master,
int  needlock 
) [static]

Definition at line 3441 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_trylock, conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, LOG_DEBUG, master, and SUB_REAL.

Referenced by dahdi_bridge(), and dahdi_fixup().

03442 {
03443    /* Unlink a specific slave or all slaves/masters from a given master */
03444    int x;
03445    int hasslaves;
03446    if (!master)
03447       return;
03448    if (needlock) {
03449       ast_mutex_lock(&master->lock);
03450       if (slave) {
03451          while (ast_mutex_trylock(&slave->lock)) {
03452             DEADLOCK_AVOIDANCE(&master->lock);
03453          }
03454       }
03455    }
03456    hasslaves = 0;
03457    for (x = 0; x < MAX_SLAVES; x++) {
03458       if (master->slaves[x]) {
03459          if (!slave || (master->slaves[x] == slave)) {
03460             /* Take slave out of the conference */
03461             ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
03462             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
03463             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
03464             master->slaves[x]->master = NULL;
03465             master->slaves[x] = NULL;
03466          } else
03467             hasslaves = 1;
03468       }
03469       if (!hasslaves)
03470          master->inconference = 0;
03471    }
03472    if (!slave) {
03473       if (master->master) {
03474          /* Take master out of the conference */
03475          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
03476          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
03477          hasslaves = 0;
03478          for (x = 0; x < MAX_SLAVES; x++) {
03479             if (master->master->slaves[x] == master)
03480                master->master->slaves[x] = NULL;
03481             else if (master->master->slaves[x])
03482                hasslaves = 1;
03483          }
03484          if (!hasslaves)
03485             master->master->inconference = 0;
03486       }
03487       master->master = NULL;
03488    }
03489    update_conf(master);
03490    if (needlock) {
03491       if (slave)
03492          ast_mutex_unlock(&slave->lock);
03493       ast_mutex_unlock(&master->lock);
03494    }
03495 }

static int dahdi_wait_event ( int  fd  )  [inline, static]

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 265 of file chan_dahdi.c.

Referenced by ss_thread().

00266 {
00267    int i, j = 0;
00268    i = DAHDI_IOMUX_SIGEVENT;
00269    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00270       return -1;
00271    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00272       return -1;
00273    return j;
00274 }

static int dahdi_wink ( struct dahdi_pvt p,
int  index 
) [static]

Definition at line 5866 of file chan_dahdi.c.

References dahdi_set_hook(), dahdi_subchannel::dfd, and dahdi_pvt::subs.

Referenced by ss_thread().

05867 {
05868    int j;
05869    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
05870    for (;;)
05871    {
05872          /* set bits of interest */
05873       j = DAHDI_IOMUX_SIGEVENT;
05874           /* wait for some happening */
05875       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
05876          /* exit loop if we have it */
05877       if (j & DAHDI_IOMUX_SIGEVENT) break;
05878    }
05879      /* get the event info */
05880    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
05881    return 0;
05882 }

static int dahdi_write ( struct ast_channel ast,
struct ast_frame frame 
) [static]

Definition at line 5391 of file chan_dahdi.c.

References AST_FORMAT_ALAW, AST_FORMAT_SLINEAR, AST_FORMAT_ULAW, AST_FRAME_IMAGE, AST_FRAME_VOICE, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::call, dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_get_index(), dahdi_setlinear(), ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, errno, ast_frame::frametype, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, my_dahdi_write(), ast_channel::name, option_debug, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, PVT_TO_CHANNEL, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

05392 {
05393    struct dahdi_pvt *p = ast->tech_pvt;
05394    int res;
05395    int index;
05396    index = dahdi_get_index(ast, p, 0);
05397    if (index < 0) {
05398       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05399       return -1;
05400    }
05401 
05402 #if 0
05403 #ifdef HAVE_PRI
05404    ast_mutex_lock(&p->lock);
05405    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05406       if (p->pri->pri) {      
05407          if (!pri_grab(p, p->pri)) {
05408                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05409                pri_rel(p->pri);
05410          } else
05411                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05412       }
05413       p->proceeding=1;
05414    }
05415    ast_mutex_unlock(&p->lock);
05416 #endif
05417 #endif
05418    /* Write a frame of (presumably voice) data */
05419    if (frame->frametype != AST_FRAME_VOICE) {
05420       if (frame->frametype != AST_FRAME_IMAGE)
05421          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05422       return 0;
05423    }
05424    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
05425        (frame->subclass != AST_FORMAT_ULAW) &&
05426        (frame->subclass != AST_FORMAT_ALAW)) {
05427       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
05428       return -1;
05429    }
05430    if (p->dialing) {
05431       if (option_debug)
05432          ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
05433       return 0;
05434    }
05435    if (!p->owner) {
05436       if (option_debug)
05437          ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
05438       return 0;
05439    }
05440    if (p->cidspill) {
05441       if (option_debug)
05442          ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
05443       return 0;
05444    }
05445    /* Return if it's not valid data */
05446    if (!frame->data || !frame->datalen)
05447       return 0;
05448 
05449    if (frame->subclass == AST_FORMAT_SLINEAR) {
05450       if (!p->subs[index].linear) {
05451          p->subs[index].linear = 1;
05452          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05453          if (res)
05454             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
05455       }
05456       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 1);
05457    } else {
05458       /* x-law already */
05459       if (p->subs[index].linear) {
05460          p->subs[index].linear = 0;
05461          res = dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
05462          if (res)
05463             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
05464       }
05465       res = my_dahdi_write(p, (unsigned char *)frame->data, frame->datalen, index, 0);
05466    }
05467    if (res < 0) {
05468       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
05469       return -1;
05470    } 
05471    return 0;
05472 }

static void destroy_all_channels ( void   )  [static]

Definition at line 2641 of file chan_dahdi.c.

References ast_free, ast_mutex_lock, ast_mutex_unlock, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cidspill, destroy_dahdi_pvt(), iflist, iflock, dahdi_pvt::next, option_verbose, and VERBOSE_PREFIX_2.

Referenced by __unload_module(), and dahdi_restart().

02642 {
02643    int x;
02644    struct dahdi_pvt *p, *pl;
02645 
02646    while (num_restart_pending) {
02647       usleep(1);
02648    }
02649 
02650    ast_mutex_lock(&iflock);
02651    /* Destroy all the interfaces and free their memory */
02652    p = iflist;
02653    while (p) {
02654       /* Free any callerid */
02655       if (p->cidspill)
02656          ast_free(p->cidspill);
02657       pl = p;
02658       p = p->next;
02659       x = pl->channel;
02660       /* Free associated memory */
02661       if (pl)
02662          destroy_dahdi_pvt(&pl);
02663       if (option_verbose > 2) 
02664          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
02665    }
02666    iflist = NULL;
02667    ifcount = 0;
02668    ast_mutex_unlock(&iflock);
02669 }

static int destroy_channel ( struct dahdi_pvt prev,
struct dahdi_pvt cur,
int  now 
) [static]

Definition at line 2591 of file chan_dahdi.c.

References destroy_dahdi_pvt(), iflist, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::prev, and dahdi_pvt::subs.

Referenced by dahdi_destroy_channel_bynum(), and dahdi_hangup().

02592 {
02593    int owned = 0;
02594    int i = 0;
02595 
02596    if (!now) {
02597       if (cur->owner) {
02598          owned = 1;
02599       }
02600 
02601       for (i = 0; i < 3; i++) {
02602          if (cur->subs[i].owner) {
02603             owned = 1;
02604          }
02605       }
02606       if (!owned) {
02607          if (prev) {
02608             prev->next = cur->next;
02609             if (prev->next)
02610                prev->next->prev = prev;
02611             else
02612                ifend = prev;
02613          } else {
02614             iflist = cur->next;
02615             if (iflist)
02616                iflist->prev = NULL;
02617             else
02618                ifend = NULL;
02619          }
02620          destroy_dahdi_pvt(&cur);
02621       }
02622    } else {
02623       if (prev) {
02624          prev->next = cur->next;
02625          if (prev->next)
02626             prev->next->prev = prev;
02627          else
02628             ifend = prev;
02629       } else {
02630          iflist = cur->next;
02631          if (iflist)
02632             iflist->prev = NULL;
02633          else
02634             ifend = NULL;
02635       }
02636       destroy_dahdi_pvt(&cur);
02637    }
02638    return 0;
02639 }

static void destroy_dahdi_pvt ( struct dahdi_pvt **  pvt  )  [static]

Definition at line 2573 of file chan_dahdi.c.

References ast_mutex_destroy, ast_smdi_interface_unref(), dahdi_close_sub(), free, dahdi_pvt::lock, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::smdi_iface, SUB_REAL, ast_channel::tech_pvt, and dahdi_pvt::use_smdi.

Referenced by chandup(), destroy_all_channels(), destroy_channel(), and mkintf().

02574 {
02575    struct dahdi_pvt *p = *pvt;
02576    /* Remove channel from the list */
02577    if (p->prev)
02578       p->prev->next = p->next;
02579    if (p->next)
02580       p->next->prev = p->prev;
02581    if (p->use_smdi)
02582       ast_smdi_interface_unref(p->smdi_iface);
02583    ast_mutex_destroy(&p->lock);
02584    dahdi_close_sub(p, SUB_REAL);
02585    if (p->owner)
02586       p->owner->tech_pvt = NULL;
02587    free(p);
02588    *pvt = NULL;
02589 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 1516 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

01517 {
01518    if (dialplan == -1) {
01519       return("Dynamically set dialplan in ISDN");
01520    }
01521    return (pri_plan2str(dialplan));
01522 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1349 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

01350 {
01351    if (isdigit(digit))
01352       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01353    else if (digit >= 'A' && digit <= 'D')
01354       return DAHDI_TONE_DTMF_A + (digit - 'A');
01355    else if (digit >= 'a' && digit <= 'd')
01356       return DAHDI_TONE_DTMF_A + (digit - 'a');
01357    else if (digit == '*')
01358       return DAHDI_TONE_DTMF_s;
01359    else if (digit == '#')
01360       return DAHDI_TONE_DTMF_p;
01361    else
01362       return -1;
01363 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 3520 of file chan_dahdi.c.

References ast_dsp_set_features(), dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_bridge().

03521 {
03522 #ifdef DAHDI_TONEDETECT
03523    int val;
03524 #endif
03525 
03526    p->ignoredtmf = 1;
03527 
03528 #ifdef DAHDI_TONEDETECT
03529    val = 0;
03530    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03531 #endif      
03532    if (!p->hardwaredtmf && p->dsp) {
03533       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
03534       ast_dsp_set_features(p->dsp, p->dsp_features);
03535    }
03536 }

static void* do_idle_thread ( void *  vchan  )  [static]

Definition at line 8647 of file chan_dahdi.c.

References ast_call(), AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, ast_copy_string(), AST_FRAME_CONTROL, ast_frfree, ast_hangup(), ast_log(), ast_pbx_run(), ast_read(), ast_verbose(), ast_waitfor(), dahdi_pvt::channel, ast_channel::context, ast_channel::exten, f, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, ast_channel::name, option_verbose, dahdi_pvt::pri, ast_channel::priority, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

Referenced by pri_dchannel().

08648 {
08649    struct ast_channel *chan = vchan;
08650    struct dahdi_pvt *pvt = chan->tech_pvt;
08651    struct ast_frame *f;
08652    char ex[80];
08653    /* Wait up to 30 seconds for an answer */
08654    int newms, ms = 30000;
08655    if (option_verbose > 2) 
08656       ast_verbose(VERBOSE_PREFIX_3 "Initiating idle call on channel %s\n", chan->name);
08657    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
08658    if (ast_call(chan, ex, 0)) {
08659       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
08660       ast_hangup(chan);
08661       return NULL;
08662    }
08663    while ((newms = ast_waitfor(chan, ms)) > 0) {
08664       f = ast_read(chan);
08665       if (!f) {
08666          /* Got hangup */
08667          break;
08668       }
08669       if (f->frametype == AST_FRAME_CONTROL) {
08670          switch (f->subclass) {
08671          case AST_CONTROL_ANSWER:
08672             /* Launch the PBX */
08673             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
08674             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
08675             chan->priority = 1;
08676             if (option_verbose > 3) 
08677                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
08678             ast_pbx_run(chan);
08679             /* It's already hungup, return immediately */
08680             return NULL;
08681          case AST_CONTROL_BUSY:
08682             if (option_verbose > 3) 
08683                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' busy, waiting...\n", chan->name);
08684             break;
08685          case AST_CONTROL_CONGESTION:
08686             if (option_verbose > 3) 
08687                ast_verbose(VERBOSE_PREFIX_3 "Idle channel '%s' congested, waiting...\n", chan->name);
08688             break;
08689          };
08690       }
08691       ast_frfree(f);
08692       ms = newms;
08693    }
08694    /* Hangup the channel since nothing happend */
08695    ast_hangup(chan);
08696    return NULL;
08697 }

static void* do_monitor ( void *  data  )  [static]

Definition at line 7272 of file chan_dahdi.c.

References ast_calloc, ast_log(), ast_mutex_lock, ast_mutex_unlock, dahdi_pvt::cidspill, free, iflist, iflock, last, LOG_DEBUG, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

07273 {
07274    int count, res, res2, spoint, pollres=0;
07275    struct dahdi_pvt *i;
07276    struct dahdi_pvt *last = NULL;
07277    time_t thispass = 0, lastpass = 0;
07278    int found;
07279    char buf[1024];
07280    struct pollfd *pfds=NULL;
07281    int lastalloc = -1;
07282    /* This thread monitors all the frame relay interfaces which are not yet in use
07283       (and thus do not have a separate thread) indefinitely */
07284    /* From here on out, we die whenever asked */
07285 #if 0
07286    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
07287       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
07288       return NULL;
07289    }
07290    ast_log(LOG_DEBUG, "Monitor starting...\n");
07291 #endif
07292    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07293 
07294    for (;;) {
07295       /* Lock the interface list */
07296       ast_mutex_lock(&iflock);
07297       if (!pfds || (lastalloc != ifcount)) {
07298          if (pfds) {
07299             free(pfds);
07300             pfds = NULL;
07301          }
07302          if (ifcount) {
07303             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
07304                ast_mutex_unlock(&iflock);
07305                return NULL;
07306             }
07307          }
07308          lastalloc = ifcount;
07309       }
07310       /* Build the stuff we're going to poll on, that is the socket of every
07311          dahdi_pvt that does not have an associated owner channel */
07312       count = 0;
07313       i = iflist;
07314       while (i) {
07315          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
07316             if (!i->owner && !i->subs[SUB_REAL].owner) {
07317                /* This needs to be watched, as it lacks an owner */
07318                pfds[count].fd = i->subs[SUB_REAL].dfd;
07319                pfds[count].events = POLLPRI;
07320                pfds[count].revents = 0;
07321                /* Message waiting or r2 channels also get watched for reading */
07322                if (i->cidspill)
07323                   pfds[count].events |= POLLIN;
07324                count++;
07325             }
07326          }
07327          i = i->next;
07328       }
07329       /* Okay, now that we know what to do, release the interface lock */
07330       ast_mutex_unlock(&iflock);
07331       
07332       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
07333       pthread_testcancel();
07334       /* Wait at least a second for something to happen */
07335       res = poll(pfds, count, 1000);
07336       pthread_testcancel();
07337       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
07338 
07339       /* Okay, poll has finished.  Let's see what happened.  */
07340       if (res < 0) {
07341          if ((errno != EAGAIN) && (errno != EINTR))
07342             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
07343          continue;
07344       }
07345       /* Alright, lock the interface list again, and let's look and see what has
07346          happened */
07347       ast_mutex_lock(&iflock);
07348       found = 0;
07349       spoint = 0;
07350       lastpass = thispass;
07351       thispass = time(NULL);
07352       i = iflist;
07353       while (i) {
07354          if (thispass != lastpass) {
07355             if (!found && ((i == last) || ((i == iflist) && !last))) {
07356                last = i;
07357                if (last) {
07358                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
07359                      (last->sig & __DAHDI_SIG_FXO)) {
07360                      res = ast_app_has_voicemail(last->mailbox, NULL);
07361                      if (last->msgstate != res) {
07362                         int x;
07363                         ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
07364                         x = DAHDI_FLUSH_BOTH;
07365                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07366                         if (res2)
07367                            ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", last->channel, strerror(errno));
07368                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
07369                            /* Turn on on hook transfer for 4 seconds */
07370                            x = 4000;
07371                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07372                            last->cidlen = ast_callerid_vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
07373                            last->cidpos = 0;
07374                            last->msgstate = res;
07375                            last->onhooktime = thispass;
07376                         }
07377                         found ++;
07378                      }
07379                   }
07380                   last = last->next;
07381                }
07382             }
07383          }
07384          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
07385             if (i->radio && !i->owner)
07386             {
07387                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07388                if (res)
07389                {
07390                   if (option_debug)
07391                      ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
07392                   /* Don't hold iflock while handling init events */
07393                   ast_mutex_unlock(&iflock);
07394                   handle_init_event(i, res);
07395                   ast_mutex_lock(&iflock);   
07396                }
07397                i = i->next;
07398                continue;
07399             }              
07400             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
07401             if (pollres & POLLIN) {
07402                if (i->owner || i->subs[SUB_REAL].owner) {
07403 #ifdef HAVE_PRI
07404                   if (!i->pri)
07405 #endif                  
07406                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
07407                   i = i->next;
07408                   continue;
07409                }
07410                if (!i->cidspill) {
07411                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
07412                   i = i->next;
07413                   continue;
07414                }
07415                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
07416                if (res > 0) {
07417                   /* We read some number of bytes.  Write an equal amount of data */
07418                   if (res > i->cidlen - i->cidpos) 
07419                      res = i->cidlen - i->cidpos;
07420                   res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
07421                   if (res2 > 0) {
07422                      i->cidpos += res2;
07423                      if (i->cidpos >= i->cidlen) {
07424                         free(i->cidspill);
07425                         i->cidspill = 0;
07426                         i->cidpos = 0;
07427                         i->cidlen = 0;
07428                      }
07429                   } else {
07430                      ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
07431                      i->msgstate = -1;
07432                   }
07433                } else {
07434                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
07435                }
07436             }
07437             if (pollres & POLLPRI) {
07438                if (i->owner || i->subs[SUB_REAL].owner) {
07439 #ifdef HAVE_PRI
07440                   if (!i->pri)
07441 #endif                  
07442                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
07443                   i = i->next;
07444                   continue;
07445                }
07446                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
07447                if (option_debug)
07448                   ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
07449                /* Don't hold iflock while handling init events */
07450                ast_mutex_unlock(&iflock);
07451                handle_init_event(i, res);
07452                ast_mutex_lock(&iflock);   
07453             }
07454          }
07455          i=i->next;
07456       }
07457       ast_mutex_unlock(&iflock);
07458    }
07459    /* Never reached */
07460    return NULL;
07461    
07462 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 3538 of file chan_dahdi.c.

References ast_dsp_set_features(), CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::dsp, DSP_FEATURE_DTMF_DETECT, dahdi_pvt::dsp_features, dahdi_pvt::hardwaredtmf, dahdi_pvt::ignoredtmf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_bridge().

03539 {
03540 #ifdef DAHDI_TONEDETECT
03541    int val;
03542 #endif
03543 
03544    if (p->channel == CHAN_PSEUDO)
03545       return;
03546 
03547    p->ignoredtmf = 0;
03548 
03549 #ifdef DAHDI_TONEDETECT
03550    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
03551    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
03552 #endif      
03553    if (!p->hardwaredtmf && p->dsp) {
03554       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
03555       ast_dsp_set_features(p->dsp, p->dsp_features);
03556    }
03557 }

static char* event2str ( int  event  )  [static]

Definition at line 1506 of file chan_dahdi.c.

Referenced by __dahdi_exception(), dahdi_handle_event(), and ss_thread().

01507 {
01508    static char buf[256];
01509    if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
01510       return events[event];
01511    sprintf(buf, "Event %d", event); /* safe */
01512    return buf;
01513 }

static void fill_rxgain ( struct dahdi_gains *  g,
float  gain,
int  law 
) [static]

Definition at line 1869 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

01870 {
01871    int j;
01872    int k;
01873    float linear_gain = pow(10.0, gain / 20.0);
01874 
01875    switch (law) {
01876    case DAHDI_LAW_ALAW:
01877       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01878          if (gain) {
01879             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01880             if (k > 32767) k = 32767;
01881             if (k < -32767) k = -32767;
01882             g->rxgain[j] = AST_LIN2A(k);
01883          } else {
01884             g->rxgain[j] = j;
01885          }
01886       }
01887       break;
01888    case DAHDI_LAW_MULAW:
01889       for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
01890          if (gain) {
01891             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01892             if (k > 32767) k = 32767;
01893             if (k < -32767) k = -32767;
01894             g->rxgain[j] = AST_LIN2MU(k);
01895          } else {
01896             g->rxgain[j] = j;
01897          }
01898       }
01899       break;
01900    }
01901 }

static void fill_txgain ( struct dahdi_gains *  g,
float  gain,
int  law 
) [static]

Definition at line 1835 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

01836 {
01837    int j;
01838    int k;
01839    float linear_gain = pow(10.0, gain / 20.0);
01840 
01841    switch (law) {
01842    case DAHDI_LAW_ALAW:
01843       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01844          if (gain) {
01845             k = (int) (((float) AST_ALAW(j)) * linear_gain);
01846             if (k > 32767) k = 32767;
01847             if (k < -32767) k = -32767;
01848             g->txgain[j] = AST_LIN2A(k);
01849          } else {
01850             g->txgain[j] = j;
01851          }
01852       }
01853       break;
01854    case DAHDI_LAW_MULAW:
01855       for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
01856          if (gain) {
01857             k = (int) (((float) AST_MULAW(j)) * linear_gain);
01858             if (k > 32767) k = 32767;
01859             if (k < -32767) k = -32767;
01860             g->txgain[j] = AST_LIN2MU(k);
01861          } else {
01862             g->txgain[j] = j;
01863          }
01864       }
01865       break;
01866    }
01867 }

static struct dahdi_pvt* find_channel ( int  channel  )  [static]

Definition at line 10953 of file chan_dahdi.c.

References dahdi_pvt::channel, iflist, and dahdi_pvt::next.

Referenced by __action_dialoffhook(), __action_dnd(), __action_transfer(), and __action_transferhangup().

10954 {
10955    struct dahdi_pvt *p = iflist;
10956    while (p) {
10957       if (p->channel == channel) {
10958          break;
10959       }
10960       p = p->next;
10961    }
10962    return p;
10963 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3980 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, errno, dahdi_pvt::span, SUB_REAL, and dahdi_pvt::subs.

Referenced by __action_showchannels(), dahdi_handle_event(), and handle_init_event().

03981 {
03982    int res;
03983    struct dahdi_spaninfo zi;
03984 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
03985    /*
03986     * The conditional compilation is needed only in asterisk-1.4 for
03987     * backward compatibility with old zaptel drivers that don't have
03988     * a DAHDI_PARAMS.chan_alarms field.
03989     */
03990    struct dahdi_params params;
03991 #endif
03992 
03993    memset(&zi, 0, sizeof(zi));
03994    zi.spanno = p->span;
03995 
03996    /* First check for span alarms */
03997    if((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) < 0) {
03998       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
03999       return 0;
04000    }
04001    if (zi.alarms != DAHDI_ALARM_NONE)
04002       return zi.alarms;
04003 #if !defined(HAVE_ZAPTEL) || defined(HAVE_ZAPTEL_CHANALARMS)
04004    /* No alarms on the span. Check for channel alarms. */
04005    memset(&params, 0, sizeof(params));
04006    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04007       return params.chan_alarms;
04008    /* ioctl failed */
04009    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04010 #endif
04011    return DAHDI_ALARM_NONE;
04012 }

static void handle_alarms ( struct dahdi_pvt p,
int  alarms 
) [static]

Definition at line 4096 of file chan_dahdi.c.

References alarm2str(), ast_log(), dahdi_pvt::channel, EVENT_FLAG_SYSTEM, manager_event(), and dahdi_pvt::unknown_alarm.

Referenced by dahdi_handle_event(), and handle_init_event().

04097 {
04098    const char *alarm_str = alarm2str(alarms);
04099    
04100    /* hack alert! Zaptel 1.4 and DAHDI expose FXO battery as an alarm, but this code
04101     * doesn't know what to do with it.  Don't confuse users with log messages. */
04102    if (!strcasecmp(alarm_str, "No Alarm") || !strcasecmp(alarm_str, "Unknown Alarm")) {
04103       p->unknown_alarm = 1;
04104       return;
04105    } else {
04106       p->unknown_alarm = 0;
04107    }
04108    
04109    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04110    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04111             "Alarm: %s\r\n"
04112             "Channel: %d\r\n",
04113             alarm_str, p->channel);
04114 }

static int handle_dahdi_show_cadences ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10768 of file chan_dahdi.c.

References ast_cli(), COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, and term_color().

10769 {
10770    int i, j;
10771    for (i = 0; i < num_cadence; i++) {
10772       char output[1024];
10773       char tmp[16], tmp2[64];
10774       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10775       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10776 
10777       for (j = 0; j < 16; j++) {
10778          if (cadences[i].ringcadence[j] == 0)
10779             break;
10780          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10781          if (cidrings[i] * 2 - 1 == j)
10782             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10783          else
10784             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10785          if (j != 0)
10786             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10787          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10788       }
10789       ast_cli(fd,"%s\n",output);
10790    }
10791    return 0;
10792 }

static int handle_init_event ( struct dahdi_pvt i,
int  event 
) [static]

Definition at line 7064 of file chan_dahdi.c.

References ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verbose(), dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, EVENT_FLAG_SYSTEM, free, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, manager_event(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, ss_thread(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::unknown_alarm, and VERBOSE_PREFIX_2.

07065 {
07066    int res;
07067    pthread_t threadid;
07068    pthread_attr_t attr;
07069    struct ast_channel *chan;
07070    pthread_attr_init(&attr);
07071    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07072    /* Handle an event on a given channel for the monitor thread. */
07073    switch (event) {
07074    case DAHDI_EVENT_NONE:
07075    case DAHDI_EVENT_BITSCHANGED:
07076       break;
07077    case DAHDI_EVENT_WINKFLASH:
07078    case DAHDI_EVENT_RINGOFFHOOK:
07079       if (i->inalarm) break;
07080       if (i->radio) break;
07081       /* Got a ring/answer.  What kind of channel are we? */
07082       switch (i->sig) {
07083       case SIG_FXOLS:
07084       case SIG_FXOGS:
07085       case SIG_FXOKS:
07086          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07087          if (res && (errno == EBUSY))
07088             break;
07089          if (i->cidspill) {
07090             /* Cancel VMWI spill */
07091             free(i->cidspill);
07092             i->cidspill = NULL;
07093          }
07094          if (i->immediate) {
07095             dahdi_enable_ec(i);
07096             /* The channel is immediately up.  Start right away */
07097             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07098             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07099             if (!chan) {
07100                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07101                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07102                if (res < 0)
07103                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07104             }
07105          } else {
07106             /* Check for callerid, digits, etc */
07107             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07108             if (chan) {
07109                if (has_voicemail(i))
07110                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07111                else
07112                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07113                if (res < 0) 
07114                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07115                if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07116                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07117                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07118                   if (res < 0)
07119                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07120                   ast_hangup(chan);
07121                }
07122             } else
07123                ast_log(LOG_WARNING, "Unable to create channel\n");
07124          }
07125          break;
07126       case SIG_FXSLS:
07127       case SIG_FXSGS:
07128       case SIG_FXSKS:
07129             i->ringt = i->ringt_base;
07130             /* Fall through */
07131       case SIG_EMWINK:
07132       case SIG_FEATD:
07133       case SIG_FEATDMF:
07134       case SIG_FEATDMF_TA:
07135       case SIG_E911:
07136       case SIG_FGC_CAMA:
07137       case SIG_FGC_CAMAMF:
07138       case SIG_FEATB:
07139       case SIG_EM:
07140       case SIG_EM_E1:
07141       case SIG_SFWINK:
07142       case SIG_SF_FEATD:
07143       case SIG_SF_FEATDMF:
07144       case SIG_SF_FEATB:
07145       case SIG_SF:
07146             /* Check for callerid, digits, etc */
07147             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
07148             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07149                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07150                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07151                if (res < 0)
07152                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07153                ast_hangup(chan);
07154             } else if (!chan) {
07155                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
07156             }
07157             break;
07158       default:
07159          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07160          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07161          if (res < 0)
07162                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07163          return -1;
07164       }
07165       break;
07166    case DAHDI_EVENT_NOALARM:
07167       i->inalarm = 0;
07168       if (!i->unknown_alarm) {
07169          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
07170          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07171                   "Channel: %d\r\n", i->channel);
07172       } else {
07173          i->unknown_alarm = 0;
07174       }
07175       break;
07176    case DAHDI_EVENT_ALARM:
07177       i->inalarm = 1;
07178       res = get_alarms(i);
07179       handle_alarms(i, res);
07180       /* fall thru intentionally */
07181    case DAHDI_EVENT_ONHOOK:
07182       if (i->radio)
07183          break;
07184       /* Back on hook.  Hang up. */
07185       switch (i->sig) {
07186       case SIG_FXOLS:
07187       case SIG_FXOGS:
07188       case SIG_FEATD:
07189       case SIG_FEATDMF:
07190       case SIG_FEATDMF_TA:
07191       case SIG_E911:
07192       case SIG_FGC_CAMA:
07193       case SIG_FGC_CAMAMF:
07194       case SIG_FEATB:
07195       case SIG_EM:
07196       case SIG_EM_E1:
07197       case SIG_EMWINK:
07198       case SIG_SF_FEATD:
07199       case SIG_SF_FEATDMF:
07200       case SIG_SF_FEATB:
07201       case SIG_SF:
07202       case SIG_SFWINK:
07203       case SIG_FXSLS:
07204       case SIG_FXSGS:
07205       case SIG_FXSKS:
07206       case SIG_GR303FXSKS:
07207          dahdi_disable_ec(i);
07208          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07209          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07210          break;
07211       case SIG_GR303FXOKS:
07212       case SIG_FXOKS:
07213          dahdi_disable_ec(i);
07214          /* Diddle the battery for the zhone */
07215 #ifdef ZHONE_HACK
07216          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07217          usleep(1);
07218 #endif         
07219          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07220          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07221          break;
07222       case SIG_PRI:
07223          dahdi_disable_ec(i);
07224          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07225          break;
07226       default:
07227          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07228          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
07229          return -1;
07230       }
07231       break;
07232    case DAHDI_EVENT_POLARITY:
07233       switch (i->sig) {
07234       case SIG_FXSLS:
07235       case SIG_FXSKS:
07236       case SIG_FXSGS:
07237          /* We have already got a PR before the channel was 
07238             created, but it wasn't handled. We need polarity 
07239             to be REV for remote hangup detection to work. 
07240             At least in Spain */
07241          if (i->hanguponpolarityswitch)
07242             i->polarity = POLARITY_REV;
07243 
07244          if (i->cid_start == CID_START_POLARITY) {
07245             i->polarity = POLARITY_REV;
07246             ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
07247                    "CID detection on channel %d\n",
07248                    i->channel);
07249             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
07250             if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
07251                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07252             }
07253          }
07254          break;
07255       default:
07256          ast_log(LOG_WARNING, "handle_init_event detected "
07257             "polarity reversal on non-FXO (SIG_FXS) "
07258             "interface %d\n", i->channel);
07259       }
07260       break;
07261    case DAHDI_EVENT_REMOVED: /* destroy channel */
07262       ast_log(LOG_NOTICE, 
07263             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
07264             i->channel);
07265       dahdi_destroy_channel_bynum(i->channel);
07266       break;
07267    }
07268    pthread_attr_destroy(&attr);
07269    return 0;
07270 }

static int handle_pri_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10162 of file chan_dahdi.c.

References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10163 {
10164    int span;
10165    int x;
10166    if (argc < 4) {
10167       return RESULT_SHOWUSAGE;
10168    }
10169    span = atoi(argv[3]);
10170    if ((span < 1) || (span > NUM_SPANS)) {
10171       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
10172       return RESULT_SUCCESS;
10173    }
10174    if (!pris[span-1].pri) {
10175       ast_cli(fd, "No PRI running on span %d\n", span);
10176       return RESULT_SUCCESS;
10177    }
10178    for (x = 0; x < NUM_DCHANS; x++) {
10179       if (pris[span-1].dchans[x])
10180          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10181                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10182                                                PRI_DEBUG_Q921_STATE);
10183    }
10184    ast_cli(fd, "Enabled debugging on span %d\n", span);
10185    return RESULT_SUCCESS;
10186 }

static int handle_pri_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10190 of file chan_dahdi.c.

References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10191 {
10192    int span;
10193    int x;
10194    if (argc < 5)
10195       return RESULT_SHOWUSAGE;
10196    span = atoi(argv[4]);
10197    if ((span < 1) || (span > NUM_SPANS)) {
10198       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10199       return RESULT_SUCCESS;
10200    }
10201    if (!pris[span-1].pri) {
10202       ast_cli(fd, "No PRI running on span %d\n", span);
10203       return RESULT_SUCCESS;
10204    }
10205    for (x = 0; x < NUM_DCHANS; x++) {
10206       if (pris[span-1].dchans[x])
10207          pri_set_debug(pris[span-1].dchans[x], 0);
10208    }
10209    ast_cli(fd, "Disabled debugging on span %d\n", span);
10210    return RESULT_SUCCESS;
10211 }

static int handle_pri_really_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10213 of file chan_dahdi.c.

References ast_cli(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10214 {
10215    int span;
10216    int x;
10217    if (argc < 5)
10218       return RESULT_SHOWUSAGE;
10219    span = atoi(argv[4]);
10220    if ((span < 1) || (span > NUM_SPANS)) {
10221       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[4], 1, NUM_SPANS);
10222       return RESULT_SUCCESS;
10223    }
10224    if (!pris[span-1].pri) {
10225       ast_cli(fd, "No PRI running on span %d\n", span);
10226       return RESULT_SUCCESS;
10227    }
10228    for (x = 0; x < NUM_DCHANS; x++) {
10229       if (pris[span-1].dchans[x])
10230          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10231                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10232                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
10233    }
10234    ast_cli(fd, "Enabled EXTENSIVE debugging on span %d\n", span);
10235    return RESULT_SUCCESS;
10236 }

static int handle_pri_set_debug_file ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 10115 of file chan_dahdi.c.

References ast_cli(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), pridebugfdlock, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10116 {
10117    int myfd;
10118 
10119    if (!strncasecmp(argv[1], "set", 3)) {
10120       if (argc < 5) 
10121          return RESULT_SHOWUSAGE;
10122 
10123       if (ast_strlen_zero(argv[4]))
10124          return RESULT_SHOWUSAGE;
10125 
10126       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
10127       if (myfd < 0) {
10128          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
10129          return RESULT_SUCCESS;
10130       }
10131 
10132       ast_mutex_lock(&pridebugfdlock);
10133 
10134       if (pridebugfd >= 0)
10135          close(pridebugfd);
10136 
10137       pridebugfd = myfd;
10138       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
10139       
10140       ast_mutex_unlock(&pridebugfdlock);
10141 
10142       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
10143    } else {
10144       /* Assume it is unset */
10145       ast_mutex_lock(&pridebugfdlock);
10146       close(pridebugfd);
10147       pridebugfd = -1;
10148       ast_cli(fd, "PRI debug output to file disabled\n");
10149       ast_mutex_unlock(&pridebugfdlock);
10150    }
10151 
10152    return RESULT_SUCCESS;
10153 }

static int handle_pri_show_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10319 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock, ast_mutex_unlock, debug, NUM_SPANS, pridebugfdlock, pris, and RESULT_SUCCESS.

10320 {
10321    int x;
10322    int span;
10323    int count=0;
10324    int debug=0;
10325 
10326    for (span = 0; span < NUM_SPANS; span++) {
10327            if (pris[span].pri) {
10328          for (x = 0; x < NUM_DCHANS; x++) {
10329             debug = 0;
10330                if (pris[span].dchans[x]) {
10331                   debug = pri_get_debug(pris[span].dchans[x]);
10332                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" );
10333                count++;
10334             }
10335          }
10336       }
10337 
10338    }
10339    ast_mutex_lock(&pridebugfdlock);
10340    if (pridebugfd >= 0) 
10341       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
10342    ast_mutex_unlock(&pridebugfdlock);
10343        
10344    if (!count) 
10345       ast_cli(fd, "No debug set or no PRI running\n");
10346    return RESULT_SUCCESS;
10347 }

static int handle_pri_show_span ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10280 of file chan_dahdi.c.

References ast_cli(), build_status(), free, NUM_SPANS, pri_order(), pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10281 {
10282    int span;
10283    int x;
10284    char status[256];
10285    if (argc < 4)
10286       return RESULT_SHOWUSAGE;
10287    span = atoi(argv[3]);
10288    if ((span < 1) || (span > NUM_SPANS)) {
10289       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
10290       return RESULT_SUCCESS;
10291    }
10292    if (!pris[span-1].pri) {
10293       ast_cli(fd, "No PRI running on span %d\n", span);
10294       return RESULT_SUCCESS;
10295    }
10296    for (x = 0; x < NUM_DCHANS; x++) {
10297       if (pris[span-1].dchannels[x]) {
10298 #ifdef PRI_DUMP_INFO_STR
10299          char *info_str = NULL;
10300 #endif
10301          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
10302          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
10303          ast_cli(fd, "Status: %s\n", status);
10304 #ifdef PRI_DUMP_INFO_STR
10305          info_str = pri_dump_info_str(pris[span-1].pri);
10306          if (info_str) {
10307             ast_cli(fd, "%s", info_str);
10308             free(info_str);
10309          }
10310 #else
10311          pri_dump_info(pris[span-1].pri);
10312 #endif
10313          ast_cli(fd, "\n");
10314       }
10315    }
10316    return RESULT_SUCCESS;
10317 }

static int handle_pri_show_spans ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 10259 of file chan_dahdi.c.

References ast_cli(), build_status(), NUM_SPANS, pris, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

10260 {
10261    int span;
10262    int x;
10263    char status[256];
10264    if (argc != 3)
10265       return RESULT_SHOWUSAGE;
10266 
10267    for (span = 0; span < NUM_SPANS; span++) {
10268       if (pris[span].pri) {
10269          for (x = 0; x < NUM_DCHANS; x++) {
10270             if (pris[span].dchannels[x]) {
10271                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
10272                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
10273             }
10274          }
10275       }
10276    }
10277    return RESULT_SUCCESS;
10278 }

static int handle_pri_version ( int  fd,
int  agc,
char *  argv[] 
) [static]

Definition at line 10156 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

10156                                                              {
10157    ast_cli(fd, "libpri version: %s\n", pri_get_version());
10158    return RESULT_SUCCESS;
10159 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 2066 of file chan_dahdi.c.

References ast_app_has_voicemail(), and dahdi_pvt::mailbox.

Referenced by dahdi_handle_event(), do_monitor(), handle_hd_hf(), handle_init_event(), handle_request(), load_module(), mgcp_hangup(), mgcp_request(), and vm_execmain().

02067 {
02068 
02069    return ast_app_has_voicemail(p->mailbox, NULL);
02070 }

static int isourconf ( struct dahdi_pvt p,
struct dahdi_subchannel c 
) [static]

Definition at line 1625 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pvt::confno, and dahdi_subchannel::curconf.

Referenced by conf_del().

01626 {
01627    /* If they're listening to our channel, they're ours */  
01628    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01629       return 1;
01630    /* If they're a talker on our (allocated) conference, they're ours */
01631    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01632       return 1;
01633    return 0;
01634 }

static int isslavenative ( struct dahdi_pvt p,
struct dahdi_pvt **  out 
) [static]

Definition at line 1655 of file chan_dahdi.c.

References dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, MAX_SLAVES, dahdi_pvt::slaves, and dahdi_pvt::subs.

Referenced by update_conf().

01656 {
01657    int x;
01658    int useslavenative;
01659    struct dahdi_pvt *slave = NULL;
01660    /* Start out optimistic */
01661    useslavenative = 1;
01662    /* Update conference state in a stateless fashion */
01663    for (x = 0; x < 3; x++) {
01664       /* Any three-way calling makes slave native mode *definitely* out
01665          of the question */
01666       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01667          useslavenative = 0;
01668    }
01669    /* If we don't have any 3-way calls, check to see if we have
01670       precisely one slave */
01671    if (useslavenative) {
01672       for (x = 0; x < MAX_SLAVES; x++) {
01673          if (p->slaves[x]) {
01674             if (slave) {
01675                /* Whoops already have a slave!  No 
01676                   slave native and stop right away */
01677                slave = NULL;
01678                useslavenative = 0;
01679                break;
01680             } else {
01681                /* We have one slave so far */
01682                slave = p->slaves[x];
01683             }
01684          }
01685       }
01686    }
01687    /* If no slave, slave native definitely out */
01688    if (!slave)
01689       useslavenative = 0;
01690    else if (slave->law != p->law) {
01691       useslavenative = 0;
01692       slave = NULL;
01693    }
01694    if (out)
01695       *out = slave;
01696    return useslavenative;
01697 }

static int load_module ( void   )  [static]

Definition at line 12218 of file chan_dahdi.c.

References __unload_module(), ast_channel_register(), ast_cli_register_multiple(), ast_cond_init, ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_init, AST_PTHREADT_NULL, ast_register_application(), ast_string_field_init, ast_string_field_set, CHAN_DAHDI_PLUS_ZAP_MODE, chan_tech, dahdi_chan_mode, dahdi_cli, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_tech, inuse, local_astman_register, lock, LOG_ERROR, name, NUM_SPANS, pris, round_robin, setup_dahdi(), ast_channel_tech::type, zap_send_keypad_facility_exec(), and zap_tech.

12219 {
12220    int res;
12221 
12222 #ifdef HAVE_PRI
12223    int y,i;
12224    memset(pris, 0, sizeof(pris));
12225    for (y = 0; y < NUM_SPANS; y++) {
12226       ast_mutex_init(&pris[y].lock);
12227       pris[y].offset = -1;
12228       pris[y].master = AST_PTHREADT_NULL;
12229       for (i = 0; i < NUM_DCHANS; i++)
12230          pris[y].fds[i] = -1;
12231    }
12232    pri_set_error(dahdi_pri_error);
12233    pri_set_message(dahdi_pri_message);
12234    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12235       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
12236          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
12237    }
12238    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
12239       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
12240 #endif
12241    if ((res = setup_dahdi(0))) {
12242       return AST_MODULE_LOAD_DECLINE;
12243    }
12244    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12245       chan_tech = &dahdi_tech;
12246    } else {
12247       chan_tech = &zap_tech;
12248    }
12249    if (ast_channel_register(chan_tech)) {
12250       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
12251       __unload_module();
12252       return -1;
12253    }
12254 #ifdef HAVE_PRI
12255    ast_string_field_init(&inuse, 16);
12256    ast_string_field_set(&inuse, name, "GR-303InUse");
12257    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12258 #endif   
12259    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12260    
12261    memset(round_robin, 0, sizeof(round_robin));
12262    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
12263    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
12264    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
12265    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
12266    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
12267    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
12268    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
12269 
12270    ast_cond_init(&ss_thread_complete, NULL);
12271 
12272    return res;
12273 }

static struct dahdi_pvt* mkintf ( int  channel,
const struct dahdi_chan_conf conf,
struct dahdi_pri pri,
int  reloading 
) [static]

Definition at line 7618 of file chan_dahdi.c.

References ast_calloc, ast_copy_string(), ast_log(), ast_mutex_init, ast_strlen_zero(), dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), destroy_dahdi_pvt(), dahdi_pri::dialplan, dialplan2str(), errno, dahdi_pri::facilityenable, free, dahdi_pri::idledial, dahdi_pri::idleext, iflist, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, MAX_CHANNELS, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pri::nationalprefix, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, NUM_SPANS, dahdi_pri::numchans, offset, dahdi_pri::overlapdial, dahdi_pvt::prev, dahdi_chan_conf::pri, pri_resolve_span(), dahdi_pri::prilogicalspan, pris, dahdi_pri::privateprefix, dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pvt::sig, sig2str, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SUB_REAL, dahdi_pri::switchtype, and dahdi_pri::unknownprefix.

Referenced by build_channels().

07619 {
07620    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
07621    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
07622    char fn[80];
07623 #if 1
07624    struct dahdi_bufferinfo bi;
07625 #endif
07626    int res;
07627    int span=0;
07628    int here = 0;
07629    int x;
07630    struct dahdi_pvt **wlist;
07631    struct dahdi_pvt **wend;
07632    struct dahdi_params p;
07633 
07634    wlist = &iflist;
07635    wend = &ifend;
07636 
07637 #ifdef HAVE_PRI
07638    if (pri) {
07639       wlist = &pri->crvs;
07640       wend = &pri->crvend;
07641    }
07642 #endif
07643 
07644    tmp2 = *wlist;
07645    prev = NULL;
07646 
07647    while (tmp2) {
07648       if (!tmp2->destroy) {
07649          if (tmp2->channel == channel) {
07650             tmp = tmp2;
07651             here = 1;
07652             break;
07653          }
07654          if (tmp2->channel > channel) {
07655             break;
07656          }
07657       }
07658       prev = tmp2;
07659       tmp2 = tmp2->next;
07660    }
07661 
07662    if (!here && reloading != 1) {
07663       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
07664          if (tmp)
07665             free(tmp);
07666          return NULL;
07667       }
07668       ast_mutex_init(&tmp->lock);
07669       ifcount++;
07670       for (x = 0; x < 3; x++)
07671          tmp->subs[x].dfd = -1;
07672       tmp->channel = channel;
07673    }
07674 
07675    if (tmp) {
07676       int chan_sig = conf->chan.sig;
07677       if (!here) {
07678          if ((channel != CHAN_PSEUDO) && !pri) {
07679             int count = 0;
07680             snprintf(fn, sizeof(fn), "%d", channel);
07681             /* Open non-blocking */
07682             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07683             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 */
07684                usleep(1);
07685                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
07686                count++;
07687             }
07688             /* Allocate a DAHDI structure */
07689             if (tmp->subs[SUB_REAL].dfd < 0) {
07690                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);
07691                destroy_dahdi_pvt(&tmp);
07692                return NULL;
07693             }
07694             memset(&p, 0, sizeof(p));
07695             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07696             if (res < 0) {
07697                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
07698                destroy_dahdi_pvt(&tmp);
07699                return NULL;
07700             }
07701             if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
07702                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));
07703                destroy_dahdi_pvt(&tmp);
07704                return NULL;
07705             }
07706             tmp->law = p.curlaw;
07707             tmp->span = p.spanno;
07708             span = p.spanno - 1;
07709          } else {
07710             if (channel == CHAN_PSEUDO)
07711                chan_sig = 0;
07712             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
07713                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
07714                return NULL;
07715             }
07716          }
07717 #ifdef HAVE_PRI
07718          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
07719             int offset;
07720             int myswitchtype;
07721             int matchesdchan;
07722             int x,y;
07723             offset = 0;
07724             if ((chan_sig == SIG_PRI) && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
07725                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
07726                destroy_dahdi_pvt(&tmp);
07727                return NULL;
07728             }
07729             if (span >= NUM_SPANS) {
07730                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
07731                destroy_dahdi_pvt(&tmp);
07732                return NULL;
07733             } else {
07734                struct dahdi_spaninfo si;
07735                si.spanno = 0;
07736                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
07737                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
07738                   destroy_dahdi_pvt(&tmp);
07739                   return NULL;
07740                }
07741                /* Store the logical span first based upon the real span */
07742                tmp->logicalspan = pris[span].prilogicalspan;
07743                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
07744                if (span < 0) {
07745                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
07746                   destroy_dahdi_pvt(&tmp);
07747                   return NULL;
07748                }
07749                if (chan_sig == SIG_PRI)
07750                   myswitchtype = conf->pri.switchtype;
07751                else
07752                   myswitchtype = PRI_SWITCH_GR303_TMC;
07753                /* Make sure this isn't a d-channel */
07754                matchesdchan=0;
07755                for (x = 0; x < NUM_SPANS; x++) {
07756                   for (y = 0; y < NUM_DCHANS; y++) {
07757                      if (pris[x].dchannels[y] == tmp->channel) {
07758                         matchesdchan = 1;
07759                         break;
07760                      }
07761                   }
07762                }
07763                offset = p.chanpos;
07764                if (!matchesdchan) {
07765                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
07766                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
07767                      destroy_dahdi_pvt(&tmp);
07768                      return NULL;
07769                   }
07770                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
07771                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
07772                      destroy_dahdi_pvt(&tmp);
07773                      return NULL;
07774                   }
07775                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
07776                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
07777                      destroy_dahdi_pvt(&tmp);
07778                      return NULL;
07779                   }
07780                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
07781                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
07782                      destroy_dahdi_pvt(&tmp);
07783                      return NULL;
07784                   }
07785                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
07786                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
07787                      destroy_dahdi_pvt(&tmp);
07788                      return NULL;
07789                   }
07790                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
07791                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
07792                      destroy_dahdi_pvt(&tmp);
07793                      return NULL;
07794                   }
07795                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
07796                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
07797                      destroy_dahdi_pvt(&tmp);
07798                      return NULL;
07799                   }
07800                   if (pris[span].numchans >= MAX_CHANNELS) {
07801                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
07802                         pris[span].trunkgroup);
07803                      destroy_dahdi_pvt(&tmp);
07804                      return NULL;
07805                   }
07806                   pris[span].nodetype = conf->pri.nodetype;
07807                   pris[span].switchtype = myswitchtype;
07808                   pris[span].nsf = conf->pri.nsf;
07809                   pris[span].dialplan = conf->pri.dialplan;
07810                   pris[span].localdialplan = conf->pri.localdialplan;
07811                   pris[span].pvts[pris[span].numchans++] = tmp;
07812                   pris[span].minunused = conf->pri.minunused;
07813                   pris[span].minidle = conf->pri.minidle;
07814                   pris[span].overlapdial = conf->pri.overlapdial;
07815 #ifdef HAVE_PRI_INBANDDISCONNECT
07816                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
07817 #endif
07818                   pris[span].facilityenable = conf->pri.facilityenable;
07819                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
07820                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
07821                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
07822                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
07823                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
07824                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
07825                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
07826                   pris[span].resetinterval = conf->pri.resetinterval;
07827                   
07828                   tmp->pri = &pris[span];
07829                   tmp->prioffset = offset;
07830                   tmp->call = NULL;
07831                } else {
07832                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
07833                   destroy_dahdi_pvt(&tmp);
07834                   return NULL;
07835                }
07836             }
07837          } else {
07838             tmp->prioffset = 0;
07839          }
07840 #endif
07841       } else {
07842          chan_sig = tmp->sig;
07843          if (tmp->subs[SUB_REAL].dfd > -1) {
07844             memset(&p, 0, sizeof(p));
07845             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
07846          }
07847       }
07848       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
07849       switch (chan_sig) {
07850       case SIG_FXSKS:
07851       case SIG_FXSLS:
07852       case SIG_EM:
07853       case SIG_EM_E1:
07854       case SIG_EMWINK:
07855       case SIG_FEATD:
07856       case SIG_FEATDMF:
07857       case SIG_FEATDMF_TA:
07858       case SIG_FEATB:
07859       case SIG_E911:
07860       case SIG_SF:
07861       case SIG_SFWINK:
07862       case SIG_FGC_CAMA:
07863       case SIG_FGC_CAMAMF:
07864       case SIG_SF_FEATD:
07865       case SIG_SF_FEATDMF:
07866       case SIG_SF_FEATB:
07867          p.starttime = 250;
07868          break;
07869       }
07870 
07871       if (tmp->radio) {
07872          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
07873          p.channo = channel;
07874          p.rxwinktime = 1;
07875          p.rxflashtime = 1;
07876          p.starttime = 1;
07877          p.debouncetime = 5;
07878       }
07879       if (!tmp->radio) {
07880          p.channo = channel;
07881          /* Override timing settings based on config file */
07882          if (conf->timing.prewinktime >= 0)
07883             p.prewinktime = conf->timing.prewinktime;
07884          if (conf->timing.preflashtime >= 0)
07885             p.preflashtime = conf->timing.preflashtime;
07886          if (conf->timing.winktime >= 0)
07887             p.winktime = conf->timing.winktime;
07888          if (conf->timing.flashtime >= 0)
07889             p.flashtime = conf->timing.flashtime;
07890          if (conf->timing.starttime >= 0)
07891             p.starttime = conf->timing.starttime;
07892          if (conf->timing.rxwinktime >= 0)
07893             p.rxwinktime = conf->timing.rxwinktime;
07894          if (conf->timing.rxflashtime >= 0)
07895             p.rxflashtime = conf->timing.rxflashtime;
07896          if (conf->timing.debouncetime >= 0)
07897             p.debouncetime = conf->timing.debouncetime;
07898       }
07899       
07900       /* dont set parms on a pseudo-channel (or CRV) */
07901       if (tmp->subs[SUB_REAL].dfd >= 0)
07902       {
07903          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
07904          if (res < 0) {
07905             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
07906             destroy_dahdi_pvt(&tmp);
07907             return NULL;
07908          }
07909       }
07910 #if 1
07911       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
07912          memset(&bi, 0, sizeof(bi));
07913          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
07914          if (!res) {
07915             bi.txbufpolicy = conf->chan.buf_policy;
07916             bi.rxbufpolicy = conf->chan.buf_policy;
07917             bi.numbufs = conf->chan.buf_no;
07918             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
07919             if (res < 0) {
07920                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
07921             }
07922          } else
07923             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
07924       }
07925 #endif
07926       tmp->immediate = conf->chan.immediate;
07927       tmp->transfertobusy = conf->chan.transfertobusy;
07928       tmp->sig = chan_sig;
07929       tmp->outsigmod = conf->chan.outsigmod;
07930       tmp->ringt_base = ringt_base;
07931       tmp->firstradio = 0;
07932       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
07933          tmp->permcallwaiting = conf->chan.callwaiting;
07934       else
07935          tmp->permcallwaiting = 0;
07936       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
07937       tmp->destroy = 0;
07938       tmp->drings = drings;
07939       tmp->usedistinctiveringdetection = conf->chan.usedistinctiveringdetection;
07940       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
07941       tmp->threewaycalling = conf->chan.threewaycalling;
07942       tmp->adsi = conf->chan.adsi;
07943       tmp->use_smdi = conf->chan.use_smdi;
07944       tmp->permhidecallerid = conf->chan.hidecallerid;
07945       tmp->callreturn = conf->chan.callreturn;
07946       tmp->echocancel = conf->chan.echocancel;
07947       tmp->echotraining = conf->chan.echotraining;
07948       tmp->pulse = conf->chan.pulse;
07949       if (tmp->echocancel)
07950          tmp->echocanbridged = conf->chan.echocanbridged;
07951       else {
07952          if (conf->chan.echocanbridged)
07953             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
07954          tmp->echocanbridged = 0;
07955       }
07956       tmp->busydetect = conf->chan.busydetect;
07957       tmp->busycount = conf->chan.busycount;
07958       tmp->busycompare = conf->chan.busycompare;
07959       tmp->busytonelength = conf->chan.busytonelength;
07960       tmp->busyquietlength = conf->chan.busyquietlength;
07961       tmp->busyfuzziness = conf->chan.busyfuzziness;
07962       tmp->silencethreshold = conf->chan.silencethreshold;
07963       tmp->callprogress = conf->chan.callprogress;
07964       tmp->cancallforward = conf->chan.cancallforward;
07965       tmp->dtmfrelax = conf->chan.dtmfrelax;
07966       tmp->callwaiting = tmp->permcallwaiting;
07967       tmp->hidecallerid = tmp->permhidecallerid;
07968       tmp->channel = channel;
07969       tmp->stripmsd = conf->chan.stripmsd;
07970       tmp->use_callerid = conf->chan.use_callerid;
07971       tmp->cid_signalling = conf->chan.cid_signalling;
07972       tmp->cid_start = conf->chan.cid_start;
07973       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
07974       tmp->restrictcid = conf->chan.restrictcid;
07975       tmp->use_callingpres = conf->chan.use_callingpres;
07976       tmp->priindication_oob = conf->chan.priindication_oob;
07977       tmp->priexclusive = conf->chan.priexclusive;
07978       if (tmp->usedistinctiveringdetection) {
07979          if (!tmp->use_callerid) {
07980             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
07981             tmp->use_callerid = 1;
07982          }
07983       }
07984 
07985       if (tmp->cid_signalling == CID_SIG_SMDI) {
07986          if (!tmp->use_smdi) {
07987             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
07988             tmp->use_smdi = 1;
07989          }
07990       }
07991       if (tmp->use_smdi) {
07992          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
07993          if (!(tmp->smdi_iface)) {
07994             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
07995             tmp->use_smdi = 0;
07996          }
07997       }
07998 
07999       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
08000       tmp->amaflags = conf->chan.amaflags;
08001       if (!here) {
08002          tmp->confno = -1;
08003          tmp->propconfno = -1;
08004       }
08005       tmp->canpark = conf->chan.canpark;
08006       tmp->transfer = conf->chan.transfer;
08007       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08008       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08009       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08010       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08011       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08012       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08013       tmp->cid_ton = 0;
08014       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08015       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08016       tmp->msgstate = -1;
08017       tmp->group = conf->chan.group;
08018       tmp->callgroup = conf->chan.callgroup;
08019       tmp->pickupgroup= conf->chan.pickupgroup;
08020       tmp->rxgain = conf->chan.rxgain;
08021       tmp->txgain = conf->chan.txgain;
08022       tmp->tonezone = conf->chan.tonezone;
08023       tmp->onhooktime = time(NULL);
08024       if (tmp->subs[SUB_REAL].dfd > -1) {
08025          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
08026          if (tmp->dsp)
08027             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
08028          update_conf(tmp);
08029          if (!here) {
08030             if (chan_sig != SIG_PRI)
08031                /* Hang it up to be sure it's good */
08032                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08033          }
08034          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
08035 #ifdef HAVE_PRI
08036          /* the dchannel is down so put the channel in alarm */
08037          if (tmp->pri && !pri_is_up(tmp->pri)) {
08038             tmp->inalarm = 1;
08039          }
08040 #endif            
08041          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
08042             tmp->inalarm = 1;
08043             handle_alarms(tmp, res);
08044          } else {
08045             /* yes, this looks strange... the unknown_alarm flag is only used to
08046                control whether an 'alarm cleared' message gets generated when we
08047                get an indication that the channel is no longer in alarm status.
08048                however, the channel *could* be in an alarm status that we aren't
08049                aware of (since get_alarms() only reports span alarms, not channel
08050                alarms). setting this flag will cause any potential 'alarm cleared'
08051                message to be suppressed, but if a real alarm occurs before that
08052                happens, this flag will get cleared by it and the situation will
08053                be normal.
08054             */
08055             tmp->unknown_alarm = 1;
08056          }
08057       }
08058 
08059       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
08060       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
08061       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
08062       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
08063 
08064    }
08065    if (tmp && !here) {
08066       /* nothing on the iflist */
08067       if (!*wlist) {
08068          *wlist = tmp;
08069          tmp->prev = NULL;
08070          tmp->next = NULL;
08071          *wend = tmp;
08072       } else {
08073          /* at least one member on the iflist */
08074          struct dahdi_pvt *working = *wlist;
08075 
08076          /* check if we maybe have to put it on the begining */
08077          if (working->channel > tmp->channel) {
08078             tmp->next = *wlist;
08079             tmp->prev = NULL;
08080             (*wlist)->prev = tmp;
08081             *wlist = tmp;
08082          } else {
08083          /* go through all the members and put the member in the right place */
08084             while (working) {
08085                /* in the middle */
08086                if (working->next) {
08087                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
08088                      tmp->next = working->next;
08089                      tmp->prev = working;
08090                      working->next->prev = tmp;
08091                      working->next = tmp;
08092                      break;
08093                   }
08094                } else {
08095                /* the last */
08096                   if (working->channel < tmp->channel) {
08097                      working->next = tmp;
08098                      tmp->next = NULL;
08099                      tmp->prev = working;
08100                      *wend = tmp;
08101                      break;
08102                   }
08103                }
08104                working = working->next;
08105             }
08106          }
08107       }
08108    }
08109    return tmp;
08110 }

static int my_dahdi_write ( struct dahdi_pvt p,
unsigned char *  buf,
int  len,
int  index,
int  linear 
) [static]

Definition at line 5368 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, errno, LOG_DEBUG, option_debug, READ_SIZE, and dahdi_pvt::subs.

Referenced by dahdi_write().

05369 {
05370    int sent=0;
05371    int size;
05372    int res;
05373    int fd;
05374    fd = p->subs[index].dfd;
05375    while (len) {
05376       size = len;
05377       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05378          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05379       res = write(fd, buf, size);
05380       if (res != size) {
05381          if (option_debug)
05382             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05383          return sent;
05384       }
05385       len -= size;
05386       buf += size;
05387    }
05388    return sent;
05389 }

static int my_getsigstr ( struct ast_channel chan,
char *  str,
const char *  term,
int  ms 
) [static]

Definition at line 5847 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

05848 {
05849    char c;
05850 
05851    *str = 0; /* start with empty output buffer */
05852    for (;;)
05853    {
05854       /* Wait for the first digit (up to specified ms). */
05855       c = ast_waitfordigit(chan, ms);
05856       /* if timeout, hangup or error, return as such */
05857       if (c < 1)
05858          return c;
05859       *str++ = c;
05860       *str = 0;
05861       if (strchr(term, c))
05862          return 1;
05863    }
05864 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

Definition at line 2776 of file chan_dahdi.c.

References dahdi_pri::dchans, dahdi_pri::fds, NUM_DCHANS, dahdi_pri::pri, and dahdi_pvt::pri.

Referenced by pri_find_principle().

02777 {
02778    int x = -1;
02779 
02780    for (x = 0; x < NUM_DCHANS; x++) {
02781       if ((pri->dchans[x] == pri->pri))
02782          break;
02783    }
02784 
02785    return pri->fds[x];
02786 }

static int pri_assign_bearer ( struct dahdi_pvt crv,
struct dahdi_pri pri,
struct dahdi_pvt bearer 
) [static]

Definition at line 2746 of file chan_dahdi.c.

References dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, ast_channel::fds, inuse, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_request().

02747 {
02748    bearer->owner = &inuse;
02749    bearer->realcall = crv;
02750    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02751    if (crv->subs[SUB_REAL].owner)
02752       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02753    crv->bearer = bearer;
02754    crv->call = bearer->call;
02755    crv->pri = pri;
02756    return 0;
02757 }

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

Definition at line 8786 of file chan_dahdi.c.

References dahdi_pri::lastreset, dahdi_pri::numchans, dahdi_pri::pri, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pri::resetpos, dahdi_pri::resetting, and dahdi_pvt::resetting.

Referenced by pri_dchannel().

08787 {
08788    do {
08789       pri->resetpos++;
08790    } while ((pri->resetpos < pri->numchans) &&
08791        (!pri->pvts[pri->resetpos] ||
08792         pri->pvts[pri->resetpos]->call ||
08793         pri->pvts[pri->resetpos]->resetting));
08794    if (pri->resetpos < pri->numchans) {
08795       /* Mark the channel as resetting and restart it */
08796       pri->pvts[pri->resetpos]->resetting = 1;
08797       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
08798    } else {
08799       pri->resetting = 0;
08800       time(&pri->lastreset);
08801    }
08802    return 0;
08803 }

static int pri_create_spanmap ( int  span,
int  trunkgroup,
int  logicalspan 
) [static]

Definition at line 7605 of file chan_dahdi.c.

References ast_log(), dahdi_pri::mastertrunkgroup, dahdi_pri::prilogicalspan, and pris.

Referenced by setup_dahdi().

07606 {
07607    if (pris[span].mastertrunkgroup) {
07608       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);
07609       return -1;
07610    }
07611    pris[span].mastertrunkgroup = trunkgroup;
07612    pris[span].prilogicalspan = logicalspan;
07613    return 0;
07614 }

static int pri_create_trunkgroup ( int  trunkgroup,
int *  channels 
) [static]

Definition at line 7542 of file chan_dahdi.c.

References ast_log(), DAHDI_FILE_CHANNEL, DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, errno, NUM_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, dahdi_pri::span, and dahdi_pri::trunkgroup.

Referenced by setup_dahdi().

07543 {
07544    struct dahdi_spaninfo si;
07545    struct dahdi_params p;
07546    int fd;
07547    int span;
07548    int ospan=0;
07549    int x,y;
07550    for (x = 0; x < NUM_SPANS; x++) {
07551       if (pris[x].trunkgroup == trunkgroup) {
07552          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
07553          return -1;
07554       }
07555    }
07556    for (y = 0; y < NUM_DCHANS; y++) {
07557       if (!channels[y]) 
07558          break;
07559       memset(&si, 0, sizeof(si));
07560       memset(&p, 0, sizeof(p));
07561       fd = open(DAHDI_FILE_CHANNEL, O_RDWR);
07562       if (fd < 0) {
07563          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
07564          return -1;
07565       }
07566       x = channels[y];
07567       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
07568          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
07569          close(fd);
07570          return -1;
07571       }
07572       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
07573          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
07574          return -1;
07575       }
07576       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
07577          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
07578          close(fd);
07579          return -1;
07580       }
07581       span = p.spanno - 1;
07582       if (pris[span].trunkgroup) {
07583          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
07584          close(fd);
07585          return -1;
07586       }
07587       if (pris[span].pvts[0]) {
07588          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
07589          close(fd);
07590          return -1;
07591       }
07592       if (!y) {
07593          pris[span].trunkgroup = trunkgroup;
07594          pris[span].offset = channels[y] - p.chanpos;
07595          ospan = span;
07596       }
07597       pris[ospan].dchannels[y] = channels[y];
07598       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
07599       pris[span].span = span + 1;
07600       close(fd);
07601    }
07602    return 0;   
07603 }

static void* pri_dchannel ( void *  vpri  )  [static]

Definition at line 8885 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_copy_string(), ast_exists_extension(), AST_FORMAT_ULAW, ast_log(), ast_mutex_lock, ast_pthread_create_background, AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), dahdi_pvt::call, dahdi_pvt::channel, dahdi_chan_name, dahdi_hangup(), dahdi_request(), dahdi_pri::dchannels, dahdi_pri::dchans, do_idle_thread(), dahdi_pri::fds, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::isidlecall, dahdi_pri::lastreset, dahdi_pri::lock, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pri_check_restart(), pri_is_up(), dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, dahdi_pri::switchtype, and t.

08886 {
08887    struct dahdi_pri *pri = vpri;
08888    pri_event *e;
08889    struct pollfd fds[NUM_DCHANS];
08890    int res;
08891    int chanpos = 0;
08892    int x;
08893    int haveidles;
08894    int activeidles;
08895    int nextidle = -1;
08896    struct ast_channel *c;
08897    struct timeval tv, lowest, *next;
08898    struct timeval lastidle = { 0, 0 };
08899    int doidling=0;
08900    char *cc;
08901    char idlen[80];
08902    struct ast_channel *idle;
08903    pthread_t p;
08904    time_t t;
08905    int i, which=-1;
08906    int numdchans;
08907    int cause=0;
08908    struct dahdi_pvt *crv;
08909    pthread_t threadid;
08910    pthread_attr_t attr;
08911    char ani2str[6];
08912    char plancallingnum[256];
08913    char plancallingani[256];
08914    char calledtonstr[10];
08915    
08916    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08917 
08918    gettimeofday(&lastidle, NULL);
08919    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
08920       /* Need to do idle dialing, check to be sure though */
08921       cc = strchr(pri->idleext, '@');
08922       if (cc) {
08923          *cc = '\0';
08924          cc++;
08925          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
08926 #if 0
08927          /* Extensions may not be loaded yet */
08928          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
08929             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
08930          else
08931 #endif
08932             doidling = 1;
08933       } else
08934          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
08935    }
08936    for (;;) {
08937       for (i = 0; i < NUM_DCHANS; i++) {
08938          if (!pri->dchannels[i])
08939             break;
08940          fds[i].fd = pri->fds[i];
08941          fds[i].events = POLLIN | POLLPRI;
08942          fds[i].revents = 0;
08943       }
08944       numdchans = i;
08945       time(&t);
08946       ast_mutex_lock(&pri->lock);
08947       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
08948          if (pri->resetting && pri_is_up(pri)) {
08949             if (pri->resetpos < 0)
08950                pri_check_restart(pri);
08951          } else {
08952             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
08953                pri->resetting = 1;
08954                pri->resetpos = -1;
08955             }
08956          }
08957       }
08958       /* Look for any idle channels if appropriate */
08959       if (doidling && pri_is_up(pri)) {
08960          nextidle = -1;
08961          haveidles = 0;
08962          activeidles = 0;
08963          for (x = pri->numchans; x >= 0; x--) {
08964             if (pri->pvts[x] && !pri->pvts[x]->owner && 
08965                 !pri->pvts[x]->call) {
08966                if (haveidles < pri->minunused) {
08967                   haveidles++;
08968                } else if (!pri->pvts[x]->resetting) {
08969                   nextidle = x;
08970                   break;
08971                }
08972             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
08973                activeidles++;
08974          }
08975          if (nextidle > -1) {
08976             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
08977                /* Don't create a new idle call more than once per second */
08978                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
08979                idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
08980                if (idle) {
08981                   pri->pvts[nextidle]->isidlecall = 1;
08982                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
08983                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
08984                      dahdi_hangup(idle);
08985                   }
08986                } else
08987                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
08988                gettimeofday(&lastidle, NULL);
08989             }
08990          } else if ((haveidles < pri->minunused) &&
08991                (activeidles > pri->minidle)) {
08992             /* Mark something for hangup if there is something 
08993                that can be hungup */
08994             for (x = pri->numchans; x >= 0; x--) {
08995                /* find a candidate channel */
08996                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
08997                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
08998                   haveidles++;
08999                   /* Stop if we have enough idle channels or
09000                     can't spare any more active idle ones */
09001                   if ((haveidles >= pri->minunused) ||
09002                       (activeidles <= pri->minidle))
09003                      break;
09004                } 
09005             }
09006          }
09007       }
09008       /* Start with reasonable max */
09009       lowest = ast_tv(60, 0);
09010       for (i = 0; i < NUM_DCHANS; i++) {
09011          /* Find lowest available d-channel */
09012          if (!pri->dchannels[i])
09013             break;
09014          if ((next = pri_schedule_next(pri->dchans[i]))) {
09015             /* We need relative time here */
09016             tv = ast_tvsub(*next, ast_tvnow());
09017             if (tv.tv_sec < 0) {
09018                tv = ast_tv(0,0);
09019             }
09020             if (doidling || pri->resetting) {
09021                if (tv.tv_sec > 1) {
09022                   tv = ast_tv(1, 0);
09023                }
09024             } else {
09025                if (tv.tv_sec > 60) {
09026                   tv = ast_tv(60, 0);
09027                }
09028             }
09029          } else if (doidling || pri->resetting) {
09030             /* Make sure we stop at least once per second if we're
09031                monitoring idle channels */
09032             tv = ast_tv(1,0);
09033          } else {
09034             /* Don't poll for more than 60 seconds */
09035             tv = ast_tv(60, 0);
09036          }
09037          if (!i || ast_tvcmp(tv, lowest) < 0) {
09038             lowest = tv;
09039          }
09040       }
09041       ast_mutex_unlock(&pri->lock);
09042 
09043       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09044       pthread_testcancel();
09045       e = NULL;
09046       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
09047       pthread_testcancel();
09048       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09049 
09050       ast_mutex_lock(&pri->lock);
09051       if (!res) {
09052          for (which = 0; which < NUM_DCHANS; which++) {
09053             if (!pri->dchans[which])
09054                break;
09055             /* Just a timeout, run the scheduler */
09056             e = pri_schedule_run(pri->dchans[which]);
09057             if (e)
09058                break;
09059          }
09060       } else if (res > -1) {
09061          for (which = 0; which < NUM_DCHANS; which++) {
09062             if (!pri->dchans[which])
09063                break;
09064             if (fds[which].revents & POLLPRI) {
09065                /* Check for an event */
09066                x = 0;
09067                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
09068                if (x) 
09069                   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);
09070                /* Keep track of alarm state */  
09071                if (x == DAHDI_EVENT_ALARM) {
09072                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
09073                   pri_find_dchan(pri);
09074                } else if (x == DAHDI_EVENT_NOALARM) {
09075                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
09076                   pri_restart(pri->dchans[which]);
09077                }
09078             
09079                if (option_debug)
09080                   ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
09081             } else if (fds[which].revents & POLLIN) {
09082                e = pri_check_event(pri->dchans[which]);
09083             }
09084             if (e)
09085                break;
09086          }
09087       } else if (errno != EINTR)
09088          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
09089 
09090       if (e) {
09091          if (pri->debug)
09092             pri_dump_event(pri->dchans[which], e);
09093 
09094          if (e->e != PRI_EVENT_DCHAN_DOWN) {
09095             if (!(pri->dchanavail[which] & DCHAN_UP)) {
09096                if (option_verbose > 1) 
09097                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d up\n", pri_order(which), pri->span);
09098             }
09099             pri->dchanavail[which] |= DCHAN_UP;
09100          } else {
09101             if (pri->dchanavail[which] & DCHAN_UP) {
09102                if (option_verbose > 1) 
09103                   ast_verbose(VERBOSE_PREFIX_2 "%s D-Channel on span %d down\n", pri_order(which), pri->span);
09104             }
09105             pri->dchanavail[which] &= ~DCHAN_UP;
09106          }
09107 
09108          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
09109             /* Must be an NFAS group that has the secondary dchan active */
09110             pri->pri = pri->dchans[which];
09111 
09112          switch (e->e) {
09113          case PRI_EVENT_DCHAN_UP:
09114             if (!pri->pri) pri_find_dchan(pri);
09115 
09116             /* Note presense of D-channel */
09117             time(&pri->lastreset);
09118 
09119             /* Restart in 5 seconds */
09120             if (pri->resetinterval > -1) {
09121                pri->lastreset -= pri->resetinterval;
09122                pri->lastreset += 5;
09123             }
09124             pri->resetting = 0;
09125             /* Take the channels from inalarm condition */
09126             for (i = 0; i < pri->numchans; i++)
09127                if (pri->pvts[i]) {
09128                   pri->pvts[i]->inalarm = 0;
09129                }
09130             break;
09131          case PRI_EVENT_DCHAN_DOWN:
09132             pri_find_dchan(pri);
09133             if (!pri_is_up(pri)) {
09134                pri->resetting = 0;
09135                /* Hangup active channels and put them in alarm mode */
09136                for (i = 0; i < pri->numchans; i++) {
09137                   struct dahdi_pvt *p = pri->pvts[i];
09138                   if (p) {
09139                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
09140                         /* T309 is not enabled : hangup calls when alarm occurs */
09141                         if (p->call) {
09142                            if (p->pri && p->pri->pri) {
09143                               pri_hangup(p->pri->pri, p->call, -1);
09144                               pri_destroycall(p->pri->pri, p->call);
09145                               p->call = NULL;
09146                            } else
09147                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
09148                         }
09149                         if (p->realcall) {
09150                            pri_hangup_all(p->realcall, pri);
09151                         } else if (p->owner)
09152                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09153                      }
09154                      p->inalarm = 1;
09155                   }
09156                }
09157             }
09158             break;
09159          case PRI_EVENT_RESTART:
09160             if (e->restart.channel > -1) {
09161                chanpos = pri_find_principle(pri, e->restart.channel);
09162                if (chanpos < 0)
09163                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
09164                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09165                else {
09166                   if (option_verbose > 2)
09167                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d restarted on span %d\n", 
09168                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
09169                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09170                   if (pri->pvts[chanpos]->call) {
09171                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
09172                      pri->pvts[chanpos]->call = NULL;
09173                   }
09174                   /* Force soft hangup if appropriate */
09175                   if (pri->pvts[chanpos]->realcall) 
09176                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09177                   else if (pri->pvts[chanpos]->owner)
09178                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09179                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09180                }
09181             } else {
09182                if (option_verbose > 2)
09183                   ast_verbose(VERBOSE_PREFIX_2 "Restart on requested on entire span %d\n", pri->span);
09184                for (x = 0; x < pri->numchans; x++)
09185                   if (pri->pvts[x]) {
09186                      ast_mutex_lock(&pri->pvts[x]->lock);
09187                      if (pri->pvts[x]->call) {
09188                         pri_destroycall(pri->pri, pri->pvts[x]->call);
09189                         pri->pvts[x]->call = NULL;
09190                      }
09191                      if (pri->pvts[chanpos]->realcall) 
09192                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09193                      else if (pri->pvts[x]->owner)
09194                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09195                      ast_mutex_unlock(&pri->pvts[x]->lock);
09196                   }
09197             }
09198             break;
09199          case PRI_EVENT_KEYPAD_DIGIT:
09200             chanpos = pri_find_principle(pri, e->digit.channel);
09201             if (chanpos < 0) {
09202                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
09203                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
09204             } else {
09205                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
09206                if (chanpos > -1) {
09207                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09208                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
09209                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
09210                      /* how to do that */
09211                      int digitlen = strlen(e->digit.digits);
09212                      char digit;
09213                      int i;               
09214                      for (i = 0; i < digitlen; i++) { 
09215                         digit = e->digit.digits[i];
09216                         {
09217                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
09218                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09219                         }
09220                      }
09221                   }
09222                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09223                }
09224             }
09225             break;
09226             
09227          case PRI_EVENT_INFO_RECEIVED:
09228             chanpos = pri_find_principle(pri, e->ring.channel);
09229             if (chanpos < 0) {
09230                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
09231                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09232             } else {
09233                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
09234                if (chanpos > -1) {
09235                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09236                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
09237                   if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
09238                      /* how to do that */
09239                      int digitlen = strlen(e->ring.callednum);
09240                      char digit;
09241                      int i;               
09242                      for (i = 0; i < digitlen; i++) { 
09243                         digit = e->ring.callednum[i];
09244                         {
09245                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
09246                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09247                         }
09248                      }
09249                   }
09250                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09251                }
09252             }
09253             break;
09254          case PRI_EVENT_RING:
09255             crv = NULL;
09256             if (e->ring.channel == -1)
09257                chanpos = pri_find_empty_chan(pri, 1);
09258             else
09259                chanpos = pri_find_principle(pri, e->ring.channel);
09260             /* if no channel specified find one empty */
09261             if (chanpos < 0) {
09262                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
09263                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09264             } else {
09265                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09266                if (pri->pvts[chanpos]->owner) {
09267                   if (pri->pvts[chanpos]->call == e->ring.call) {
09268                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
09269                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09270                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09271                      break;
09272                   } else {
09273                      /* This is where we handle initial glare */
09274                      ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
09275                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
09276                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09277                      chanpos = -1;
09278                   }
09279                }
09280                if (chanpos > -1)
09281                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09282             }
09283             if ((chanpos < 0) && (e->ring.flexible))
09284                chanpos = pri_find_empty_chan(pri, 1);
09285             if (chanpos > -1) {
09286                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09287                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
09288                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
09289                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
09290                   if (crv)
09291                      ast_mutex_lock(&crv->lock);
09292                   if (!crv || crv->owner) {
09293                      pri->pvts[chanpos]->call = NULL;
09294                      if (crv) {
09295                         if (crv->owner)
09296                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09297                         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);
09298                      } else
09299                         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);
09300                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
09301                      if (crv)
09302                         ast_mutex_unlock(&crv->lock);
09303                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09304                      break;
09305                   }
09306                }
09307                pri->pvts[chanpos]->call = e->ring.call;
09308                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
09309                if (pri->pvts[chanpos]->use_callerid) {
09310                   ast_shrink_phone_number(plancallingnum);
09311                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
09312 #ifdef PRI_ANI
09313                   if (!ast_strlen_zero(e->ring.callingani)) {
09314                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
09315                      ast_shrink_phone_number(plancallingani);
09316                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
09317                   } else {
09318                      pri->pvts[chanpos]->cid_ani[0] = '\0';
09319                   }
09320 #endif
09321                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
09322                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
09323                } else {
09324                   pri->pvts[chanpos]->cid_num[0] = '\0';
09325                   pri->pvts[chanpos]->cid_ani[0] = '\0';
09326                   pri->pvts[chanpos]->cid_name[0] = '\0';
09327                   pri->pvts[chanpos]->cid_ton = 0;
09328                }
09329                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
09330                           e->ring.redirectingnum, e->ring.callingplanrdnis);
09331                /* If immediate=yes go to s|1 */
09332                if (pri->pvts[chanpos]->immediate) {
09333                   if (option_verbose > 2)
09334                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
09335                   pri->pvts[chanpos]->exten[0] = 's';
09336                   pri->pvts[chanpos]->exten[1] = '\0';
09337                }
09338                /* Get called number */
09339                else if (!ast_strlen_zero(e->ring.callednum)) {
09340                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
09341                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09342                } else if (pri->overlapdial)
09343                   pri->pvts[chanpos]->exten[0] = '\0';
09344                else {
09345                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
09346                   pri->pvts[chanpos]->exten[0] = 's';
09347                   pri->pvts[chanpos]->exten[1] = '\0';
09348                }
09349                /* Set DNID on all incoming calls -- even immediate */
09350                if (!ast_strlen_zero(e->ring.callednum))
09351                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
09352                /* No number yet, but received "sending complete"? */
09353                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
09354                   if (option_verbose > 2)
09355                      ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
09356                   pri->pvts[chanpos]->exten[0] = 's';
09357                   pri->pvts[chanpos]->exten[1] = '\0';
09358                }
09359                /* Make sure extension exists (or in overlap dial mode, can exist) */
09360                if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
09361                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09362                   /* Setup law */
09363                   int law;
09364                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
09365                      /* Set to audio mode at this point */
09366                      law = 1;
09367                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09368                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
09369                   }
09370                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
09371                      law = DAHDI_LAW_ALAW;
09372                   else
09373                      law = DAHDI_LAW_MULAW;
09374                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
09375                   if (res < 0) 
09376                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
09377                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
09378                   if (res < 0)
09379                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
09380                   if (e->ring.complete || !pri->overlapdial) {
09381                      /* Just announce proceeding */
09382                      pri->pvts[chanpos]->proceeding = 1;
09383                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
09384                   } else {
09385                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
09386                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09387                      else
09388                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
09389                   }
09390                   /* Get the use_callingpres state */
09391                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
09392                
09393                   /* Start PBX */
09394                   if (!e->ring.complete && pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
09395                      /* Release the PRI lock while we create the channel */
09396                      ast_mutex_unlock(&pri->lock);
09397                      if (crv) {
09398                         /* Set bearer and such */
09399                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
09400                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09401                         pri->pvts[chanpos]->owner = &inuse;
09402                         ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
09403                      } else {
09404                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
09405                      }
09406 
09407                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09408 
09409                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
09410                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
09411                      }
09412                      if (e->ring.ani2 >= 0) {
09413                         snprintf(ani2str, 5, "%.2d", e->ring.ani2);
09414                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09415                      }
09416 
09417 #ifdef SUPPORT_USERUSER
09418                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
09419                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09420                      }
09421 #endif
09422 
09423                      snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09424                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09425                      if (e->ring.redirectingreason >= 0)
09426                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09427                   
09428                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09429                      ast_mutex_lock(&pri->lock);
09430 
09431                      pthread_attr_init(&attr);
09432                      pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09433                      if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
09434                         if (option_verbose > 2)
09435                            ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
09436                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
09437                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09438                      } else {
09439                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09440                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09441                         if (c)
09442                            ast_hangup(c);
09443                         else {
09444                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09445                            pri->pvts[chanpos]->call = NULL;
09446                         }
09447                      }
09448                      pthread_attr_destroy(&attr);
09449                   } else  {
09450                      ast_mutex_unlock(&pri->lock);
09451                      /* Release PRI lock while we create the channel */
09452                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
09453                      if (c) {
09454                         char calledtonstr[10];
09455 
09456                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09457 
09458                         if (e->ring.ani2 >= 0) {
09459                            snprintf(ani2str, 5, "%d", e->ring.ani2);
09460                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
09461                         }
09462 
09463 #ifdef SUPPORT_USERUSER
09464                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
09465                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
09466                         }
09467 #endif
09468 
09469                         if (e->ring.redirectingreason >= 0)
09470                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
09471                      
09472                         snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
09473                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
09474 
09475                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
09476                         ast_mutex_lock(&pri->lock);
09477 
09478                         if (option_verbose > 2)
09479                            ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
09480                               plancallingnum, pri->pvts[chanpos]->exten, 
09481                                  pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09482                         dahdi_enable_ec(pri->pvts[chanpos]);
09483                      } else {
09484 
09485                         ast_mutex_lock(&pri->lock);
09486 
09487                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
09488                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
09489                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
09490                         pri->pvts[chanpos]->call = NULL;
09491                      }
09492                   }
09493                } else {
09494                   if (option_verbose > 2)
09495                      ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
09496                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
09497                            pri->pvts[chanpos]->prioffset, pri->span);
09498                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
09499                   pri->pvts[chanpos]->call = NULL;
09500                   pri->pvts[chanpos]->exten[0] = '\0';
09501                }
09502                if (crv)
09503                   ast_mutex_unlock(&crv->lock);
09504                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09505             } else {
09506                if (e->ring.flexible)
09507                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
09508                else
09509                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
09510             }
09511             break;
09512          case PRI_EVENT_RINGING:
09513             chanpos = pri_find_principle(pri, e->ringing.channel);
09514             if (chanpos < 0) {
09515                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
09516                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09517             } else {
09518                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
09519                if (chanpos < 0) {
09520                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
09521                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
09522                } else {
09523                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09524                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09525                      dahdi_enable_ec(pri->pvts[chanpos]);
09526                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
09527                      pri->pvts[chanpos]->alerting = 1;
09528                   } else
09529                      ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
09530 #ifdef PRI_PROGRESS_MASK
09531                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09532 #else
09533                   if (e->ringing.progress == 8) {
09534 #endif
09535                      /* Now we can do call progress detection */
09536                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09537                         /* RINGING detection isn't required because we got ALERTING signal */
09538                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
09539                         pri->pvts[chanpos]->dsp_features = 0;
09540                      }
09541                   }
09542 
09543 #ifdef SUPPORT_USERUSER
09544                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
09545                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09546                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09547                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
09548                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09549                   }
09550 #endif
09551 
09552                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09553                }
09554             }
09555             break;
09556          case PRI_EVENT_PROGRESS:
09557             /* Get chan value if e->e is not PRI_EVNT_RINGING */
09558             chanpos = pri_find_principle(pri, e->proceeding.channel);
09559             if (chanpos > -1) {
09560 #ifdef PRI_PROGRESS_MASK
09561                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
09562 #else
09563                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
09564 #endif
09565                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
09566 
09567                   if (e->proceeding.cause > -1) {
09568                      if (option_verbose > 2)
09569                         ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
09570 
09571                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
09572                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
09573                         if (pri->pvts[chanpos]->owner) {
09574                            if (option_verbose > 2)
09575                               ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
09576 
09577                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
09578                            f.subclass = AST_CONTROL_BUSY;
09579                         }
09580                      }
09581                   }
09582                   
09583                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09584                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
09585                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09586                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09587 #ifdef PRI_PROGRESS_MASK
09588                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09589 #else
09590                   if (e->proceeding.progress == 8) {
09591 #endif
09592                      /* Now we can do call progress detection */
09593                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09594                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09595                         pri->pvts[chanpos]->dsp_features = 0;
09596                      }
09597                      /* Bring voice path up */
09598                      f.subclass = AST_CONTROL_PROGRESS;
09599                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09600                   }
09601                   pri->pvts[chanpos]->progress = 1;
09602                   pri->pvts[chanpos]->dialing = 0;
09603                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09604                }
09605             }
09606             break;
09607          case PRI_EVENT_PROCEEDING:
09608             chanpos = pri_find_principle(pri, e->proceeding.channel);
09609             if (chanpos > -1) {
09610                if (!pri->pvts[chanpos]->proceeding) {
09611                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
09612                   
09613                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09614                   ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
09615                         pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
09616                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09617 #ifdef PRI_PROGRESS_MASK
09618                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
09619 #else
09620                   if (e->proceeding.progress == 8) {
09621 #endif
09622                      /* Now we can do call progress detection */
09623                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09624                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09625                         pri->pvts[chanpos]->dsp_features = 0;
09626                      }
09627                      /* Bring voice path up */
09628                      f.subclass = AST_CONTROL_PROGRESS;
09629                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09630                   }
09631                   pri->pvts[chanpos]->proceeding = 1;
09632                   pri->pvts[chanpos]->dialing = 0;
09633                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09634                }
09635             }
09636             break;
09637          case PRI_EVENT_FACNAME:
09638             chanpos = pri_find_principle(pri, e->facname.channel);
09639             if (chanpos < 0) {
09640                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
09641                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09642             } else {
09643                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
09644                if (chanpos < 0) {
09645                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
09646                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
09647                } else {
09648                   /* Re-use *69 field for PRI */
09649                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09650                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
09651                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
09652                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
09653                   dahdi_enable_ec(pri->pvts[chanpos]);
09654                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09655                }
09656             }
09657             break;            
09658          case PRI_EVENT_ANSWER:
09659             chanpos = pri_find_principle(pri, e->answer.channel);
09660             if (chanpos < 0) {
09661                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
09662                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09663             } else {
09664                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
09665                if (chanpos < 0) {
09666                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
09667                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
09668                } else {
09669                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09670                   /* Now we can do call progress detection */
09671 
09672                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
09673                    * By this time, we need DTMF detection and other features that were previously disabled
09674                    * -- Matt F */
09675                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
09676                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
09677                      pri->pvts[chanpos]->dsp_features = 0;
09678                   }
09679                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
09680                      ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
09681                      x = DAHDI_START;
09682                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
09683                      if (res < 0) {
09684                         if (errno != EINPROGRESS) {
09685                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
09686                         }
09687                      }
09688                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
09689                      pri->pvts[chanpos]->dialing = 1;
09690                      /* Send any "w" waited stuff */
09691                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
09692                      if (res < 0) {
09693                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
09694                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09695                      } else 
09696                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
09697                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
09698                   } else if (pri->pvts[chanpos]->confirmanswer) {
09699                      ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
09700                   } else {
09701                      pri->pvts[chanpos]->dialing = 0;
09702                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
09703                      /* Enable echo cancellation if it's not on already */
09704                      dahdi_enable_ec(pri->pvts[chanpos]);
09705                   }
09706 
09707 #ifdef SUPPORT_USERUSER
09708                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
09709                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09710                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09711                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
09712                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09713                   }
09714 #endif
09715 
09716                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09717                }
09718             }
09719             break;            
09720          case PRI_EVENT_HANGUP:
09721             chanpos = pri_find_principle(pri, e->hangup.channel);
09722             if (chanpos < 0) {
09723                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
09724                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09725             } else {
09726                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09727                if (chanpos > -1) {
09728                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09729                   if (!pri->pvts[chanpos]->alreadyhungup) {
09730                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
09731                      pri->pvts[chanpos]->alreadyhungup = 1;
09732                      if (pri->pvts[chanpos]->realcall) 
09733                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09734                      else if (pri->pvts[chanpos]->owner) {
09735                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
09736                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09737                         if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09738                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09739                         else {
09740                            switch (e->hangup.cause) {
09741                               case PRI_CAUSE_USER_BUSY:
09742                                  pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09743                                  break;
09744                               case PRI_CAUSE_CALL_REJECTED:
09745                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09746                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09747                               case PRI_CAUSE_SWITCH_CONGESTION:
09748                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09749                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09750                                  pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09751                                  break;
09752                               default:
09753                                  pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09754                            }
09755                         }
09756                      }
09757                      if (option_verbose > 2) 
09758                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
09759                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
09760                   } else {
09761                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09762                      pri->pvts[chanpos]->call = NULL;
09763                   }
09764                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09765                      if (option_verbose > 2)
09766                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
09767                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09768                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09769                      pri->pvts[chanpos]->resetting = 1;
09770                   }
09771                   if (e->hangup.aoc_units > -1)
09772                      if (option_verbose > 2)
09773                         ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09774                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09775 
09776 #ifdef SUPPORT_USERUSER
09777                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
09778                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09779                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09780                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09781                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09782                   }
09783 #endif
09784 
09785                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09786                } else {
09787                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
09788                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09789                }
09790             } 
09791             break;
09792 #ifndef PRI_EVENT_HANGUP_REQ
09793 #error please update libpri
09794 #endif
09795          case PRI_EVENT_HANGUP_REQ:
09796             chanpos = pri_find_principle(pri, e->hangup.channel);
09797             if (chanpos < 0) {
09798                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
09799                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09800             } else {
09801                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09802                if (chanpos > -1) {
09803                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09804                   if (pri->pvts[chanpos]->realcall) 
09805                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09806                   else if (pri->pvts[chanpos]->owner) {
09807                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
09808                      if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
09809                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09810                      else {
09811                         switch (e->hangup.cause) {
09812                            case PRI_CAUSE_USER_BUSY:
09813                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
09814                               break;
09815                            case PRI_CAUSE_CALL_REJECTED:
09816                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
09817                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
09818                            case PRI_CAUSE_SWITCH_CONGESTION:
09819                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
09820                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
09821                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
09822                               break;
09823                            default:
09824                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09825                         }
09826                      }
09827                      if (option_verbose > 2) 
09828                         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);
09829                      if (e->hangup.aoc_units > -1)
09830                         if (option_verbose > 2)
09831                            ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
09832                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
09833                   } else {
09834                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
09835                      pri->pvts[chanpos]->call = NULL;
09836                   }
09837                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
09838                      if (option_verbose > 2)
09839                         ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d span %d since channel reported in use\n", 
09840                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09841                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
09842                      pri->pvts[chanpos]->resetting = 1;
09843                   }
09844 
09845 #ifdef SUPPORT_USERUSER
09846                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09847                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09848                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09849                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09850                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09851                   }
09852 #endif
09853 
09854                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09855                } else {
09856                   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);
09857                }
09858             } 
09859             break;
09860          case PRI_EVENT_HANGUP_ACK:
09861             chanpos = pri_find_principle(pri, e->hangup.channel);
09862             if (chanpos < 0) {
09863                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
09864                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
09865             } else {
09866                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
09867                if (chanpos > -1) {
09868                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09869                   pri->pvts[chanpos]->call = NULL;
09870                   pri->pvts[chanpos]->resetting = 0;
09871                   if (pri->pvts[chanpos]->owner) {
09872                      if (option_verbose > 2) 
09873                         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);
09874                   }
09875 
09876 #ifdef SUPPORT_USERUSER
09877                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
09878                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
09879                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09880                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
09881                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09882                   }
09883 #endif
09884 
09885                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09886                }
09887             }
09888             break;
09889          case PRI_EVENT_CONFIG_ERR:
09890             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
09891             break;
09892          case PRI_EVENT_RESTART_ACK:
09893             chanpos = pri_find_principle(pri, e->restartack.channel);
09894             if (chanpos < 0) {
09895                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
09896                   channel number, so we have to figure it out...  This must be why
09897                   everybody resets exactly a channel at a time. */
09898                for (x = 0; x < pri->numchans; x++) {
09899                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
09900                      chanpos = x;
09901                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
09902                      ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
09903                            pri->pvts[chanpos]->prioffset, pri->span);
09904                      if (pri->pvts[chanpos]->realcall) 
09905                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09906                      else if (pri->pvts[chanpos]->owner) {
09907                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
09908                            pri->pvts[chanpos]->prioffset, pri->span);
09909                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09910                      }
09911                      pri->pvts[chanpos]->resetting = 0;
09912                      if (option_verbose > 2)
09913                         ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09914                            pri->pvts[chanpos]->prioffset, pri->span);
09915                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09916                      if (pri->resetting)
09917                         pri_check_restart(pri);
09918                      break;
09919                   }
09920                }
09921                if (chanpos < 0) {
09922                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
09923                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09924                }
09925             } else {
09926                if (pri->pvts[chanpos]) {
09927                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09928                   if (pri->pvts[chanpos]->realcall) 
09929                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
09930                   else if (pri->pvts[chanpos]->owner) {
09931                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
09932                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
09933                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
09934                   }
09935                   pri->pvts[chanpos]->resetting = 0;
09936                   if (option_verbose > 2)
09937                      ast_verbose(VERBOSE_PREFIX_3 "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan, 
09938                            pri->pvts[chanpos]->prioffset, pri->span);
09939                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09940                   if (pri->resetting)
09941                      pri_check_restart(pri);
09942                }
09943             }
09944             break;
09945          case PRI_EVENT_SETUP_ACK:
09946             chanpos = pri_find_principle(pri, e->setup_ack.channel);
09947             if (chanpos < 0) {
09948                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
09949                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
09950             } else {
09951                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
09952                if (chanpos > -1) {
09953                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
09954                   pri->pvts[chanpos]->setup_ack = 1;
09955                   /* Send any queued digits */
09956                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
09957                      ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
09958                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
09959                         pri->pvts[chanpos]->dialdest[x]);
09960                   }
09961                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09962                } else
09963                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
09964             }
09965             break;
09966          case PRI_EVENT_NOTIFY:
09967             chanpos = pri_find_principle(pri, e->notify.channel);
09968             if (chanpos < 0) {
09969                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
09970                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
09971             } else {
09972                struct ast_frame f = { AST_FRAME_CONTROL, };
09973                ast_mutex_lock(&pri->pvts[chanpos]->lock);
09974                switch (e->notify.info) {
09975                case PRI_NOTIFY_REMOTE_HOLD:
09976                   f.subclass = AST_CONTROL_HOLD;
09977                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09978                   break;
09979                case PRI_NOTIFY_REMOTE_RETRIEVAL:
09980                   f.subclass = AST_CONTROL_UNHOLD;
09981                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
09982                   break;
09983                }
09984                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
09985             }
09986             break;
09987          default:
09988             ast_log(LOG_DEBUG, "Event: %d\n", e->e);
09989          }
09990       }  
09991       ast_mutex_unlock(&pri->lock);
09992    }
09993    /* Never reached */
09994    return NULL;
09995 }

static struct dahdi_pvt* pri_find_crv ( struct dahdi_pri pri,
int  crv 
) [static]

Definition at line 8524 of file chan_dahdi.c.

References dahdi_pvt::channel, dahdi_pri::crvs, dahdi_pvt::next, and dahdi_pvt::pri.

08525 {
08526    struct dahdi_pvt *p;
08527    p = pri->crvs;
08528    while (p) {
08529       if (p->channel == crv)
08530          return p;
08531       p = p->next;
08532    }
08533    return NULL;
08534 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 2788 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchans, NUM_DCHANS, and dahdi_pri::pri.

02789 {
02790    int oldslot = -1;
02791    struct pri *old;
02792    int newslot = -1;
02793    int x;
02794    old = pri->pri;
02795    for (x = 0; x < NUM_DCHANS; x++) {
02796       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
02797          newslot = x;
02798       if (pri->dchans[x] == old) {
02799          oldslot = x;
02800       }
02801    }
02802    if (newslot < 0) {
02803       newslot = 0;
02804       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
02805          pri->dchannels[newslot]);
02806    }
02807    if (old && (oldslot != newslot))
02808       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
02809          pri->dchannels[oldslot], pri->dchannels[newslot]);
02810    pri->pri = pri->dchans[newslot];
02811    return 0;
02812 }

static int pri_find_empty_chan ( struct dahdi_pri pri,
int  backwards 
) [static]

Definition at line 8256 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::inalarm, LOG_DEBUG, dahdi_pvt::logicalspan, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::prioffset, and dahdi_pri::pvts.

Referenced by dahdi_request().

08257 {
08258    int x;
08259    if (backwards)
08260       x = pri->numchans;
08261    else
08262       x = 0;
08263    for (;;) {
08264       if (backwards && (x < 0))
08265          break;
08266       if (!backwards && (x >= pri->numchans))
08267          break;
08268       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
08269          ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
08270             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
08271          return x;
08272       }
08273       if (backwards)
08274          x--;
08275       else
08276          x++;
08277    }
08278    return -1;
08279 }

static int pri_find_principle ( struct dahdi_pri pri,
int  channel 
) [static]

Definition at line 8537 of file chan_dahdi.c.

References dahdi_pvt::logicalspan, dahdi_pri::numchans, pri_active_dchan_fd(), PRI_CHANNEL, PRI_EXPLICIT, PRI_SPAN, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::pvts, and dahdi_pvt::span.

08538 {
08539    int x;
08540    int span = PRI_SPAN(channel);
08541    int spanfd;
08542    struct dahdi_params param;
08543    int principle = -1;
08544    int explicit = PRI_EXPLICIT(channel);
08545    channel = PRI_CHANNEL(channel);
08546 
08547    if (!explicit) {
08548       spanfd = pri_active_dchan_fd(pri);
08549       memset(&param, 0, sizeof(param));
08550       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
08551          return -1;
08552       span = pris[param.spanno - 1].prilogicalspan;
08553    }
08554 
08555    for (x = 0; x < pri->numchans; x++) {
08556       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
08557          principle = x;
08558          break;
08559       }
08560    }
08561    
08562    return principle;
08563 }

static int pri_fixup_principle ( struct dahdi_pri pri,
int  principle,
q931_call *  c 
) [static]

Definition at line 8565 of file chan_dahdi.c.

References ast_log(), ast_string_field_build, ast_verbose(), dahdi_pvt::call, dahdi_chan_name, name, dahdi_pri::numchans, option_verbose, dahdi_pvt::pri, dahdi_pri::pvts, SUB_REAL, dahdi_pri::trunkgroup, and VERBOSE_PREFIX_3.

08566 {
08567    int x;
08568    struct dahdi_pvt *crv;
08569    if (!c) {
08570       if (principle < 0)
08571          return -1;
08572       return principle;
08573    }
08574    if ((principle > -1) && 
08575       (principle < pri->numchans) && 
08576       (pri->pvts[principle]) && 
08577       (pri->pvts[principle]->call == c))
08578       return principle;
08579    /* First, check for other bearers */
08580    for (x = 0; x < pri->numchans; x++) {
08581       if (!pri->pvts[x])
08582          continue;
08583       if (pri->pvts[x]->call == c) {
08584          /* Found our call */
08585          if (principle != x) {
08586             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
08587 
08588             if (option_verbose > 2)
08589                ast_verbose(VERBOSE_PREFIX_3 "Moving call from channel %d to channel %d\n",
08590                   old->channel, new->channel);
08591             if (new->owner) {
08592                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
08593                   old->channel, new->channel, new->channel);
08594                return -1;
08595             }
08596             /* Fix it all up now */
08597             new->owner = old->owner;
08598             old->owner = NULL;
08599             if (new->owner) {
08600                ast_string_field_build(new->owner, name, "%s/%d:%d-%d", dahdi_chan_name, pri->trunkgroup, new->channel, 1);
08601                new->owner->tech_pvt = new;
08602                new->owner->fds[0] = new->subs[SUB_REAL].dfd;
08603                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
08604                old->subs[SUB_REAL].owner = NULL;
08605             } else
08606                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);
08607             new->call = old->call;
08608             old->call = NULL;
08609 
08610             /* Copy any DSP that may be present */
08611             new->dsp = old->dsp;
08612             new->dsp_features = old->dsp_features;
08613             old->dsp = NULL;
08614             old->dsp_features = 0;
08615          }
08616          return principle;
08617       }
08618    }
08619    /* Now check for a CRV with no bearer */
08620    crv = pri->crvs;
08621    while (crv) {
08622       if (crv->call == c) {
08623          /* This is our match...  Perform some basic checks */
08624          if (crv->bearer)
08625             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
08626          else if (pri->pvts[principle]->owner) 
08627             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
08628          else {
08629             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
08630                wakeup the potential sleeper */
08631             dahdi_close_sub(crv, SUB_REAL);
08632             pri->pvts[principle]->call = crv->call;
08633             pri_assign_bearer(crv, pri, pri->pvts[principle]);
08634             ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
08635                            pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
08636                            pri->trunkgroup, crv->channel);
08637             wakeup_sub(crv, SUB_REAL, pri);
08638          }
08639          return principle;
08640       }
08641       crv = crv->next;
08642    }
08643    ast_log(LOG_WARNING, "Call specified, but not found?\n");
08644    return -1;
08645 }

static int pri_grab ( struct dahdi_pvt pvt,
struct dahdi_pri pri 
) [inline, static]

Definition at line 1072 of file chan_dahdi.c.

References ast_mutex_trylock, AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_pri::master, and dahdi_pvt::pri.

Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_write(), and send_keypad_facility_exec().

01073 {
01074    int res;
01075    /* Grab the lock first */
01076    do {
01077       res = ast_mutex_trylock(&pri->lock);
01078       if (res) {
01079          DEADLOCK_AVOIDANCE(&pvt->lock);
01080       }
01081    } while (res);
01082    /* Then break the poll */
01083    if (pri->master != AST_PTHREADT_NULL)
01084       pthread_kill(pri->master, SIGURG);
01085    return 0;
01086 }

static int pri_hangup_all ( struct dahdi_pvt p,
struct dahdi_pri pri 
) [static]

Definition at line 8805 of file chan_dahdi.c.

References ast_mutex_lock, ast_mutex_trylock, ast_mutex_unlock, ast_queue_hangup(), DEADLOCK_AVOIDANCE, ast_channel::lock, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

08806 {
08807    int x;
08808    int redo;
08809    ast_mutex_unlock(&pri->lock);
08810    ast_mutex_lock(&p->lock);
08811    do {
08812       redo = 0;
08813       for (x = 0; x < 3; x++) {
08814          while (p->subs[x].owner && ast_mutex_trylock(&p->subs[x].owner->lock)) {
08815             redo++;
08816             DEADLOCK_AVOIDANCE(&p->lock);
08817          }
08818          if (p->subs[x].owner) {
08819             ast_queue_hangup(p->subs[x].owner);
08820             ast_mutex_unlock(&p->subs[x].owner->lock);
08821          }
08822       }
08823    } while (redo);
08824    ast_mutex_unlock(&p->lock);
08825    ast_mutex_lock(&pri->lock);
08826    return 0;
08827 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 2736 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, NUM_DCHANS, and dahdi_pvt::pri.

Referenced by pri_dchannel().

02737 {
02738    int x;
02739    for (x = 0; x < NUM_DCHANS; x++) {
02740       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02741          return 1;
02742    }
02743    return 0;
02744 }

static char* pri_order ( int  level  )  [static]

Definition at line 2759 of file chan_dahdi.c.

Referenced by handle_pri_show_span().

02760 {
02761    switch (level) {
02762    case 0:
02763       return "Primary";
02764    case 1:
02765       return "Secondary";
02766    case 2:
02767       return "Tertiary";
02768    case 3:
02769       return "Quaternary";
02770    default:
02771       return "<Unknown>";
02772    }     
02773 }

static void pri_rel ( struct dahdi_pri pri  )  [inline, static]

Definition at line 361 of file chan_dahdi.c.

References ast_mutex_unlock, and dahdi_pri::pri.

Referenced by dahdi_answer(), dahdi_call(), dahdi_digit_begin(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_write(), and send_keypad_facility_exec().

00362 {
00363    ast_mutex_unlock(&pri->lock);
00364 }

static int pri_resolve_span ( int *  span,
int  channel,
int  offset,
struct dahdi_spaninfo *  si 
) [static]

Definition at line 7496 of file chan_dahdi.c.

References ast_log(), DCHAN_PROVISIONED, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::mastertrunkgroup, NUM_SPANS, dahdi_pri::offset, pris, and dahdi_pri::span.

Referenced by mkintf().

07497 {
07498    int x;
07499    int trunkgroup;
07500    /* Get appropriate trunk group if there is one */
07501    trunkgroup = pris[*span].mastertrunkgroup;
07502    if (trunkgroup) {
07503       /* Select a specific trunk group */
07504       for (x = 0; x < NUM_SPANS; x++) {
07505          if (pris[x].trunkgroup == trunkgroup) {
07506             *span = x;
07507             return 0;
07508          }
07509       }
07510       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
07511       *span = -1;
07512    } else {
07513       if (pris[*span].trunkgroup) {
07514          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
07515          *span = -1;
07516       } else if (pris[*span].mastertrunkgroup) {
07517          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
07518          *span = -1;
07519       } else {
07520          if (si->totalchans == 31) {
07521             /* E1 */
07522             pris[*span].dchannels[0] = 16 + offset;
07523          } else if (si->totalchans == 24) {
07524             /* T1 or J1 */
07525             pris[*span].dchannels[0] = 24 + offset;
07526          } else if (si->totalchans == 3) {
07527             /* BRI */
07528             pris[*span].dchannels[0] = 3 + offset;
07529          } else {
07530             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);
07531             *span = -1;
07532             return 0;
07533          }
07534          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
07535          pris[*span].offset = offset;
07536          pris[*span].span = *span + 1;
07537       }
07538    }
07539    return 0;
07540 }

static int process_dahdi ( struct dahdi_chan_conf confp,
const char *  cat,
struct ast_variable v,
int  reload,
int  skipchannels 
) [static]

Definition at line 11354 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), ast_strlen_zero(), ast_true(), ast_verbose(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, dahdi_pvt::cid_name, dahdi_pvt::cid_num, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, dahdi_pri::facilityenable, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_pvt::language, ast_variable::lineno, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, option_verbose, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, dahdi_pvt::pulse, dahdi_pvt::radio, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SFWINK, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, ast_variable::value, and VERBOSE_PREFIX_3.

Referenced by setup_dahdi().

11355 {
11356    struct dahdi_pvt *tmp;
11357    int y;
11358    int found_pseudo = 0;
11359         char dahdichan[MAX_CHANLIST_LEN] = {};
11360 
11361    for (; v; v = v->next) {
11362       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
11363          continue;
11364 
11365       /* Create the interface list */
11366       if (!strcasecmp(v->name, "channel")
11367 #ifdef HAVE_PRI
11368           || !strcasecmp(v->name, "crv")
11369 #endif         
11370          ) {
11371          int iscrv;
11372          if (skipchannels)
11373             continue;
11374          iscrv = !strcasecmp(v->name, "crv");
11375          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
11376                return -1;
11377       } else if (!strcasecmp(v->name, "buffers")) {
11378          int res;
11379          char policy[21] = "";
11380 
11381          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
11382          if (res != 2) {
11383             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
11384             confp->chan.buf_no = numbufs;
11385             continue;
11386          }
11387          if (confp->chan.buf_no < 0)
11388             confp->chan.buf_no = numbufs;
11389          if (!strcasecmp(policy, "full")) {
11390             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
11391          } else if (!strcasecmp(policy, "immediate")) {
11392             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
11393          } else {
11394             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
11395          }
11396       } else if (!strcasecmp(v->name, "zapchan") || !strcasecmp(v->name, "dahdichan")) {
11397          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
11398          if (v->name[0] == 'z' || v->name[0] == 'Z') {
11399             ast_log(LOG_WARNING, "Option zapchan has been deprecated in favor of dahdichan (found in [%s])\n", cat);
11400          }
11401       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
11402          if (ast_true(v->value))
11403             confp->chan.usedistinctiveringdetection = 1;
11404       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
11405          if (ast_true(v->value))
11406             distinctiveringaftercid = 1;
11407       } else if (!strcasecmp(v->name, "dring1context")) {
11408          ast_copy_string(drings.ringContext[0].contextData, v->value, sizeof(drings.ringContext[0].contextData));
11409       } else if (!strcasecmp(v->name, "dring2context")) {
11410          ast_copy_string(drings.ringContext[1].contextData, v->value, sizeof(drings.ringContext[1].contextData));
11411       } else if (!strcasecmp(v->name, "dring3context")) {
11412          ast_copy_string(drings.ringContext[2].contextData, v->value, sizeof(drings.ringContext[2].contextData));
11413       } else if (!strcasecmp(v->name, "dring1")) {
11414          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[0].ring[0], &drings.ringnum[0].ring[1], &drings.ringnum[0].ring[2]);
11415       } else if (!strcasecmp(v->name, "dring2")) {
11416          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[1].ring[0], &drings.ringnum[1].ring[1], &drings.ringnum[1].ring[2]);
11417       } else if (!strcasecmp(v->name, "dring3")) {
11418          sscanf(v->value, "%30d,%30d,%30d", &drings.ringnum[2].ring[0], &drings.ringnum[2].ring[1], &drings.ringnum[2].ring[2]);
11419       } else if (!strcasecmp(v->name, "usecallerid")) {
11420          confp->chan.use_callerid = ast_true(v->value);
11421       } else if (!strcasecmp(v->name, "cidsignalling")) {
11422          if (!strcasecmp(v->value, "bell"))
11423             confp->chan.cid_signalling = CID_SIG_BELL;
11424          else if (!strcasecmp(v->value, "v23"))
11425             confp->chan.cid_signalling = CID_SIG_V23;
11426          else if (!strcasecmp(v->value, "dtmf"))
11427             confp->chan.cid_signalling = CID_SIG_DTMF;
11428          else if (!strcasecmp(v->value, "smdi"))
11429             confp->chan.cid_signalling = CID_SIG_SMDI;
11430          else if (!strcasecmp(v->value, "v23_jp"))
11431             confp->chan.cid_signalling = CID_SIG_V23_JP;
11432          else if (ast_true(v->value))
11433             confp->chan.cid_signalling = CID_SIG_BELL;
11434       } else if (!strcasecmp(v->name, "cidstart")) {
11435          if (!strcasecmp(v->value, "ring"))
11436             confp->chan.cid_start = CID_START_RING;
11437          else if (!strcasecmp(v->value, "polarity"))
11438             confp->chan.cid_start = CID_START_POLARITY;
11439          else if (ast_true(v->value))
11440             confp->chan.cid_start = CID_START_RING;
11441       } else if (!strcasecmp(v->name, "threewaycalling")) {
11442          confp->chan.threewaycalling = ast_true(v->value);
11443       } else if (!strcasecmp(v->name, "cancallforward")) {
11444          confp->chan.cancallforward = ast_true(v->value);
11445       } else if (!strcasecmp(v->name, "relaxdtmf")) {
11446          if (ast_true(v->value)) 
11447             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
11448          else
11449             confp->chan.dtmfrelax = 0;
11450       } else if (!strcasecmp(v->name, "mailbox")) {
11451          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
11452       } else if (!strcasecmp(v->name, "hasvoicemail")) {
11453          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
11454             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
11455          }
11456       } else if (!strcasecmp(v->name, "adsi")) {
11457          confp->chan.adsi = ast_true(v->value);
11458       } else if (!strcasecmp(v->name, "usesmdi")) {
11459          confp->chan.use_smdi = ast_true(v->value);
11460       } else if (!strcasecmp(v->name, "smdiport")) {
11461          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
11462       } else if (!strcasecmp(v->name, "transfer")) {
11463          confp->chan.transfer = ast_true(v->value);
11464       } else if (!strcasecmp(v->name, "canpark")) {
11465          confp->chan.canpark = ast_true(v->value);
11466       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
11467          confp->chan.echocanbridged = ast_true(v->value);
11468       } else if (!strcasecmp(v->name, "busydetect")) {
11469          confp->chan.busydetect = ast_true(v->value);
11470       } else if (!strcasecmp(v->name, "busycount")) {
11471          confp->chan.busycount = atoi(v->value);
11472       } else if (!strcasecmp(v->name, "silencethreshold")) {
11473             confp->chan.silencethreshold = atoi(v->value);
11474       } else if (!strcasecmp(v->name, "busycompare")) {
11475             confp->chan.busycompare = ast_true(v->value);
11476       } else if (!strcasecmp(v->name, "busypattern")) {
11477          int count = sscanf(v->value, "%30d,%30d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
11478          if (count == 1)
11479             confp->chan.busyquietlength = 0;
11480          else if (count < 1)
11481                ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength]\n");
11482       } else if (!strcasecmp(v->name, "busyfuzziness")) {
11483             confp->chan.busyfuzziness = atoi(v->value);
11484       } else if (!strcasecmp(v->name, "callprogress")) {
11485          if (ast_true(v->value))
11486             confp->chan.callprogress |= 1;
11487          else
11488             confp->chan.callprogress &= ~1;
11489       } else if (!strcasecmp(v->name, "faxdetect")) {
11490          if (!strcasecmp(v->value, "incoming")) {
11491             confp->chan.callprogress |= 4;
11492             confp->chan.callprogress &= ~2;
11493          } else if (!strcasecmp(v->value, "outgoing")) {
11494             confp->chan.callprogress &= ~4;
11495             confp->chan.callprogress |= 2;
11496          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
11497             confp->chan.callprogress |= 6;
11498          else
11499             confp->chan.callprogress &= ~6;
11500       } else if (!strcasecmp(v->name, "echocancel")) {
11501          if (!ast_strlen_zero(v->value)) {
11502             y = atoi(v->value);
11503          } else
11504             y = 0;
11505          if ((y == 32) || (y == 64) || (y == 128) || (y == 256) || (y == 512) || (y == 1024))
11506             confp->chan.echocancel = y;
11507          else {
11508             confp->chan.echocancel = ast_true(v->value);
11509             if (confp->chan.echocancel)
11510                confp->chan.echocancel=128;
11511          }
11512       } else if (!strcasecmp(v->name, "echotraining")) {
11513          if (sscanf(v->value, "%30d", &y) == 1) {
11514             if ((y < 10) || (y > 4000)) {
11515                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d\n", v->lineno);              
11516             } else {
11517                confp->chan.echotraining = y;
11518             }
11519          } else if (ast_true(v->value)) {
11520             confp->chan.echotraining = 400;
11521          } else
11522             confp->chan.echotraining = 0;
11523       } else if (!strcasecmp(v->name, "hidecallerid")) {
11524          confp->chan.hidecallerid = ast_true(v->value);
11525       } else if (!strcasecmp(v->name, "hidecalleridname")) {
11526          confp->chan.hidecalleridname = ast_true(v->value);
11527       } else if (!strcasecmp(v->name, "pulsedial")) {
11528          confp->chan.pulse = ast_true(v->value);
11529       } else if (!strcasecmp(v->name, "callreturn")) {
11530          confp->chan.callreturn = ast_true(v->value);
11531       } else if (!strcasecmp(v->name, "callwaiting")) {
11532          confp->chan.callwaiting = ast_true(v->value);
11533       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
11534          confp->chan.callwaitingcallerid = ast_true(v->value);
11535       } else if (!strcasecmp(v->name, "context")) {
11536          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
11537       } else if (!strcasecmp(v->name, "language")) {
11538          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
11539       } else if (!strcasecmp(v->name, "progzone")) {
11540          ast_copy_string(progzone, v->value, sizeof(progzone));
11541       } else if (!strcasecmp(v->name, "mohinterpret") 
11542          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
11543          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
11544       } else if (!strcasecmp(v->name, "mohsuggest")) {
11545          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
11546       } else if (!strcasecmp(v->name, "stripmsd")) {
11547          confp->chan.stripmsd = atoi(v->value);
11548       } else if (!strcasecmp(v->name, "jitterbuffers")) {
11549          numbufs = atoi(v->value);
11550       } else if (!strcasecmp(v->name, "group")) {
11551          confp->chan.group = ast_get_group(v->value);
11552       } else if (!strcasecmp(v->name, "callgroup")) {
11553          confp->chan.callgroup = ast_get_group(v->value);
11554       } else if (!strcasecmp(v->name, "pickupgroup")) {
11555          confp->chan.pickupgroup = ast_get_group(v->value);
11556       } else if (!strcasecmp(v->name, "immediate")) {
11557          confp->chan.immediate = ast_true(v->value);
11558       } else if (!strcasecmp(v->name, "transfertobusy")) {
11559          confp->chan.transfertobusy = ast_true(v->value);
11560       } else if (!strcasecmp(v->name, "rxgain")) {
11561          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
11562             ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
11563          }
11564       } else if (!strcasecmp(v->name, "txgain")) {
11565          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
11566             ast_log(LOG_WARNING, "Invalid txgain: %s\n", v->value);
11567          }
11568       } else if (!strcasecmp(v->name, "tonezone")) {
11569          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
11570             ast_log(LOG_WARNING, "Invalid tonezone: %s\n", v->value);
11571          }
11572       } else if (!strcasecmp(v->name, "callerid")) {
11573          if (!strcasecmp(v->value, "asreceived")) {
11574             confp->chan.cid_num[0] = '\0';
11575             confp->chan.cid_name[0] = '\0';
11576          } else {
11577             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
11578          } 
11579       } else if (!strcasecmp(v->name, "fullname")) {
11580          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
11581       } else if (!strcasecmp(v->name, "cid_number")) {
11582          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
11583       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer") || !strcasecmp(v->name, "useincomingcalleridonzaptransfer")) {
11584          confp->chan.dahditrcallerid = ast_true(v->value);
11585          if (strstr(v->name, "zap")) {
11586             ast_log(LOG_WARNING, "Option useincomingcalleridonzaptransfer has been deprecated in favor of useincomingcalleridondahditransfer (in [%s]).\n", cat);
11587          }
11588       } else if (!strcasecmp(v->name, "restrictcid")) {
11589          confp->chan.restrictcid = ast_true(v->value);
11590       } else if (!strcasecmp(v->name, "usecallingpres")) {
11591          confp->chan.use_callingpres = ast_true(v->value);
11592       } else if (!strcasecmp(v->name, "accountcode")) {
11593          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
11594       } else if (!strcasecmp(v->name, "amaflags")) {
11595          y = ast_cdr_amaflags2int(v->value);
11596          if (y < 0) 
11597             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
11598          else
11599             confp->chan.amaflags = y;
11600       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
11601          confp->chan.polarityonanswerdelay = atoi(v->value);
11602       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
11603          confp->chan.answeronpolarityswitch = ast_true(v->value);
11604       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
11605          confp->chan.hanguponpolarityswitch = ast_true(v->value);
11606       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
11607          confp->chan.sendcalleridafter = atoi(v->value);
11608       } else if (reload != 1) {
11609           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
11610             confp->chan.outsigmod = -1;
11611             if (!strcasecmp(v->value, "em")) {
11612                confp->chan.sig = SIG_EM;
11613             } else if (!strcasecmp(v->value, "em_e1")) {
11614                confp->chan.sig = SIG_EM_E1;
11615             } else if (!strcasecmp(v->value, "em_w")) {
11616                confp->chan.sig = SIG_EMWINK;
11617                confp->chan.radio = 0;
11618             } else if (!strcasecmp(v->value, "fxs_ls")) {
11619                confp->chan.sig = SIG_FXSLS;
11620                confp->chan.radio = 0;
11621             } else if (!strcasecmp(v->value, "fxs_gs")) {
11622                confp->chan.sig = SIG_FXSGS;
11623                confp->chan.radio = 0;
11624             } else if (!strcasecmp(v->value, "fxs_ks")) {
11625                confp->chan.sig = SIG_FXSKS;
11626                confp->chan.radio = 0;
11627             } else if (!strcasecmp(v->value, "fxo_ls")) {
11628                confp->chan.sig = SIG_FXOLS;
11629                confp->chan.radio = 0;
11630             } else if (!strcasecmp(v->value, "fxo_gs")) {
11631                confp->chan.sig = SIG_FXOGS;
11632                confp->chan.radio = 0;
11633             } else if (!strcasecmp(v->value, "fxo_ks")) {
11634                confp->chan.sig = SIG_FXOKS;
11635                confp->chan.radio = 0;
11636             } else if (!strcasecmp(v->value, "fxs_rx")) {
11637                confp->chan.sig = SIG_FXSKS;
11638                confp->chan.radio = 1;
11639             } else if (!strcasecmp(v->value, "fxo_rx")) {
11640                confp->chan.sig = SIG_FXOLS;
11641                confp->chan.radio = 1;
11642             } else if (!strcasecmp(v->value, "fxs_tx")) {
11643                confp->chan.sig = SIG_FXSLS;
11644                confp->chan.radio = 1;
11645             } else if (!strcasecmp(v->value, "fxo_tx")) {
11646                confp->chan.sig = SIG_FXOGS;
11647                confp->chan.radio = 1;
11648             } else if (!strcasecmp(v->value, "em_rx")) {
11649                confp->chan.sig = SIG_EM;
11650                confp->chan.radio = 1;
11651             } else if (!strcasecmp(v->value, "em_tx")) {
11652                confp->chan.sig = SIG_EM;
11653                confp->chan.radio = 1;
11654             } else if (!strcasecmp(v->value, "em_rxtx")) {
11655                confp->chan.sig = SIG_EM;
11656                confp->chan.radio = 2;
11657             } else if (!strcasecmp(v->value, "em_txrx")) {
11658                confp->chan.sig = SIG_EM;
11659                confp->chan.radio = 2;
11660             } else if (!strcasecmp(v->value, "sf")) {
11661                confp->chan.sig = SIG_SF;
11662                confp->chan.radio = 0;
11663             } else if (!strcasecmp(v->value, "sf_w")) {
11664                confp->chan.sig = SIG_SFWINK;
11665                confp->chan.radio = 0;
11666             } else if (!strcasecmp(v->value, "sf_featd")) {
11667                confp->chan.sig = SIG_FEATD;
11668                confp->chan.radio = 0;
11669             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11670                confp->chan.sig = SIG_FEATDMF;
11671                confp->chan.radio = 0;
11672             } else if (!strcasecmp(v->value, "sf_featb")) {
11673                confp->chan.sig = SIG_SF_FEATB;
11674                confp->chan.radio = 0;
11675             } else if (!strcasecmp(v->value, "sf")) {
11676                confp->chan.sig = SIG_SF;
11677                confp->chan.radio = 0;
11678             } else if (!strcasecmp(v->value, "sf_rx")) {
11679                confp->chan.sig = SIG_SF;
11680                confp->chan.radio = 1;
11681             } else if (!strcasecmp(v->value, "sf_tx")) {
11682                confp->chan.sig = SIG_SF;
11683                confp->chan.radio = 1;
11684             } else if (!strcasecmp(v->value, "sf_rxtx")) {
11685                confp->chan.sig = SIG_SF;
11686                confp->chan.radio = 2;
11687             } else if (!strcasecmp(v->value, "sf_txrx")) {
11688                confp->chan.sig = SIG_SF;
11689                confp->chan.radio = 2;
11690             } else if (!strcasecmp(v->value, "featd")) {
11691                confp->chan.sig = SIG_FEATD;
11692                confp->chan.radio = 0;
11693             } else if (!strcasecmp(v->value, "featdmf")) {
11694                confp->chan.sig = SIG_FEATDMF;
11695                confp->chan.radio = 0;
11696             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11697                confp->chan.sig = SIG_FEATDMF_TA;
11698                confp->chan.radio = 0;
11699             } else if (!strcasecmp(v->value, "e911")) {
11700                confp->chan.sig = SIG_E911;
11701                confp->chan.radio = 0;
11702             } else if (!strcasecmp(v->value, "fgccama")) {
11703                confp->chan.sig = SIG_FGC_CAMA;
11704                confp->chan.radio = 0;
11705             } else if (!strcasecmp(v->value, "fgccamamf")) {
11706                confp->chan.sig = SIG_FGC_CAMAMF;
11707                confp->chan.radio = 0;
11708             } else if (!strcasecmp(v->value, "featb")) {
11709                confp->chan.sig = SIG_FEATB;
11710                confp->chan.radio = 0;
11711 #ifdef HAVE_PRI
11712             } else if (!strcasecmp(v->value, "pri_net")) {
11713                confp->chan.radio = 0;
11714                confp->chan.sig = SIG_PRI;
11715                confp->pri.nodetype = PRI_NETWORK;
11716             } else if (!strcasecmp(v->value, "pri_cpe")) {
11717                confp->chan.sig = SIG_PRI;
11718                confp->chan.radio = 0;
11719                confp->pri.nodetype = PRI_CPE;
11720             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
11721                confp->chan.sig = SIG_GR303FXOKS;
11722                confp->chan.radio = 0;
11723                confp->pri.nodetype = PRI_NETWORK;
11724             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
11725                confp->chan.sig = SIG_GR303FXSKS;
11726                confp->chan.radio = 0;
11727                confp->pri.nodetype = PRI_CPE;
11728 #endif
11729             } else {
11730                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11731             }
11732           } else if (!strcasecmp(v->name, "outsignalling")) {
11733             if (!strcasecmp(v->value, "em")) {
11734                confp->chan.outsigmod = SIG_EM;
11735             } else if (!strcasecmp(v->value, "em_e1")) {
11736                confp->chan.outsigmod = SIG_EM_E1;
11737             } else if (!strcasecmp(v->value, "em_w")) {
11738                confp->chan.outsigmod = SIG_EMWINK;
11739             } else if (!strcasecmp(v->value, "sf")) {
11740                confp->chan.outsigmod = SIG_SF;
11741             } else if (!strcasecmp(v->value, "sf_w")) {
11742                confp->chan.outsigmod = SIG_SFWINK;
11743             } else if (!strcasecmp(v->value, "sf_featd")) {
11744                confp->chan.outsigmod = SIG_FEATD;
11745             } else if (!strcasecmp(v->value, "sf_featdmf")) {
11746                confp->chan.outsigmod = SIG_FEATDMF;
11747             } else if (!strcasecmp(v->value, "sf_featb")) {
11748                confp->chan.outsigmod = SIG_SF_FEATB;
11749             } else if (!strcasecmp(v->value, "sf")) {
11750                confp->chan.outsigmod = SIG_SF;
11751             } else if (!strcasecmp(v->value, "featd")) {
11752                confp->chan.outsigmod = SIG_FEATD;
11753             } else if (!strcasecmp(v->value, "featdmf")) {
11754                confp->chan.outsigmod = SIG_FEATDMF;
11755             } else if (!strcasecmp(v->value, "featdmf_ta")) {
11756                confp->chan.outsigmod = SIG_FEATDMF_TA;
11757             } else if (!strcasecmp(v->value, "e911")) {
11758                confp->chan.outsigmod = SIG_E911;
11759             } else if (!strcasecmp(v->value, "fgccama")) {
11760                confp->chan.outsigmod = SIG_FGC_CAMA;
11761             } else if (!strcasecmp(v->value, "fgccamamf")) {
11762                confp->chan.outsigmod = SIG_FGC_CAMAMF;
11763             } else if (!strcasecmp(v->value, "featb")) {
11764                confp->chan.outsigmod = SIG_FEATB;
11765             } else {
11766                ast_log(LOG_ERROR, "Unknown signalling method '%s'\n", v->value);
11767             }
11768 #ifdef HAVE_PRI
11769          } else if (!strcasecmp(v->name, "pridialplan")) {
11770             if (!strcasecmp(v->value, "national")) {
11771                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
11772             } else if (!strcasecmp(v->value, "unknown")) {
11773                confp->pri.dialplan = PRI_UNKNOWN + 1;
11774             } else if (!strcasecmp(v->value, "private")) {
11775                confp->pri.dialplan = PRI_PRIVATE + 1;
11776             } else if (!strcasecmp(v->value, "international")) {
11777                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
11778             } else if (!strcasecmp(v->value, "local")) {
11779                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
11780             } else if (!strcasecmp(v->value, "dynamic")) {
11781                confp->pri.dialplan = -1;
11782             } else {
11783                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11784             }
11785          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
11786             if (!strcasecmp(v->value, "national")) {
11787                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
11788             } else if (!strcasecmp(v->value, "unknown")) {
11789                confp->pri.localdialplan = PRI_UNKNOWN + 1;
11790             } else if (!strcasecmp(v->value, "private")) {
11791                confp->pri.localdialplan = PRI_PRIVATE + 1;
11792             } else if (!strcasecmp(v->value, "international")) {
11793                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
11794             } else if (!strcasecmp(v->value, "local")) {
11795                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
11796             } else if (!strcasecmp(v->value, "dynamic")) {
11797                confp->pri.localdialplan = -1;
11798             } else {
11799                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
11800             }
11801          } else if (!strcasecmp(v->name, "switchtype")) {
11802             if (!strcasecmp(v->value, "national")) 
11803                confp->pri.switchtype = PRI_SWITCH_NI2;
11804             else if (!strcasecmp(v->value, "ni1"))
11805                confp->pri.switchtype = PRI_SWITCH_NI1;
11806             else if (!strcasecmp(v->value, "dms100"))
11807                confp->pri.switchtype = PRI_SWITCH_DMS100;
11808             else if (!strcasecmp(v->value, "4ess"))
11809                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
11810             else if (!strcasecmp(v->value, "5ess"))
11811                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
11812             else if (!strcasecmp(v->value, "euroisdn"))
11813                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
11814             else if (!strcasecmp(v->value, "qsig"))
11815                confp->pri.switchtype = PRI_SWITCH_QSIG;
11816             else {
11817                ast_log(LOG_ERROR, "Unknown switchtype '%s'\n", v->value);
11818                return -1;
11819             }
11820          } else if (!strcasecmp(v->name, "nsf")) {
11821             if (!strcasecmp(v->value, "sdn"))
11822                confp->pri.nsf = PRI_NSF_SDN;
11823             else if (!strcasecmp(v->value, "megacom"))
11824                confp->pri.nsf = PRI_NSF_MEGACOM;
11825             else if (!strcasecmp(v->value, "tollfreemegacom"))
11826                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
11827             else if (!strcasecmp(v->value, "accunet"))
11828                confp->pri.nsf = PRI_NSF_ACCUNET;
11829             else if (!strcasecmp(v->value, "none"))
11830                confp->pri.nsf = PRI_NSF_NONE;
11831             else {
11832                ast_log(LOG_WARNING, "Unknown network-specific facility '%s'\n", v->value);
11833                confp->pri.nsf = PRI_NSF_NONE;
11834             }
11835          } else if (!strcasecmp(v->name, "priindication")) {
11836             if (!strcasecmp(v->value, "outofband"))
11837                confp->chan.priindication_oob = 1;
11838             else if (!strcasecmp(v->value, "inband"))
11839                confp->chan.priindication_oob = 0;
11840             else
11841                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
11842                   v->value, v->lineno);
11843          } else if (!strcasecmp(v->name, "priexclusive")) {
11844             confp->chan.priexclusive = ast_true(v->value);
11845          } else if (!strcasecmp(v->name, "internationalprefix")) {
11846             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
11847          } else if (!strcasecmp(v->name, "nationalprefix")) {
11848             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
11849          } else if (!strcasecmp(v->name, "localprefix")) {
11850             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
11851          } else if (!strcasecmp(v->name, "privateprefix")) {
11852             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
11853          } else if (!strcasecmp(v->name, "unknownprefix")) {
11854             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
11855          } else if (!strcasecmp(v->name, "resetinterval")) {
11856             if (!strcasecmp(v->value, "never"))
11857                confp->pri.resetinterval = -1;
11858             else if (atoi(v->value) >= 60)
11859                confp->pri.resetinterval = atoi(v->value);
11860             else
11861                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d\n",
11862                   v->value, v->lineno);
11863          } else if (!strcasecmp(v->name, "minunused")) {
11864             confp->pri.minunused = atoi(v->value);
11865          } else if (!strcasecmp(v->name, "minidle")) {
11866             confp->pri.minidle = atoi(v->value); 
11867          } else if (!strcasecmp(v->name, "idleext")) {
11868             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
11869          } else if (!strcasecmp(v->name, "idledial")) {
11870             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
11871          } else if (!strcasecmp(v->name, "overlapdial")) {
11872             confp->pri.overlapdial = ast_true(v->value);
11873 #ifdef HAVE_PRI_INBANDDISCONNECT
11874          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
11875             confp->pri.inbanddisconnect = ast_true(v->value);
11876 #endif
11877          } else if (!strcasecmp(v->name, "pritimer")) {
11878 #ifdef PRI_GETSET_TIMERS
11879             char tmp[20];
11880             char *timerc;
11881             char *c;
11882             int timer;
11883             int timeridx;
11884 
11885             ast_copy_string(tmp, v->value, sizeof(tmp));
11886             c = tmp;
11887             timerc = strsep(&c, ",");
11888             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
11889                timeridx = pri_timer2idx(timerc);
11890                timer = atoi(c);
11891                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
11892                   ast_log(LOG_WARNING,
11893                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
11894                      v->lineno);
11895                } else if (!timer) {
11896                   ast_log(LOG_WARNING,
11897                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
11898                      c, timerc, v->lineno);
11899                } else {
11900                   pritimers[timeridx] = timer;
11901                }
11902             } else {
11903                ast_log(LOG_WARNING,
11904                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
11905                   v->value, v->lineno);
11906             }
11907 #endif /* PRI_GETSET_TIMERS */
11908          } else if (!strcasecmp(v->name, "facilityenable")) {
11909             confp->pri.facilityenable = ast_true(v->value);
11910 #endif /* HAVE_PRI */
11911          } else if (!strcasecmp(v->name, "cadence")) {
11912             /* setup to scan our argument */
11913             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
11914             int i;
11915             struct dahdi_ring_cadence new_cadence;
11916             int cid_location = -1;
11917             int firstcadencepos = 0;
11918             char original_args[80];
11919             int cadence_is_ok = 1;
11920 
11921             ast_copy_string(original_args, v->value, sizeof(original_args));
11922             /* 16 cadences allowed (8 pairs) */
11923             element_count = sscanf(v->value, "%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d,%30d", &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]);
11924    
11925             /* Cadence must be even (on/off) */
11926             if (element_count % 2 == 1) {
11927                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s\n",original_args);
11928                cadence_is_ok = 0;
11929             }
11930    
11931             /* Ring cadences cannot be negative */
11932             for (i = 0; i < element_count; i++) {
11933                if (c[i] == 0) {
11934                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s\n", original_args);
11935                   cadence_is_ok = 0;
11936                   break;
11937                } else if (c[i] < 0) {
11938                   if (i % 2 == 1) {
11939                      /* Silence duration, negative possibly okay */
11940                      if (cid_location == -1) {
11941                         cid_location = i;
11942                         c[i] *= -1;
11943                      } else {
11944                         ast_log(LOG_ERROR, "CID location specified twice: %s\n",original_args);
11945                         cadence_is_ok = 0;
11946                         break;
11947                      }
11948                   } else {
11949                      if (firstcadencepos == 0) {
11950                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
11951                                  /* duration will be passed negative to the DAHDI driver */
11952                      } else {
11953                          ast_log(LOG_ERROR, "First cadence position specified twice: %s\n",original_args);
11954                         cadence_is_ok = 0;
11955                         break;
11956                      }
11957                   }
11958                }
11959             }
11960    
11961             /* Substitute our scanned cadence */
11962             for (i = 0; i < 16; i++) {
11963                new_cadence.ringcadence[i] = c[i];
11964             }
11965    
11966             if (cadence_is_ok) {
11967                /* ---we scanned it without getting annoyed; now some sanity checks--- */
11968                if (element_count < 2) {
11969                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s\n", original_args);
11970                } else {
11971                   if (cid_location == -1) {
11972                      /* user didn't say; default to first pause */
11973                      cid_location = 1;
11974                   } else {
11975                      /* convert element_index to cidrings value */
11976                      cid_location = (cid_location + 1) / 2;
11977                   }
11978                   /* ---we like their cadence; try to install it--- */
11979                   if (!user_has_defined_cadences++)
11980                      /* this is the first user-defined cadence; clear the default user cadences */
11981                      num_cadence = 0;
11982                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
11983                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s\n", NUM_CADENCE_MAX, original_args);
11984                   else {
11985                      cadences[num_cadence] = new_cadence;
11986                      cidrings[num_cadence++] = cid_location;
11987                      if (option_verbose > 2)
11988                         ast_verbose(VERBOSE_PREFIX_3 "cadence 'r%d' added: %s\n",num_cadence,original_args);
11989                   }
11990                }
11991             }
11992          } else if (!strcasecmp(v->name, "ringtimeout")) {
11993             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
11994          } else if (!strcasecmp(v->name, "prewink")) {
11995             confp->timing.prewinktime = atoi(v->value);
11996          } else if (!strcasecmp(v->name, "preflash")) {
11997             confp->timing.preflashtime = atoi(v->value);
11998          } else if (!strcasecmp(v->name, "wink")) {
11999             confp->timing.winktime = atoi(v->value);
12000          } else if (!strcasecmp(v->name, "flash")) {
12001             confp->timing.flashtime = atoi(v->value);
12002          } else if (!strcasecmp(v->name, "start")) {
12003             confp->timing.starttime = atoi(v->value);
12004          } else if (!strcasecmp(v->name, "rxwink")) {
12005             confp->timing.rxwinktime = atoi(v->value);
12006          } else if (!strcasecmp(v->name, "rxflash")) {
12007             confp->timing.rxflashtime = atoi(v->value);
12008          } else if (!strcasecmp(v->name, "debounce")) {
12009             confp->timing.debouncetime = atoi(v->value);
12010          } else if (!strcasecmp(v->name, "toneduration")) {
12011             int toneduration;
12012             int ctlfd;
12013             int res;
12014             struct dahdi_dialparams dps;
12015 
12016             ctlfd = open(DAHDI_FILE_CTL, O_RDWR);
12017 
12018             if (ctlfd == -1) {
12019                ast_log(LOG_ERROR, "Unable to open " DAHDI_FILE_CTL " to set toneduration\n");
12020                return -1;
12021             }
12022 
12023             toneduration = atoi(v->value);
12024             if (toneduration > -1) {
12025                memset(&dps, 0, sizeof(dps));
12026 
12027                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
12028                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
12029                if (res < 0) {
12030                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms: %s\n", toneduration, strerror(errno));
12031                   return -1;
12032                }
12033             }
12034             close(ctlfd);
12035          } else if (!strcasecmp(v->name, "defaultcic")) {
12036             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
12037          } else if (!strcasecmp(v->name, "defaultozz")) {
12038             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
12039          } 
12040       } else if (!skipchannels)
12041          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload)\n", v->name);
12042    }
12043    if (dahdichan[0]) { 
12044       /* The user has set 'dahdichan' */
12045       /*< \todo pass proper line number instead of 0 */
12046       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
12047          return -1;
12048       }
12049    }
12050    /*< \todo why check for the pseudo in the per-channel section.
12051     * Any actual use for manual setup of the pseudo channel? */
12052    if (!found_pseudo && reload != 1) {
12053       /* use the default configuration for a channel, so
12054          that any settings from real configured channels
12055          don't "leak" into the pseudo channel config
12056       */
12057       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12058 
12059       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
12060 
12061       if (tmp) {
12062          if (option_verbose > 2)
12063             ast_verbose(VERBOSE_PREFIX_3 "Automatically generated pseudo channel\n");
12064       } else {
12065          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
12066       }
12067    }
12068    return 0;
12069 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 8829 of file chan_dahdi.c.

Referenced by __oh323_new().

08830 {
08831    switch (redirectingreason) {
08832    case 0:
08833       return "UNKNOWN";
08834    case 1:
08835       return "BUSY";
08836    case 2:
08837       return "NO_REPLY";
08838    case 0xF:
08839       return "UNCONDITIONAL";
08840    default:
08841       return "NOREDIRECT";
08842    }
08843 }

static int reload ( void   )  [static]

Definition at line 12376 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

12377 {
12378    int res = 0;
12379 
12380    res = setup_dahdi(1);
12381    if (res) {
12382       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12383       return -1;
12384    }
12385    return 0;
12386 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1699 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::channel, dahdi_pvt::confno, dahdi_subchannel::dfd, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_hangup().

01700 {
01701    p->confno = -1;
01702    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01703    if (p->subs[SUB_REAL].dfd > -1) {
01704       struct dahdi_confinfo zi;
01705 
01706       memset(&zi, 0, sizeof(zi));
01707       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01708          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01709    }
01710    return 0;
01711 }

static int restart_monitor ( void   )  [static]

Definition at line 7464 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and monlock.

Referenced by dahdi_hangup(), dahdi_request(), h323_reload(), load_module(), mgcp_reload(), mgcp_request(), oh323_request(), phone_hangup(), phone_request(), setup_dahdi(), sip_reload(), sip_request_call(), and skinny_request().

07465 {
07466    pthread_attr_t attr;
07467    pthread_attr_init(&attr);
07468    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
07469    /* If we're supposed to be stopped -- stay stopped */
07470    if (monitor_thread == AST_PTHREADT_STOP)
07471       return 0;
07472    ast_mutex_lock(&monlock);
07473    if (monitor_thread == pthread_self()) {
07474       ast_mutex_unlock(&monlock);
07475       ast_log(LOG_WARNING, "Cannot kill myself\n");
07476       return -1;
07477    }
07478    if (monitor_thread != AST_PTHREADT_NULL) {
07479       /* Wake up the thread */
07480       pthread_kill(monitor_thread, SIGURG);
07481    } else {
07482       /* Start a new monitor */
07483       if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
07484          ast_mutex_unlock(&monlock);
07485          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
07486          pthread_attr_destroy(&attr);
07487          return -1;
07488       }
07489    }
07490    ast_mutex_unlock(&monlock);
07491    pthread_attr_destroy(&attr);
07492    return 0;
07493 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2032 of file chan_dahdi.c.

References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_event(), dahdi_read(), and send_callerid().

02033 {
02034    int res;
02035    if (p->saveconf.confmode) {
02036       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02037       p->saveconf.confmode = 0;
02038       if (res) {
02039          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02040          return -1;
02041       }
02042    }
02043    if (option_debug)
02044       ast_log(LOG_DEBUG, "Restored conferencing\n");
02045    return 0;
02046 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 1959 of file chan_dahdi.c.

References ast_log(), errno, dahdi_pvt::law, LOG_WARNING, dahdi_pvt::rxgain, set_actual_gain(), SUB_REAL, dahdi_pvt::subs, and dahdi_pvt::txgain.

Referenced by dahdi_hangup(), and ss_thread().

01960 {
01961    int res;
01962 
01963    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
01964    if (res) {
01965       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
01966       return -1;
01967    }
01968 
01969    return 0;
01970 }

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2005 of file chan_dahdi.c.

References ast_log(), errno, LOG_DEBUG, LOG_WARNING, option_debug, dahdi_pvt::saveconf, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_callwait(), and dahdi_handle_event().

02006 {
02007    struct dahdi_confinfo c;
02008    int res;
02009    if (p->saveconf.confmode) {
02010       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02011       return -1;
02012    }
02013    p->saveconf.chan = 0;
02014    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02015    if (res) {
02016       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02017       p->saveconf.confmode = 0;
02018       return -1;
02019    }
02020    memset(&c, 0, sizeof(c));
02021    c.confmode = DAHDI_CONF_NORMAL;
02022    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02023    if (res) {
02024       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02025       return -1;
02026    }
02027    if (option_debug)
02028       ast_log(LOG_DEBUG, "Disabled conferencing\n");
02029    return 0;
02030 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 2072 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::callwaitcas, CIDCW_EXPIRE_SAMPLES, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_setlinear(), errno, free, dahdi_subchannel::linear, LOG_WARNING, restore_conference(), SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_call(), dahdi_callwait(), dahdi_read(), and send_cwcidspill().

02073 {
02074    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02075    int res;
02076    /* Take out of linear mode if necessary */
02077    if (p->subs[SUB_REAL].linear) {
02078       p->subs[SUB_REAL].linear = 0;
02079       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02080    }
02081    while (p->cidpos < p->cidlen) {
02082       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02083       if (res < 0) {
02084          if (errno == EAGAIN)
02085             return 0;
02086          else {
02087             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02088             return -1;
02089          }
02090       }
02091       if (!res)
02092          return 0;
02093       p->cidpos += res;
02094    }
02095    free(p->cidspill);
02096    p->cidspill = NULL;
02097    if (p->callwaitcas) {
02098       /* Wait for CID/CW to expire */
02099       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02100    } else
02101       restore_conference(p);
02102    return 0;
02103 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 2050 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verbose(), dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::cidcwexpire, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, MAX_CALLERID_SIZE, option_verbose, READ_SIZE, send_callerid(), and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_dtmfup().

02051 {
02052    p->callwaitcas = 0;
02053    p->cidcwexpire = 0;
02054    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02055       return -1;
02056    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02057    /* Make sure we account for the end */
02058    p->cidlen += READ_SIZE * 4;
02059    p->cidpos = 0;
02060    send_callerid(p);
02061    if (option_verbose > 2)
02062       ast_verbose(VERBOSE_PREFIX_3 "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02063    return 0;
02064 }

static int send_keypad_facility_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 2685 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), dahdi_pvt::call, dahdi_pvt::lock, LOG_DEBUG, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), and ast_channel::tech_pvt.

Referenced by dahdi_send_keypad_facility_exec(), and zap_send_keypad_facility_exec().

02686 {
02687    /* Data will be our digit string */
02688    struct dahdi_pvt *p;
02689    char *digits = (char *) data;
02690 
02691    if (ast_strlen_zero(digits)) {
02692       ast_log(LOG_DEBUG, "No digit string sent to application!\n");
02693       return -1;
02694    }
02695 
02696    p = (struct dahdi_pvt *)chan->tech_pvt;
02697 
02698    if (!p) {
02699       ast_log(LOG_DEBUG, "Unable to find technology private\n");
02700       return -1;
02701    }
02702 
02703    ast_mutex_lock(&p->lock);
02704 
02705    if (!p->pri || !p->call) {
02706       ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
02707       ast_mutex_unlock(&p->lock);
02708       return -1;
02709    }
02710 
02711    if (!pri_grab(p, p->pri)) {
02712       pri_keypad_facility(p->pri->pri, p->call, digits);
02713       pri_rel(p->pri);
02714    } else {
02715       ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
02716       ast_mutex_unlock(&p->lock);
02717       return -1;
02718    }
02719 
02720    ast_mutex_unlock(&p->lock);
02721 
02722    return 0;
02723 }

static int set_actual_gain ( int  fd,
int  chan,
float  rxgain,
float  txgain,
int  law 
) [static]

Definition at line 1940 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

Referenced by bump_gains(), dahdi_call(), and restore_gains().

01941 {
01942    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
01943 }

static int set_actual_rxgain ( int  fd,
int  chan,
float  gain,
int  law 
) [static]

Definition at line 1922 of file chan_dahdi.c.

References ast_log(), errno, fill_rxgain(), and LOG_DEBUG.

Referenced by dahdi_setoption(), and set_actual_gain().

01923 {
01924    struct dahdi_gains g;
01925    int res;
01926 
01927    memset(&g, 0, sizeof(g));
01928    g.chan = chan;
01929    res = ioctl(fd, DAHDI_GETGAINS, &g);
01930    if (res) {
01931       ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01932       return res;
01933    }
01934 
01935    fill_rxgain(&g, gain, law);
01936 
01937    return ioctl(fd, DAHDI_SETGAINS, &g);
01938 }

static int set_actual_txgain ( int  fd,
int  chan,
float  gain,
int  law 
) [static]

Definition at line 1903 of file chan_dahdi.c.

References ast_log(), errno, fill_txgain(), LOG_DEBUG, and option_debug.

Referenced by dahdi_setoption(), and set_actual_gain().

01904 {
01905    struct dahdi_gains g;
01906    int res;
01907 
01908    memset(&g, 0, sizeof(g));
01909    g.chan = chan;
01910    res = ioctl(fd, DAHDI_GETGAINS, &g);
01911    if (res) {
01912       if (option_debug)
01913          ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
01914       return res;
01915    }
01916 
01917    fill_txgain(&g, gain, law);
01918 
01919    return ioctl(fd, DAHDI_SETGAINS, &g);
01920 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 12071 of file chan_dahdi.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verbose(), CHAN_ZAP_MODE, dahdi_chan_conf_default(), dahdi_chan_mode, default_jbconf, global_jbconf, iflock, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, NUM_SPANS, option_verbose, pri_create_spanmap(), pri_create_trunkgroup(), pris, process_dahdi(), restart_monitor(), start_pri(), ast_variable::value, and VERBOSE_PREFIX_2.

Referenced by dahdi_restart(), load_module(), and reload().

12072 {
12073    struct ast_config *cfg;
12074    struct ast_variable *v;
12075    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12076    int res;
12077 
12078 #ifdef HAVE_PRI
12079    char *c;
12080    int spanno;
12081    int i, x;
12082    int logicalspan;
12083    int trunkgroup;
12084    int dchannels[NUM_DCHANS];
12085 #endif
12086 
12087 #ifdef HAVE_ZAPTEL
12088    int load_from_zapata_conf = 1;
12089 #else
12090    int load_from_zapata_conf = (*dahdi_chan_mode == CHAN_ZAP_MODE);
12091 #endif
12092 
12093    if (load_from_zapata_conf) {
12094       if (!(cfg = ast_config_load("zapata.conf"))) {
12095          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
12096          return 0;
12097       }
12098    } else {
12099       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
12100          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
12101          return 0;
12102       }
12103    }
12104 
12105    /* It's a little silly to lock it, but we mind as well just to be sure */
12106    ast_mutex_lock(&iflock);
12107 #ifdef HAVE_PRI
12108    if (reload != 1) {
12109       /* Process trunkgroups first */
12110       v = ast_variable_browse(cfg, "trunkgroups");
12111       while (v) {
12112          if (!strcasecmp(v->name, "trunkgroup")) {
12113             trunkgroup = atoi(v->value);
12114             if (trunkgroup > 0) {
12115                if ((c = strchr(v->value, ','))) {
12116                   i = 0;
12117                   memset(dchannels, 0, sizeof(dchannels));
12118                   while (c && (i < NUM_DCHANS)) {
12119                      dchannels[i] = atoi(c + 1);
12120                      if (dchannels[i] < 0) {
12121                         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);
12122                      } else
12123                         i++;
12124                      c = strchr(c + 1, ',');
12125                   }
12126                   if (i) {
12127                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
12128                         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);
12129                      } else if (option_verbose > 1)
12130                         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");
12131                   } else
12132                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12133                } else
12134                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12135             } else
12136                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
12137          } else if (!strcasecmp(v->name, "spanmap")) {
12138             spanno = atoi(v->value);
12139             if (spanno > 0) {
12140                if ((c = strchr(v->value, ','))) {
12141                   trunkgroup = atoi(c + 1);
12142                   if (trunkgroup > 0) {
12143                      if ((c = strchr(c + 1, ','))) 
12144                         logicalspan = atoi(c + 1);
12145                      else
12146                         logicalspan = 0;
12147                      if (logicalspan >= 0) {
12148                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
12149                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12150                         } else if (option_verbose > 1) 
12151                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12152                      } else
12153                         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);
12154                   } else
12155                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
12156                } else
12157                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
12158             } else
12159                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
12160          } else {
12161             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
12162          }
12163          v = v->next;
12164       }
12165    }
12166 #endif
12167    
12168    /* Copy the default jb config over global_jbconf */
12169    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
12170 
12171    v = ast_variable_browse(cfg, "channels");
12172    res = process_dahdi(&conf, "", v, reload, 0);
12173    ast_mutex_unlock(&iflock);
12174    ast_config_destroy(cfg);
12175    if (res)
12176       return res;
12177    cfg = ast_config_load("users.conf");
12178    if (cfg) {
12179       char *cat;
12180       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
12181       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
12182          if (!strcasecmp(cat, "general"))
12183             continue;
12184          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
12185             struct dahdi_chan_conf sect_conf;
12186             memcpy(&sect_conf, &conf, sizeof(sect_conf));
12187 
12188             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
12189          }
12190       }
12191       ast_config_destroy(cfg);
12192    }
12193 #ifdef HAVE_PRI
12194    if (reload != 1) {
12195       for (x = 0; x < NUM_SPANS; x++) {
12196          if (pris[x].pvts[0]) {
12197             if (start_pri(pris + x)) {
12198                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
12199                return -1;
12200             } else if (option_verbose > 1)
12201                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
12202          }
12203       }
12204    }
12205 #endif
12206    /* And start the monitor for the first time */
12207    restart_monitor();
12208    return 0;
12209 }

static void * ss_thread ( void *  data  )  [static]

Definition at line 5884 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_dsp_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock, ast_mutex_unlock, ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), ast_smdi_md_message_wait(), AST_STATE_PRERING, AST_STATE_RING, AST_STATE_RINGING, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitfor(), ast_waitfordigit(), ast_waitstream(), bump_gains(), dahdi_pvt::call, dahdi_pvt::call_forward, callerid_feed(), callerid_feed_jp(), callerid_free(), callerid_get(), callerid_get_dtmf(), callerid_new(), ast_smdi_md_message::calling_st, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::cancallforward, dahdi_pvt::canpark, chan_tech, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_name, dahdi_pvt::cid_name, ast_callerid::cid_num, dahdi_pvt::cid_num, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_chan_name, dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dnd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), EVENT_FLAG_SYSTEM, ast_channel::exten, dahdi_pvt::exten, exten, f, free, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, manager_event(), my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, option_debug, option_verbose, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, quit, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, dahdi_pvt::smdi_iface, SMDI_MD_WAIT_TIMEOUT, ss_thread_lock, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::transfer, ast_smdi_md_message::type, unalloc_sub(), dahdi_pvt::use_callerid, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

Referenced by dahdi_handle_event(), and handle_init_event().

05885 {
05886    struct ast_channel *chan = data;
05887    struct dahdi_pvt *p = chan->tech_pvt;
05888    char exten[AST_MAX_EXTENSION] = "";
05889    char exten2[AST_MAX_EXTENSION] = "";
05890    unsigned char buf[256];
05891    char dtmfcid[300];
05892    char dtmfbuf[300];
05893    struct callerid_state *cs = NULL;
05894    char *name = NULL, *number = NULL;
05895    int distMatches;
05896    int curRingData[3];
05897    int receivedRingT;
05898    int counter1;
05899    int counter;
05900    int samples = 0;
05901    struct ast_smdi_md_message *smdi_msg = NULL;
05902    int flags;
05903    int i;
05904    int timeout;
05905    int getforward = 0;
05906    char *s1, *s2;
05907    int len = 0;
05908    int res;
05909    int index;
05910 
05911    ast_mutex_lock(&ss_thread_lock);
05912    ss_thread_count++;
05913    ast_mutex_unlock(&ss_thread_lock);
05914    /* in the bizarre case where the channel has become a zombie before we
05915       even get started here, abort safely
05916    */
05917    if (!p) {
05918       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
05919       ast_hangup(chan);
05920       goto quit;
05921    }
05922    if (option_verbose > 2) 
05923       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
05924    index = dahdi_get_index(chan, p, 1);
05925    if (index < 0) {
05926       ast_log(LOG_WARNING, "Huh?\n");
05927       ast_hangup(chan);
05928       goto quit;
05929    }
05930    if (p->dsp)
05931       ast_dsp_digitreset(p->dsp);
05932    switch (p->sig) {
05933 #ifdef HAVE_PRI
05934    case SIG_PRI:
05935       /* Now loop looking for an extension */
05936       ast_copy_string(exten, p->exten, sizeof(exten));
05937       len = strlen(exten);
05938       res = 0;
05939       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
05940          if (len && !ast_ignore_pattern(chan->context, exten))
05941             tone_zone_play_tone(p->subs[index].dfd, -1);
05942          else
05943             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
05944          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
05945             timeout = matchdigittimeout;
05946          else
05947             timeout = gendigittimeout;
05948          res = ast_waitfordigit(chan, timeout);
05949          if (res < 0) {
05950             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
05951             ast_hangup(chan);
05952             goto quit;
05953          } else if (res) {
05954             exten[len++] = res;
05955             exten[len] = '\0';
05956          } else
05957             break;
05958       }
05959       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
05960       if (ast_strlen_zero(exten)) {
05961          if (option_verbose > 2)
05962             ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of empty extension received on overlap call\n");
05963          exten[0] = 's';
05964          exten[1] = '\0';
05965       }
05966       tone_zone_play_tone(p->subs[index].dfd, -1);
05967       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
05968          /* Start the real PBX */
05969          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
05970          if (p->dsp) ast_dsp_digitreset(p->dsp);
05971          dahdi_enable_ec(p);
05972          ast_setstate(chan, AST_STATE_RING);
05973          res = ast_pbx_run(chan);
05974          if (res) {
05975             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
05976          }
05977       } else {
05978          ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
05979          chan->hangupcause = AST_CAUSE_UNALLOCATED;
05980          ast_hangup(chan);
05981          p->exten[0] = '\0';
05982          /* Since we send release complete here, we won't get one */
05983          p->call = NULL;
05984       }
05985       goto quit;
05986       break;
05987 #endif
05988    case SIG_FEATD:
05989    case SIG_FEATDMF:
05990    case SIG_FEATDMF_TA:
05991    case SIG_E911:
05992    case SIG_FGC_CAMAMF:
05993    case SIG_FEATB:
05994    case SIG_EMWINK:
05995    case SIG_SF_FEATD:
05996    case SIG_SF_FEATDMF:
05997    case SIG_SF_FEATB:
05998    case SIG_SFWINK:
05999       if (dahdi_wink(p, index))  
06000          goto quit;
06001       /* Fall through */
06002    case SIG_EM:
06003    case SIG_EM_E1:
06004    case SIG_SF:
06005    case SIG_FGC_CAMA:
06006       res = tone_zone_play_tone(p->subs[index].dfd, -1);
06007       if (p->dsp)
06008          ast_dsp_digitreset(p->dsp);
06009       /* set digit mode appropriately */
06010       if (p->dsp) {
06011          if (NEED_MFDETECT(p))
06012             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax); 
06013          else 
06014             ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06015       }
06016       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06017       /* Wait for the first digit only if immediate=no */
06018       if (!p->immediate)
06019          /* Wait for the first digit (up to 5 seconds). */
06020          res = ast_waitfordigit(chan, 5000);
06021       else
06022          res = 0;
06023       if (res > 0) {
06024          /* save first char */
06025          dtmfbuf[0] = res;
06026          switch (p->sig) {
06027          case SIG_FEATD:
06028          case SIG_SF_FEATD:
06029             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06030             if (res > 0)
06031                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06032             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06033             break;
06034          case SIG_FEATDMF_TA:
06035             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06036             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06037             if (dahdi_wink(p, index)) goto quit;
06038             dtmfbuf[0] = 0;
06039             /* Wait for the first digit (up to 5 seconds). */
06040             res = ast_waitfordigit(chan, 5000);
06041             if (res <= 0) break;
06042             dtmfbuf[0] = res;
06043             /* fall through intentionally */
06044          case SIG_FEATDMF:
06045          case SIG_E911:
06046          case SIG_FGC_CAMAMF:
06047          case SIG_SF_FEATDMF:
06048             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06049             /* if international caca, do it again to get real ANO */
06050             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06051             {
06052                if (dahdi_wink(p, index)) goto quit;
06053                dtmfbuf[0] = 0;
06054                /* Wait for the first digit (up to 5 seconds). */
06055                res = ast_waitfordigit(chan, 5000);
06056                if (res <= 0) break;
06057                dtmfbuf[0] = res;
06058                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06059             }
06060             if (res > 0) {
06061                /* if E911, take off hook */
06062                if (p->sig == SIG_E911)
06063                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06064                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06065             }
06066             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06067             break;
06068          case SIG_FEATB:
06069          case SIG_SF_FEATB:
06070             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06071             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06072             break;
06073          case SIG_EMWINK:
06074             /* if we received a '*', we are actually receiving Feature Group D
06075                dial syntax, so use that mode; otherwise, fall through to normal
06076                mode
06077             */
06078             if (res == '*') {
06079                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06080                if (res > 0)
06081                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06082                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06083                break;
06084             }
06085          default:
06086             /* If we got the first digit, get the rest */
06087             len = 1;
06088             dtmfbuf[len] = '\0';
06089             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06090                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06091                   timeout = matchdigittimeout;
06092                } else {
06093                   timeout = gendigittimeout;
06094                }
06095                res = ast_waitfordigit(chan, timeout);
06096                if (res < 0) {
06097                   ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06098                   ast_hangup(chan);
06099                   goto quit;
06100                } else if (res) {
06101                   dtmfbuf[len++] = res;
06102                   dtmfbuf[len] = '\0';
06103                } else {
06104                   break;
06105                }
06106             }
06107             break;
06108          }
06109       }
06110       if (res == -1) {
06111          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06112          ast_hangup(chan);
06113          goto quit;
06114       } else if (res < 0) {
06115          ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
06116          ast_hangup(chan);
06117          goto quit;
06118       }
06119 
06120       if (p->sig == SIG_FGC_CAMA) {
06121          char anibuf[100];
06122 
06123          if (ast_safe_sleep(chan,1000) == -1) {
06124                            ast_hangup(chan);
06125                            goto quit;
06126          }
06127                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06128                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MF | p->dtmfrelax);
06129                         res = my_getsigstr(chan, anibuf, "#", 10000);
06130                         if ((res > 0) && (strlen(anibuf) > 2)) {
06131             if (anibuf[strlen(anibuf) - 1] == '#')
06132                anibuf[strlen(anibuf) - 1] = 0;
06133             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06134          }
06135                         ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax);
06136       }
06137 
06138       ast_copy_string(exten, dtmfbuf, sizeof(exten));
06139       if (ast_strlen_zero(exten))
06140          ast_copy_string(exten, "s", sizeof(exten));
06141       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06142          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
06143          if (exten[0] == '*') {
06144             char *stringp=NULL;
06145             ast_copy_string(exten2, exten, sizeof(exten2));
06146             /* Parse out extension and callerid */
06147             stringp=exten2 +1;
06148             s1 = strsep(&stringp, "*");
06149             s2 = strsep(&stringp, "*");
06150             if (s2) {
06151                if (!ast_strlen_zero(p->cid_num))
06152                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06153                else
06154                   ast_set_callerid(chan, s1, NULL, s1);
06155                ast_copy_string(exten, s2, sizeof(exten));
06156             } else
06157                ast_copy_string(exten, s1, sizeof(exten));
06158          } else if (p->sig == SIG_FEATD)
06159             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06160       }
06161       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06162          if (exten[0] == '*') {
06163             char *stringp=NULL;
06164             ast_copy_string(exten2, exten, sizeof(exten2));
06165             /* Parse out extension and callerid */
06166             stringp=exten2 +1;
06167             s1 = strsep(&stringp, "#");
06168             s2 = strsep(&stringp, "#");
06169             if (s2) {
06170                if (!ast_strlen_zero(p->cid_num))
06171                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06172                else
06173                   if (*(s1 + 2))
06174                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06175                ast_copy_string(exten, s2 + 1, sizeof(exten));
06176             } else
06177                ast_copy_string(exten, s1 + 2, sizeof(exten));
06178          } else
06179             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06180       }
06181       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06182          if (exten[0] == '*') {
06183             char *stringp=NULL;
06184             ast_copy_string(exten2, exten, sizeof(exten2));
06185             /* Parse out extension and callerid */
06186             stringp=exten2 +1;
06187             s1 = strsep(&stringp, "#");
06188             s2 = strsep(&stringp, "#");
06189             if (s2 && (*(s2 + 1) == '0')) {
06190                if (*(s2 + 2))
06191                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06192             }
06193             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
06194             else ast_copy_string(exten, "911", sizeof(exten));
06195          } else
06196             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06197       }
06198       if (p->sig == SIG_FEATB) {
06199          if (exten[0] == '*') {
06200             char *stringp=NULL;
06201             ast_copy_string(exten2, exten, sizeof(exten2));
06202             /* Parse out extension and callerid */
06203             stringp=exten2 +1;
06204             s1 = strsep(&stringp, "#");
06205             ast_copy_string(exten, exten2 + 1, sizeof(exten));
06206          } else
06207             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06208       }
06209       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06210          dahdi_wink(p, index);
06211                         /* some switches require a minimum guard time between
06212                            the last FGD wink and something that answers
06213                            immediately. This ensures it */
06214                         if (ast_safe_sleep(chan,100)) goto quit;
06215       }
06216       dahdi_enable_ec(p);
06217       if (NEED_MFDETECT(p)) {
06218          if (p->dsp) {
06219             if (!p->hardwaredtmf)
06220                ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); 
06221             else {
06222                ast_dsp_free(p->dsp);
06223                p->dsp = NULL;
06224             }
06225          }
06226       }
06227 
06228       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06229          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06230          if (p->dsp) ast_dsp_digitreset(p->dsp);
06231          res = ast_pbx_run(chan);
06232          if (res) {
06233             ast_log(LOG_WARNING, "PBX exited non-zero\n");
06234             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06235          }
06236          goto quit;
06237       } else {
06238          if (option_verbose > 2)
06239             ast_verbose(VERBOSE_PREFIX_2 "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06240          sleep(2);
06241          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_INFO);
06242          if (res < 0)
06243             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06244          else
06245             sleep(1);
06246          res = ast_streamfile(chan, "ss-noservice", chan->language);
06247          if (res >= 0)
06248             ast_waitstream(chan, "");
06249          res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06250          ast_hangup(chan);
06251          goto quit;
06252       }
06253       break;
06254    case SIG_FXOLS:
06255    case SIG_FXOGS:
06256    case SIG_FXOKS:
06257       /* Read the first digit */
06258       timeout = firstdigittimeout;
06259       /* If starting a threeway call, never timeout on the first digit so someone
06260          can use flash-hook as a "hold" feature */
06261       if (p->subs[SUB_THREEWAY].owner) 
06262          timeout = 999999;
06263       while (len < AST_MAX_EXTENSION-1) {
06264          /* Read digit unless it's supposed to be immediate, in which case the
06265             only answer is 's' */
06266          if (p->immediate) 
06267             res = 's';
06268          else
06269             res = ast_waitfordigit(chan, timeout);
06270          timeout = 0;
06271          if (res < 0) {
06272             ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
06273             res = tone_zone_play_tone(p->subs[index].dfd, -1);
06274             ast_hangup(chan);
06275             goto quit;
06276          } else if (res)  {
06277             exten[len++]=res;
06278             exten[len] = '\0';
06279          }
06280          if (!ast_ignore_pattern(chan->context, exten))
06281             tone_zone_play_tone(p->subs[index].dfd, -1);
06282          else
06283             tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06284          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06285             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06286                if (getforward) {
06287                   /* Record this as the forwarding extension */
06288                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
06289                   if (option_verbose > 2)
06290                      ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06291                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06292                   if (res)
06293                      break;
06294                   usleep(500000);
06295                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
06296                   sleep(1);
06297                   memset(exten, 0, sizeof(exten));
06298                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALTONE);
06299                   len = 0;
06300                   getforward = 0;
06301                } else  {
06302                   res = tone_zone_play_tone(p->subs[index].dfd, -1);
06303                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06304                   if (!ast_strlen_zero(p->cid_num)) {
06305                      if (!p->hidecallerid)
06306                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
06307                      else
06308                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
06309                   }
06310                   if (!ast_strlen_zero(p->cid_name)) {
06311                      if (!p->hidecallerid)
06312                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
06313                   }
06314                   ast_setstate(chan, AST_STATE_RING);
06315                   dahdi_enable_ec(p);
06316                   res = ast_pbx_run(chan);
06317                   if (res) {
06318                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
06319                      res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06320                   }
06321                   goto quit;
06322                }
06323             } else {
06324                /* It's a match, but they just typed a digit, and there is an ambiguous match,
06325                   so just set the timeout to matchdigittimeout and wait some more */
06326                timeout = matchdigittimeout;
06327             }
06328          } else if (res == 0) {
06329             ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
06330             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06331             dahdi_wait_event(p->subs[index].dfd);
06332             ast_hangup(chan);
06333             goto quit;
06334          } else if (p->callwaiting && !strcmp(exten, "*70")) {
06335             if (option_verbose > 2) 
06336                ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
06337             /* Disable call waiting if enabled */
06338             p->callwaiting = 0;
06339             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06340             if (res) {
06341                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06342                   chan->name, strerror(errno));
06343             }
06344             len = 0;
06345             ioctl(p->subs[index].dfd,DAHDI_CONFDIAG,&len);
06346             memset(exten, 0, sizeof(exten));
06347             timeout = firstdigittimeout;
06348                
06349          } else if (!strcmp(exten,ast_pickup_ext())) {
06350             /* Scan all channels and see if there are any
06351              * ringing channels that have call groups
06352              * that equal this channels pickup group  
06353              */
06354             if (index == SUB_REAL) {
06355                /* Switch us from Third call to Call Wait */
06356                if (p->subs[SUB_THREEWAY].owner) {
06357                   /* If you make a threeway call and the *8# a call, it should actually 
06358                      look like a callwait */
06359                   alloc_sub(p, SUB_CALLWAIT);   
06360                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
06361                   unalloc_sub(p, SUB_THREEWAY);
06362                }
06363                dahdi_enable_ec(p);
06364                if (ast_pickup_call(chan)) {
06365                   ast_log(LOG_DEBUG, "No call pickup possible...\n");
06366                   res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06367                   dahdi_wait_event(p->subs[index].dfd);
06368                }
06369                ast_hangup(chan);
06370                goto quit;
06371             } else {
06372                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
06373                ast_hangup(chan);
06374                goto quit;
06375             }
06376             
06377          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
06378             if (option_verbose > 2) 
06379                ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
06380             /* Disable Caller*ID if enabled */
06381             p->hidecallerid = 1;
06382             if (chan->cid.cid_num)
06383                free(chan->cid.cid_num);
06384             chan->cid.cid_num = NULL;
06385             if (chan->cid.cid_name)
06386                free(chan->cid.cid_name);
06387             chan->cid.cid_name = NULL;
06388             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06389             if (res) {
06390                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06391                   chan->name, strerror(errno));
06392             }
06393             len = 0;
06394             memset(exten, 0, sizeof(exten));
06395             timeout = firstdigittimeout;
06396          } else if (p->callreturn && !strcmp(exten, "*69")) {
06397             res = 0;
06398             if (!ast_strlen_zero(p->lastcid_num)) {
06399                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
06400             }
06401             if (!res)
06402                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06403             break;
06404          } else if (!strcmp(exten, "*78")) {
06405             /* Do not disturb */
06406             if (option_verbose > 2)
06407                ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %d\n", p->channel);
06408             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06409                      "Channel: %s/%d\r\n"
06410                      "Status: enabled\r\n", dahdi_chan_name, p->channel);
06411             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06412             p->dnd = 1;
06413             getforward = 0;
06414             memset(exten, 0, sizeof(exten));
06415             len = 0;
06416          } else if (!strcmp(exten, "*79")) {
06417             /* Do not disturb */
06418             if (option_verbose > 2)
06419                ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %d\n", p->channel);
06420             manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06421                      "Channel: %s/%d\r\n"
06422                      "Status: disabled\r\n", dahdi_chan_name, p->channel);
06423             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06424             p->dnd = 0;
06425             getforward = 0;
06426             memset(exten, 0, sizeof(exten));
06427             len = 0;
06428          } else if (p->cancallforward && !strcmp(exten, "*72")) {
06429             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06430             getforward = 1;
06431             memset(exten, 0, sizeof(exten));
06432             len = 0;
06433          } else if (p->cancallforward && !strcmp(exten, "*73")) {
06434             if (option_verbose > 2)
06435                ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %d\n", p->channel);
06436             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06437             memset(p->call_forward, 0, sizeof(p->call_forward));
06438             getforward = 0;
06439             memset(exten, 0, sizeof(exten));
06440             len = 0;
06441          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
06442                   p->subs[SUB_THREEWAY].owner &&
06443                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06444             /* This is a three way call, the main call being a real channel, 
06445                and we're parking the first call. */
06446             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
06447             if (option_verbose > 2)
06448                ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
06449             break;
06450          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
06451             if (option_verbose > 2)
06452                ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", p->lastcid_num);
06453             res = ast_db_put("blacklist", p->lastcid_num, "1");
06454             if (!res) {
06455                res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06456                memset(exten, 0, sizeof(exten));
06457                len = 0;
06458             }
06459          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
06460             if (option_verbose > 2) 
06461                ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
06462             /* Enable Caller*ID if enabled */
06463             p->hidecallerid = 0;
06464             if (chan->cid.cid_num)
06465                free(chan->cid.cid_num);
06466             chan->cid.cid_num = NULL;
06467             if (chan->cid.cid_name)
06468                free(chan->cid.cid_name);
06469             chan->cid.cid_name = NULL;
06470             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
06471             res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_DIALRECALL);
06472             if (res) {
06473                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06474                   chan->name, strerror(errno));
06475             }
06476             len = 0;
06477             memset(exten, 0, sizeof(exten));
06478             timeout = firstdigittimeout;
06479          } else if (!strcmp(exten, "*0")) {
06480             struct ast_channel *nbridge = 
06481                p->subs[SUB_THREEWAY].owner;
06482             struct dahdi_pvt *pbridge = NULL;
06483               /* set up the private struct of the bridged one, if any */
06484             if (nbridge && ast_bridged_channel(nbridge)) 
06485                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
06486             if (nbridge && pbridge && 
06487                 (nbridge->tech == chan_tech) && 
06488                 (ast_bridged_channel(nbridge)->tech == chan_tech) &&
06489                 ISTRUNK(pbridge)) {
06490                int func = DAHDI_FLASH;
06491                /* Clear out the dial buffer */
06492                p->dop.dialstr[0] = '\0';
06493                /* flash hookswitch */
06494                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06495                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06496                      nbridge->name, strerror(errno));
06497                }
06498                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06499                unalloc_sub(p, SUB_THREEWAY);
06500                p->owner = p->subs[SUB_REAL].owner;
06501                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
06502                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06503                ast_hangup(chan);
06504                goto quit;
06505             } else {
06506                tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
06507                dahdi_wait_event(p->subs[index].dfd);
06508                tone_zone_play_tone(p->subs[index].dfd, -1);
06509                swap_subs(p, SUB_REAL, SUB_THREEWAY);
06510                unalloc_sub(p, SUB_THREEWAY);
06511                p->owner = p->subs[SUB_REAL].owner;
06512                ast_hangup(chan);
06513                goto quit;
06514             }              
06515          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
06516                      ((exten[0] != '*') || (strlen(exten) > 2))) {
06517             if (option_debug)
06518                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);
06519             break;
06520          }
06521          if (!timeout)
06522             timeout = gendigittimeout;
06523          if (len && !ast_ignore_pattern(chan->context, exten))
06524             tone_zone_play_tone(p->subs[index].dfd, -1);
06525       }
06526       break;
06527    case SIG_FXSLS:
06528    case SIG_FXSGS:
06529    case SIG_FXSKS:
06530 #ifdef HAVE_PRI
06531       if (p->pri) {
06532          /* This is a GR-303 trunk actually.  Wait for the first ring... */
06533          struct ast_frame *f;
06534          int res;
06535          time_t start;
06536 
06537          time(&start);
06538          ast_setstate(chan, AST_STATE_RING);
06539          while (time(NULL) < start + 3) {
06540             res = ast_waitfor(chan, 1000);
06541             if (res) {
06542                f = ast_read(chan);
06543                if (!f) {
06544                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
06545                   ast_hangup(chan);
06546                   goto quit;
06547                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
06548                   res = 1;
06549                } else
06550                   res = 0;
06551                ast_frfree(f);
06552                if (res) {
06553                   ast_log(LOG_DEBUG, "Got ring!\n");
06554                   res = 0;
06555                   break;
06556                }
06557             }
06558          }
06559       }
06560 #endif
06561       /* check for SMDI messages */
06562       if (p->use_smdi && p->smdi_iface) {
06563          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
06564 
06565          if (smdi_msg != NULL) {
06566             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
06567 
06568             if (smdi_msg->type == 'B')
06569                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
06570             else if (smdi_msg->type == 'N')
06571                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
06572 
06573             ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
06574          } else {
06575             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
06576          }
06577       }
06578 
06579       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
06580             number = smdi_msg->calling_st;
06581 
06582       /* If we want caller id, we're in a prering state due to a polarity reversal
06583        * and we're set to use a polarity reversal to trigger the start of caller id,
06584        * grab the caller id and wait for ringing to start... */
06585       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
06586          /* If set to use DTMF CID signalling, listen for DTMF */
06587          if (p->cid_signalling == CID_SIG_DTMF) {
06588             int i = 0;
06589             cs = NULL;
06590             ast_log(LOG_DEBUG, "Receiving DTMF cid on "
06591                "channel %s\n", chan->name);
06592             dahdi_setlinear(p->subs[index].dfd, 0);
06593             res = 2000;
06594             for (;;) {
06595                struct ast_frame *f;
06596                res = ast_waitfor(chan, res);
06597                if (res <= 0) {
06598                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
06599                      "Exiting simple switch\n");
06600                   ast_hangup(chan);
06601                   goto quit;
06602                } 
06603                f = ast_read(chan);
06604                if (!f)
06605                   break;
06606                if (f->frametype == AST_FRAME_DTMF) {
06607                   dtmfbuf[i++] = f->subclass;
06608                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
06609                   res = 2000;
06610                }
06611                ast_frfree(f);
06612                if (chan->_state == AST_STATE_RING ||
06613                    chan->_state == AST_STATE_RINGING) 
06614                   break; /* Got ring */
06615             }
06616             dtmfbuf[i] = '\0';
06617             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06618             /* Got cid and ring. */
06619             ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
06620             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
06621             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n", 
06622                dtmfcid, flags);
06623             /* If first byte is NULL, we have no cid */
06624             if (!ast_strlen_zero(dtmfcid)) 
06625                number = dtmfcid;
06626             else
06627                number = NULL;
06628          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
06629          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
06630             cs = callerid_new(p->cid_signalling);
06631             if (cs) {
06632                samples = 0;
06633 #if 1
06634                bump_gains(p);
06635 #endif            
06636                /* Take out of linear mode for Caller*ID processing */
06637                dahdi_setlinear(p->subs[index].dfd, 0);
06638                
06639                /* First we wait and listen for the Caller*ID */
06640                for (;;) {  
06641                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06642                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06643                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06644                      callerid_free(cs);
06645                      ast_hangup(chan);
06646                      goto quit;
06647                   }
06648                   if (i & DAHDI_IOMUX_SIGEVENT) {
06649                      res = dahdi_get_event(p->subs[index].dfd);
06650                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06651 
06652                      if (p->cid_signalling == CID_SIG_V23_JP) {
06653 #ifdef DAHDI_EVENT_RINGBEGIN
06654                         if (res == DAHDI_EVENT_RINGBEGIN) {
06655                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06656                            usleep(1);
06657                         }
06658 #endif
06659                      } else {
06660                         res = 0;
06661                         break;
06662                      }
06663                   } else if (i & DAHDI_IOMUX_READ) {
06664                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06665                      if (res < 0) {
06666                         if (errno != ELAST) {
06667                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06668                            callerid_free(cs);
06669                            ast_hangup(chan);
06670                            goto quit;
06671                         }
06672                         break;
06673                      }
06674                      samples += res;
06675 
06676                      if  (p->cid_signalling == CID_SIG_V23_JP) {
06677                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
06678                      } else {
06679                         res = callerid_feed(cs, buf, res, AST_LAW(p));
06680                      }
06681 
06682                      if (res < 0) {
06683                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
06684                         break;
06685                      } else if (res)
06686                         break;
06687                      else if (samples > (8000 * 10))
06688                         break;
06689                   }
06690                }
06691                if (res == 1) {
06692                   callerid_get(cs, &name, &number, &flags);
06693                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06694                }
06695 
06696                if (p->cid_signalling == CID_SIG_V23_JP) {
06697                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
06698                   usleep(1);
06699                   res = 4000;
06700                } else {
06701 
06702                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
06703                   res = 2000;
06704                }
06705 
06706                for (;;) {
06707                   struct ast_frame *f;
06708                   res = ast_waitfor(chan, res);
06709                   if (res <= 0) {
06710                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
06711                         "Exiting simple switch\n");
06712                      ast_hangup(chan);
06713                      goto quit;
06714                   } 
06715                   if (!(f = ast_read(chan))) {
06716                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
06717                      ast_hangup(chan);
06718                      goto quit;
06719                   }
06720                   ast_frfree(f);
06721                   if (chan->_state == AST_STATE_RING ||
06722                       chan->_state == AST_STATE_RINGING) 
06723                      break; /* Got ring */
06724                }
06725    
06726                /* We must have a ring by now, so, if configured, lets try to listen for
06727                 * distinctive ringing */ 
06728                if (p->usedistinctiveringdetection) {
06729                   len = 0;
06730                   distMatches = 0;
06731                   /* Clear the current ring data array so we dont have old data in it. */
06732                   for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06733                      curRingData[receivedRingT] = 0;
06734                   receivedRingT = 0;
06735                   counter = 0;
06736                   counter1 = 0;
06737                   /* Check to see if context is what it should be, if not set to be. */
06738                   if (strcmp(p->context,p->defcontext) != 0) {
06739                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06740                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06741                   }
06742       
06743                   for (;;) {  
06744                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06745                      if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06746                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06747                         callerid_free(cs);
06748                         ast_hangup(chan);
06749                         goto quit;
06750                      }
06751                      if (i & DAHDI_IOMUX_SIGEVENT) {
06752                         res = dahdi_get_event(p->subs[index].dfd);
06753                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06754                         res = 0;
06755                         /* Let us detect distinctive ring */
06756       
06757                         curRingData[receivedRingT] = p->ringt;
06758       
06759                         if (p->ringt < p->ringt_base/2)
06760                            break;
06761                         /* Increment the ringT counter so we can match it against
06762                            values in chan_dahdi.conf for distinctive ring */
06763                         if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06764                            break;
06765                      } else if (i & DAHDI_IOMUX_READ) {
06766                         res = read(p->subs[index].dfd, buf, sizeof(buf));
06767                         if (res < 0) {
06768                            if (errno != ELAST) {
06769                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06770                               callerid_free(cs);
06771                               ast_hangup(chan);
06772                               goto quit;
06773                            }
06774                            break;
06775                         }
06776                         if (p->ringt) 
06777                            p->ringt--;
06778                         if (p->ringt == 1) {
06779                            res = -1;
06780                            break;
06781                         }
06782                      }
06783                   }
06784                   if (option_verbose > 2)
06785                      /* this only shows up if you have n of the dring patterns filled in */
06786                      ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06787    
06788                   for (counter = 0; counter < 3; counter++) {
06789                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06790                      channel */
06791                      distMatches = 0;
06792                      for (counter1 = 0; counter1 < 3; counter1++) {
06793                         if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06794                         (p->drings.ringnum[counter].ring[counter1]-10)) {
06795                            distMatches++;
06796                         }
06797                      }
06798                      if (distMatches == 3) {
06799                         /* The ring matches, set the context to whatever is for distinctive ring.. */
06800                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06801                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06802                         if (option_verbose > 2)
06803                            ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06804                         break;
06805                      }
06806                   }
06807                }
06808                /* Restore linear mode (if appropriate) for Caller*ID processing */
06809                dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06810 #if 1
06811                restore_gains(p);
06812 #endif            
06813             } else
06814                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
06815          } else {
06816             ast_log(LOG_WARNING, "Channel %s in prering "
06817                "state, but I have nothing to do. "
06818                "Terminating simple switch, should be "
06819                "restarted by the actual ring.\n", 
06820                chan->name);
06821             ast_hangup(chan);
06822             goto quit;
06823          }
06824       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
06825          /* FSK Bell202 callerID */
06826          cs = callerid_new(p->cid_signalling);
06827          if (cs) {
06828 #if 1
06829             bump_gains(p);
06830 #endif            
06831             samples = 0;
06832             len = 0;
06833             distMatches = 0;
06834             /* Clear the current ring data array so we dont have old data in it. */
06835             for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
06836                curRingData[receivedRingT] = 0;
06837             receivedRingT = 0;
06838             counter = 0;
06839             counter1 = 0;
06840             /* Check to see if context is what it should be, if not set to be. */
06841             if (strcmp(p->context,p->defcontext) != 0) {
06842                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
06843                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
06844             }
06845 
06846             /* Take out of linear mode for Caller*ID processing */
06847             dahdi_setlinear(p->subs[index].dfd, 0);
06848             for (;;) {  
06849                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06850                if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))  {
06851                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06852                   callerid_free(cs);
06853                   ast_hangup(chan);
06854                   goto quit;
06855                }
06856                if (i & DAHDI_IOMUX_SIGEVENT) {
06857                   res = dahdi_get_event(p->subs[index].dfd);
06858                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06859                   /* If we get a PR event, they hung up while processing calerid */
06860                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
06861                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
06862                      p->polarity = POLARITY_IDLE;
06863                      callerid_free(cs);
06864                      ast_hangup(chan);
06865                      goto quit;
06866                   }
06867                   res = 0;
06868                   /* Let us detect callerid when the telco uses distinctive ring */
06869 
06870                   curRingData[receivedRingT] = p->ringt;
06871 
06872                   if (p->ringt < p->ringt_base/2)
06873                      break;
06874                   /* Increment the ringT counter so we can match it against
06875                      values in chan_dahdi.conf for distinctive ring */
06876                   if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06877                      break;
06878                } else if (i & DAHDI_IOMUX_READ) {
06879                   res = read(p->subs[index].dfd, buf, sizeof(buf));
06880                   if (res < 0) {
06881                      if (errno != ELAST) {
06882                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06883                         callerid_free(cs);
06884                         ast_hangup(chan);
06885                         goto quit;
06886                      }
06887                      break;
06888                   }
06889                   if (p->ringt) 
06890                      p->ringt--;
06891                   if (p->ringt == 1) {
06892                      res = -1;
06893                      break;
06894                   }
06895                   samples += res;
06896                   res = callerid_feed(cs, buf, res, AST_LAW(p));
06897                   if (res < 0) {
06898                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
06899                      break;
06900                   } else if (res)
06901                      break;
06902                   else if (samples > (8000 * 10))
06903                      break;
06904                }
06905             }
06906             if (res == 1) {
06907                callerid_get(cs, &name, &number, &flags);
06908                if (option_debug)
06909                   ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
06910             }
06911             if (distinctiveringaftercid == 1) {
06912                /* Clear the current ring data array so we dont have old data in it. */
06913                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
06914                   curRingData[receivedRingT] = 0;
06915                }
06916                receivedRingT = 0;
06917                if (option_verbose > 2)
06918                   ast_verbose( VERBOSE_PREFIX_3 "Detecting post-CID distinctive ring\n");
06919                for (;;) {
06920                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
06921                   if ((res = ioctl(p->subs[index].dfd, DAHDI_IOMUX, &i)))    {
06922                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
06923                      callerid_free(cs);
06924                      ast_hangup(chan);
06925                      goto quit;
06926                   }
06927                   if (i & DAHDI_IOMUX_SIGEVENT) {
06928                      res = dahdi_get_event(p->subs[index].dfd);
06929                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
06930                      res = 0;
06931                      /* Let us detect callerid when the telco uses distinctive ring */
06932 
06933                      curRingData[receivedRingT] = p->ringt;
06934 
06935                      if (p->ringt < p->ringt_base/2)
06936                         break;
06937                      /* Increment the ringT counter so we can match it against
06938                         values in chan_dahdi.conf for distinctive ring */
06939                      if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
06940                         break;
06941                   } else if (i & DAHDI_IOMUX_READ) {
06942                      res = read(p->subs[index].dfd, buf, sizeof(buf));
06943                      if (res < 0) {
06944                         if (errno != ELAST) {
06945                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
06946                            callerid_free(cs);
06947                            ast_hangup(chan);
06948                            goto quit;
06949                         }
06950                         break;
06951                      }
06952                   if (p->ringt)
06953                      p->ringt--;
06954                      if (p->ringt == 1) {
06955                         res = -1;
06956                         break;
06957                      }
06958                   }
06959                }
06960             }
06961             if (p->usedistinctiveringdetection) {
06962                if (option_verbose > 2)
06963                   /* this only shows up if you have n of the dring patterns filled in */
06964                   ast_verbose( VERBOSE_PREFIX_3 "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
06965 
06966                for (counter = 0; counter < 3; counter++) {
06967                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
06968                   channel */
06969                   if (option_verbose > 2)
06970                      /* this only shows up if you have n of the dring patterns filled in */
06971                      ast_verbose( VERBOSE_PREFIX_3 "Checking %d,%d,%d\n",
06972                         p->drings.ringnum[counter].ring[0],
06973                         p->drings.ringnum[counter].ring[1],
06974                         p->drings.ringnum[counter].ring[2]);
06975                   distMatches = 0;
06976                   for (counter1 = 0; counter1 < 3; counter1++) {
06977                      if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1]+10) && curRingData[counter1] >=
06978                      (p->drings.ringnum[counter].ring[counter1]-10)) {
06979                         distMatches++;
06980                      }
06981                   }
06982                   if (distMatches == 3) {
06983                      /* The ring matches, set the context to whatever is for distinctive ring.. */
06984                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
06985                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
06986                      if (option_verbose > 2)
06987                         ast_verbose( VERBOSE_PREFIX_3 "Distinctive Ring matched context %s\n",p->context);
06988                      break;
06989                   }
06990                }
06991             }
06992             /* Restore linear mode (if appropriate) for Caller*ID processing */
06993             dahdi_setlinear(p->subs[index].dfd, p->subs[index].linear);
06994 #if 1
06995             restore_gains(p);
06996 #endif            
06997             if (res < 0) {
06998                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
06999             }
07000          } else
07001             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07002       }
07003       else
07004          cs = NULL;
07005 
07006       if (number)
07007          ast_shrink_phone_number(number);
07008       ast_set_callerid(chan, number, name, number);
07009 
07010       if (smdi_msg)
07011          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07012 
07013       if (cs)
07014          callerid_free(cs);
07015 
07016       ast_setstate(chan, AST_STATE_RING);
07017       chan->rings = 1;
07018       p->ringt = p->ringt_base;
07019       res = ast_pbx_run(chan);
07020       if (res) {
07021          ast_hangup(chan);
07022          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07023       }
07024       goto quit;
07025    default:
07026       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07027       res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07028       if (res < 0)
07029             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07030    }
07031    res = tone_zone_play_tone(p->subs[index].dfd, DAHDI_TONE_CONGESTION);
07032    if (res < 0)
07033          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07034    ast_hangup(chan);
07035 quit:
07036    ast_mutex_lock(&ss_thread_lock);
07037    ss_thread_count--;
07038    ast_cond_signal(&ss_thread_complete);
07039    ast_mutex_unlock(&ss_thread_lock);
07040    return NULL;
07041 }

static int start_pri ( struct dahdi_pri pri  )  [static]

Definition at line 9997 of file chan_dahdi.c.

References ast_log(), dahdi_close_pri_fd(), DAHDI_FILE_CHANNEL, DCHAN_NOTINALARM, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, DEFAULT_PRI_DEBUG, errno, dahdi_pri::fds, dahdi_pri::inbanddisconnect, LOG_ERROR, dahdi_pri::nodetype, dahdi_pri::nsf, dahdi_pri::overlapdial, and dahdi_pri::switchtype.

Referenced by setup_dahdi().

09998 {
09999    int res, x;
10000    struct dahdi_params p;
10001    struct dahdi_bufferinfo bi;
10002    struct dahdi_spaninfo si;
10003    int i;
10004    
10005    for (i = 0; i < NUM_DCHANS; i++) {
10006       if (!pri->dchannels[i])
10007          break;
10008       pri->fds[i] = open(DAHDI_FILE_CHANNEL, O_RDWR, 0600);
10009       x = pri->dchannels[i];
10010       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
10011          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
10012          return -1;
10013       }
10014       memset(&p, 0, sizeof(p));
10015       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
10016       if (res) {
10017          dahdi_close_pri_fd(pri, i);
10018          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
10019          return -1;
10020       }
10021       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
10022          dahdi_close_pri_fd(pri, i);
10023          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi/system.conf\n", x);
10024          return -1;
10025       }
10026       memset(&si, 0, sizeof(si));
10027       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
10028       if (res) {
10029          dahdi_close_pri_fd(pri, i);
10030          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
10031       }
10032       if (!si.alarms)
10033          pri->dchanavail[i] |= DCHAN_NOTINALARM;
10034       else
10035          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
10036       memset(&bi, 0, sizeof(bi));
10037       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
10038       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
10039       bi.numbufs = 32;
10040       bi.bufsize = 1024;
10041       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
10042          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
10043          dahdi_close_pri_fd(pri, i);
10044          return -1;
10045       }
10046       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
10047       /* Force overlap dial if we're doing GR-303! */
10048       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
10049          pri->overlapdial = 1;
10050       pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
10051 #ifdef HAVE_PRI_INBANDDISCONNECT
10052       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
10053 #endif
10054       /* Enslave to master if appropriate */
10055       if (i)
10056          pri_enslave(pri->dchans[0], pri->dchans[i]);
10057       if (!pri->dchans[i]) {
10058          dahdi_close_pri_fd(pri, i);
10059          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
10060          return -1;
10061       }
10062       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
10063       pri_set_nsf(pri->dchans[i], pri->nsf);
10064 #ifdef PRI_GETSET_TIMERS
10065       for (x = 0; x < PRI_MAX_TIMERS; x++) {
10066          if (pritimers[x] != 0)
10067             pri_set_timer(pri->dchans[i], x, pritimers[x]);
10068       }
10069 #endif
10070    }
10071    /* Assume primary is the one we use */
10072    pri->pri = pri->dchans[0];
10073    pri->resetpos = -1;
10074    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
10075       for (i = 0; i < NUM_DCHANS; i++) {
10076          if (!pri->dchannels[i])
10077             break;
10078          dahdi_close_pri_fd(pri, i);
10079       }
10080       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
10081       return -1;
10082    }
10083    return 0;
10084 }

static void swap_subs ( struct dahdi_pvt p,
int  a,
int  b 
) [static]

Definition at line 1193 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::chan, dahdi_subchannel::dfd, ast_channel::fds, dahdi_subchannel::inthreeway, LOG_DEBUG, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

Referenced by attempt_transfer(), dahdi_answer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().

01194 {
01195    int tchan;
01196    int tinthreeway;
01197    struct ast_channel *towner;
01198 
01199    ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
01200 
01201    tchan = p->subs[a].chan;
01202    towner = p->subs[a].owner;
01203    tinthreeway = p->subs[a].inthreeway;
01204 
01205    p->subs[a].chan = p->subs[b].chan;
01206    p->subs[a].owner = p->subs[b].owner;
01207    p->subs[a].inthreeway = p->subs[b].inthreeway;
01208 
01209    p->subs[b].chan = tchan;
01210    p->subs[b].owner = towner;
01211    p->subs[b].inthreeway = tinthreeway;
01212 
01213    if (p->subs[a].owner) 
01214       p->subs[a].owner->fds[0] = p->subs[a].dfd;
01215    if (p->subs[b].owner) 
01216       p->subs[b].owner->fds[0] = p->subs[b].dfd;
01217    wakeup_sub(p, a, NULL);
01218    wakeup_sub(p, b, NULL);
01219 }

static int unalloc_sub ( struct dahdi_pvt p,
int  x 
) [static]

Definition at line 1332 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::chan, dahdi_pvt::channel, dahdi_subchannel::curconf, dahdi_close_sub(), dahdi_subchannel::inthreeway, dahdi_subchannel::linear, LOG_DEBUG, LOG_WARNING, dahdi_subchannel::owner, dahdi_pvt::polarity, POLARITY_IDLE, and dahdi_pvt::subs.

Referenced by attempt_transfer(), dahdi_handle_event(), dahdi_hangup(), and ss_thread().

01333 {
01334    if (!x) {
01335       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01336       return -1;
01337    }
01338    ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
01339    dahdi_close_sub(p, x);
01340    p->subs[x].linear = 0;
01341    p->subs[x].chan = 0;
01342    p->subs[x].owner = NULL;
01343    p->subs[x].inthreeway = 0;
01344    p->polarity = POLARITY_IDLE;
01345    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01346    return 0;
01347 }

static int unload_module ( void   )  [static]

Definition at line 11251 of file chan_dahdi.c.

References __unload_module(), ast_mutex_destroy, lock, NUM_SPANS, and pris.

11252 {
11253 #ifdef HAVE_PRI      
11254    int y;
11255    for (y = 0; y < NUM_SPANS; y++)
11256       ast_mutex_destroy(&pris[y].lock);
11257 #endif
11258    return __unload_module();
11259 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1713 of file chan_dahdi.c.

References conf_add(), conf_del(), dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, isslavenative(), and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_handle_event(), and dahdi_hangup().

01714 {
01715    int needconf = 0;
01716    int x;
01717    int useslavenative;
01718    struct dahdi_pvt *slave = NULL;
01719 
01720    useslavenative = isslavenative(p, &slave);
01721    /* Start with the obvious, general stuff */
01722    for (x = 0; x < 3; x++) {
01723       /* Look for three way calls */
01724       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01725          conf_add(p, &p->subs[x], x, 0);
01726          needconf++;
01727       } else {
01728          conf_del(p, &p->subs[x], x);
01729       }
01730    }
01731    /* If we have a slave, add him to our conference now. or DAX
01732       if this is slave native */
01733    for (x = 0; x < MAX_SLAVES; x++) {
01734       if (p->slaves[x]) {
01735          if (useslavenative)
01736             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01737          else {
01738             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01739             needconf++;
01740          }
01741       }
01742    }
01743    /* If we're supposed to be in there, do so now */
01744    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01745       if (useslavenative)
01746          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01747       else {
01748          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01749          needconf++;
01750       }
01751    }
01752    /* If we have a master, add ourselves to his conference */
01753    if (p->master) {
01754       if (isslavenative(p->master, NULL)) {
01755          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01756       } else {
01757          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01758       }
01759    }
01760    if (!needconf) {
01761       /* Nobody is left (or should be left) in our conference.
01762          Kill it. */
01763       p->confno = -1;
01764    }
01765    if (option_debug)
01766       ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
01767    return 0;
01768 }

static void wakeup_sub ( struct dahdi_pvt p,
int  a,
struct dahdi_pri pri 
) [static]

Definition at line 1135 of file chan_dahdi.c.

References ast_mutex_trylock, ast_mutex_unlock, ast_null_frame, ast_queue_frame(), and DEADLOCK_AVOIDANCE.

Referenced by swap_subs().

01139 {
01140 #ifdef HAVE_PRI
01141    if (pri)
01142       ast_mutex_unlock(&pri->lock);
01143 #endif         
01144    for (;;) {
01145       if (p->subs[a].owner) {
01146          if (ast_mutex_trylock(&p->subs[a].owner->lock)) {
01147             DEADLOCK_AVOIDANCE(&p->lock);
01148          } else {
01149             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01150             ast_mutex_unlock(&p->subs[a].owner->lock);
01151             break;
01152          }
01153       } else
01154          break;
01155    }
01156 #ifdef HAVE_PRI
01157    if (pri)
01158       ast_mutex_lock(&pri->lock);
01159 #endif         
01160 }

static int zap_action_dialoffhook ( struct mansession s,
const struct message m 
) [static]

Definition at line 11097 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

11098 {
11099    return __action_dialoffhook(s, m, 1);
11100 }

static int zap_action_dndoff ( struct mansession s,
const struct message m 
) [static]

Definition at line 10997 of file chan_dahdi.c.

References __action_dnd(), and s.

10998 {
10999    return __action_dnd(s, m, 1, 0);
11000 }

static int zap_action_dndon ( struct mansession s,
const struct message m 
) [static]

Definition at line 10987 of file chan_dahdi.c.

References __action_dnd(), and s.

10988 {
10989    return __action_dnd(s, m, 1, 1);
10990 }

static int zap_action_restart ( struct mansession s,
const struct message m 
) [static]

Definition at line 11176 of file chan_dahdi.c.

References __action_restart(), and s.

11177 {
11178    return __action_restart(s, m, 1);
11179 }

static int zap_action_showchannels ( struct mansession s,
const struct message m 
) [static]

Definition at line 11152 of file chan_dahdi.c.

References __action_showchannels(), and s.

11153 {
11154    return __action_showchannels(s, m, 1);
11155 }

static int zap_action_transfer ( struct mansession s,
const struct message m 
) [static]

Definition at line 11026 of file chan_dahdi.c.

References __action_transfer(), and s.

11027 {
11028    return __action_transfer(s, m, 1);
11029 }

static int zap_action_transferhangup ( struct mansession s,
const struct message m 
) [static]

Definition at line 11054 of file chan_dahdi.c.

References __action_transferhangup(), and s.

11055 {
11056    return __action_transferhangup(s, m, 1);
11057 }

static int zap_send_keypad_facility_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 2730 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and send_keypad_facility_exec().

Referenced by load_module().

02731 {
02732    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);  
02733    return send_keypad_facility_exec(chan, data);
02734 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "DAHDI Telephony w/PRI" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "6989f2ec67f8497e38c12890500c525b" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 12402 of file chan_dahdi.c.

int alarm

Definition at line 1484 of file chan_dahdi.c.

Referenced by __action_showchannels().

struct { ... } alarms[] [static]

Referenced by alarm2str(), and dahdi_show_status().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 12402 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 1093 of file chan_dahdi.c.

struct ast_channel_tech* chan_tech [static]

Definition at line 1061 of file chan_dahdi.c.

Referenced by __unload_module(), ast_device_state(), dahdi_new(), load_module(), and ss_thread().

int cidrings[NUM_CADENCE_MAX] [static]

cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.

Definition at line 1104 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_destroy_channel_deprecated [static]

Initial value:

 {
   { "zap", "destroy", "channel", NULL },
   dahdi_destroy_channel, NULL,
   NULL }

Definition at line 10893 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_restart_deprecated [static]

Initial value:

 {
   { "zap", "restart", NULL },
   dahdi_restart_cmd, NULL,
   NULL }

Definition at line 10898 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_cadences_deprecated [static]

Initial value:

 {
   { "zap", "show", "cadences", NULL },
   handle_dahdi_show_cadences, NULL,
   NULL }

Definition at line 10878 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_channel_deprecated [static]

Initial value:

 {
   { "zap", "show", "channel", NULL },
   dahdi_show_channel, NULL,
   NULL }

Definition at line 10888 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_channels_deprecated [static]

Initial value:

 {
   { "zap", "show", "channels", NULL },
   dahdi_show_channels, NULL,
   NULL }

Definition at line 10883 of file chan_dahdi.c.

struct ast_cli_entry cli_zap_show_status_deprecated [static]

Initial value:

 {
   { "zap", "show", "status", NULL },
   dahdi_show_status, NULL,
   NULL }

Definition at line 10903 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 10908 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 10369 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

char dahdi_restart_usage[] [static]

Definition at line 10871 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 2672 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_descrip [static]

Initial value:

 
"  DAHDISendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
"  IE over the current channel.\n"

Definition at line 2678 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static]

Definition at line 2675 of file chan_dahdi.c.

char dahdi_show_cadences_usage[] [static]

Initial value:

"Usage: dahdi show cadences\n"
"       Shows all cadences currently defined\n"

Definition at line 10764 of file chan_dahdi.c.

char dahdi_show_status_usage[] [static]

Initial value:

   "Usage: dahdi show status\n"
   "       Shows a list of DAHDI cards with status\n"

Definition at line 10863 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1019 of file chan_dahdi.c.

Referenced by load_module().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 110 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 199 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 200 of file chan_dahdi.c.

char destroy_channel_usage[] [static]

Initial value:

   "Usage: dahdi destroy channel <chan num>\n"
   "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n"

Definition at line 10867 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 204 of file chan_dahdi.c.

struct dahdi_distRings drings [static]

Definition at line 380 of file chan_dahdi.c.

Referenced by process_dahdi().

char* events[] [static]

Definition at line 1461 of file chan_dahdi.c.

Referenced by authenticate(), and geteventbyname().

int firstdigittimeout = 16000 [static]

Wait up to 16 seconds for first digit (FXO logic).

Definition at line 218 of file chan_dahdi.c.

Referenced by disa_exec(), mgcp_ss(), and skinny_ss().

int gendigittimeout = 8000 [static]

How long to wait for following digits (FXO logic).

Definition at line 221 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 117 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 230 of file chan_dahdi.c.

struct dahdi_pvt * ifend [static]

struct dahdi_pvt * iflist [static]

Referenced by __action_showchannels(), __oh323_destroy(), __sip_destroy(), __sip_show_channels(), __unload_module(), chandup(), complete_sipch(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call(), find_call_locked(), find_channel(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), mkintf(), oh323_alloc(), phone_request(), sip_alloc(), sip_show_channel(), sip_show_history(), and unload_module().

ast_mutex_t iflock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Protect the interface list (of dahdi_pvt's).

Definition at line 227 of file chan_dahdi.c.

Referenced by __action_showchannels(), __sip_show_channels(), __unload_module(), complete_sipch(), dahdi_hangup(), dahdi_request(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), find_call(), find_call_locked(), get_sip_pvt_byid_locked(), handle_request_subscribe(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), setup_dahdi(), sip_alloc(), sip_destroy(), sip_show_channel(), sip_show_history(), and unload_module().

struct ast_channel inuse [static]

Definition at line 209 of file chan_dahdi.c.

Referenced by ast_jb_do_usecheck(), chanavail_exec(), load_module(), pri_assign_bearer(), and update_call_counter().

int matchdigittimeout = 3000 [static]

How long to wait for an extra digit, if there is an ambiguous match.

Definition at line 224 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

This is the thread for the monitor which checks for input on the channels which are not currently in use.

Definition at line 242 of file chan_dahdi.c.

Referenced by reload_config(), restart_monitor(), and unload_module().

ast_mutex_t monlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.

Definition at line 238 of file chan_dahdi.c.

Referenced by __unload_module(), dahdi_restart(), do_monitor(), restart_monitor(), and unload_module().

char* name

Definition at line 1485 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1090 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 247 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 206 of file chan_dahdi.c.

const char pri_debug_help[] [static]

Initial value:

 
   "Usage: pri debug span <span>\n"
   "       Enables debugging on a given PRI span\n"

Definition at line 10349 of file chan_dahdi.c.

const char pri_no_debug_help[] [static]

Initial value:

 
   "Usage: pri no debug span <span>\n"
   "       Disables debugging on a given PRI span\n"

Definition at line 10353 of file chan_dahdi.c.

const char pri_really_debug_help[] [static]

Initial value:

 
   "Usage: pri intensive debug span <span>\n"
   "       Enables debugging down to the Q.921 level\n"

Definition at line 10357 of file chan_dahdi.c.

const char pri_show_span_help[] [static]

Initial value:

 
   "Usage: pri show span <span>\n"
   "       Displays PRI Information on a given PRI span\n"

Definition at line 10361 of file chan_dahdi.c.

const char pri_show_spans_help[] [static]

Initial value:

 
   "Usage: pri show spans\n"
   "       Displays PRI Information\n"

Definition at line 10365 of file chan_dahdi.c.

int pridebugfd = -1 [static]

Definition at line 213 of file chan_dahdi.c.

ast_mutex_t pridebugfdlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Definition at line 233 of file chan_dahdi.c.

Referenced by dahdi_pri_error(), dahdi_pri_message(), handle_pri_set_debug_file(), and handle_pri_show_debug().

char pridebugfilename[1024] = "" [static]

Definition at line 214 of file chan_dahdi.c.

struct dahdi_pri pris[NUM_SPANS] [static]

Definition at line 353 of file chan_dahdi.c.

Referenced by __unload_module(), build_channels(), complete_span_helper(), dahdi_pri_error(), dahdi_pri_message(), dahdi_request(), dahdi_restart(), dahdi_show_channel(), dahdi_show_channels(), handle_pri_debug(), handle_pri_no_debug(), handle_pri_really_debug(), handle_pri_show_debug(), handle_pri_show_span(), handle_pri_show_spans(), load_module(), mkintf(), pri_create_spanmap(), pri_create_trunkgroup(), pri_find_principle(), pri_resolve_span(), setup_dahdi(), and unload_module().

char progzone[10] = "" [static]

Definition at line 202 of file chan_dahdi.c.

ast_mutex_t restart_lock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Definition at line 245 of file chan_dahdi.c.

Referenced by dahdi_restart().

int ringt_base = DEFAULT_RINGT [static]

Configured ring timeout base.

Note:
Value computed from "ringtimeout" read in from chan_dahdi.conf if it exists.

Definition at line 294 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32]

Definition at line 1069 of file chan_dahdi.c.

Referenced by dahdi_request(), and load_module().

char show_channel_usage[] [static]

Initial value:

   "Usage: dahdi show channel <chan num>\n"
   "  Detailed information about a given channel\n"

Definition at line 10859 of file chan_dahdi.c.

char show_channels_usage[] [static]

Initial value:

   "Usage: dahdi show channels\n"
   "  Shows a list of available channels\n"

Definition at line 10855 of file chan_dahdi.c.

ast_cond_t ss_thread_complete [static]

Definition at line 243 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 246 of file chan_dahdi.c.

ast_mutex_t ss_thread_lock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Definition at line 244 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

char* subnames[] [static]

Initial value:

 {
   "Real",
   "Callwait",
   "Threeway"
}

Definition at line 393 of file chan_dahdi.c.

const char tdesc[] [static]

Initial value:

 "DAHDI Telephony Driver"

               " w/PRI"

Definition at line 156 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 1091 of file chan_dahdi.c.

char* zap_send_keypad_facility_app = "ZapSendKeypadFacility" [static]

Definition at line 2673 of file chan_dahdi.c.

char* zap_send_keypad_facility_descrip [static]

Initial value:

 
"  ZapSendKeypadFacility(): This application will send the given string of digits in a Keypad Facility\n"
"  IE over the current channel.\n"

Definition at line 2681 of file chan_dahdi.c.

char* zap_send_keypad_facility_synopsis = "Send digits out of band over a PRI" [static]

Definition at line 2676 of file chan_dahdi.c.

struct ast_channel_tech zap_tech [static]

Definition at line 1040 of file chan_dahdi.c.

Referenced by load_module().


Generated on Thu Oct 8 00:59:24 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7