Fri Apr 24 16:26:14 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 = "f450f61f60e761b3aa089ebed76ca8a5" , .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 = ((ast_mutex_t) 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 = ((ast_mutex_t) 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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char pridebugfilename [1024] = ""
static struct dahdi_pri pris [NUM_SPANS]
static char progzone [10] = ""
static ast_mutex_t restart_lock = ((ast_mutex_t) 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 = ((ast_mutex_t) 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 10911 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 10941 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 10942 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 12176 of file chan_dahdi.c.

Referenced by load_module().

#define local_astman_unregister (  ) 

Definition at line 11162 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 11329 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_dchannel(), 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 12358 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 10910 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 11040 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().

11041 {
11042    struct dahdi_pvt *p = NULL;
11043    const char *channel = local_astman_header(m, "Channel", zap_mode);
11044    const char *number = astman_get_header(m, "Number");
11045    int i;
11046 
11047    if (ast_strlen_zero(channel)) {
11048       astman_send_error(s, m, "No channel specified");
11049       return 0;
11050    }
11051    if (ast_strlen_zero(number)) {
11052       astman_send_error(s, m, "No number specified");
11053       return 0;
11054    }
11055    if (!(p = find_channel(atoi(channel)))) {
11056       astman_send_error(s, m, "No such channel");
11057       return 0;
11058    }
11059    if (!p->owner) {
11060       astman_send_error(s, m, "Channel does not have an owner");
11061       return 0;
11062    }
11063    for (i = 0; i < strlen(number); i++) {
11064       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
11065 
11066       dahdi_queue_frame(p, &f, NULL); 
11067    }
11068    local_astman_ack(s, m, "DialOffHook", zap_mode);
11069 
11070    return 0;
11071 }

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

Definition at line 10944 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().

10945 {
10946    struct dahdi_pvt *p = NULL;
10947    const char *channel = local_astman_header(m, "Channel", zap_mode);
10948 
10949    if (ast_strlen_zero(channel)) {
10950       astman_send_error(s, m, "No channel specified");
10951       return 0;
10952    }
10953    if (!(p = find_channel(atoi(channel)))) {
10954       astman_send_error(s, m, "No such channel");
10955       return 0;
10956    }
10957    p->dnd = dnd;
10958    local_astman_ack(s, m, "DND", zap_mode);
10959 
10960    return 0;
10961 }

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

Definition at line 11138 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().

11139 {
11140    if (dahdi_restart() != 0) {
11141       if (zap_mode) {
11142          astman_send_error(s, m, "Failed to restart Zap");
11143       } else {
11144          astman_send_error(s, m, "Failed to restart DAHDI");
11145       }
11146       return 1;
11147    }
11148    local_astman_ack(s, m, "Restart: Success", zap_mode);
11149    return 0;
11150 }

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

Definition at line 11083 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().

11084 {
11085    struct dahdi_pvt *tmp = NULL;
11086    const char *id = astman_get_header(m, "ActionID");
11087    char idText[256] = "";
11088 
11089    local_astman_ack(s, m, " channel status will follow", zap_mode);
11090    if (!ast_strlen_zero(id))
11091       snprintf(idText, sizeof(idText) - 1, "ActionID: %s\r\n", id);
11092 
11093    ast_mutex_lock(&iflock);
11094    
11095    tmp = iflist;
11096    while (tmp) {
11097       if (tmp->channel > 0) {
11098          int alarm = get_alarms(tmp);
11099          astman_append(s,
11100                   "Event: %sShowChannels\r\n"
11101                   "Channel: %d\r\n"
11102                   "Signalling: %s\r\n"
11103                   "Context: %s\r\n"
11104                   "DND: %s\r\n"
11105                   "Alarm: %s\r\n"
11106                   "%s"
11107                   "\r\n",
11108                   dahdi_chan_name,
11109                   tmp->channel, sig2str(tmp->sig), tmp->context, 
11110                   tmp->dnd ? "Enabled" : "Disabled",
11111                   alarm2str(alarm), idText);
11112       } 
11113 
11114       tmp = tmp->next;
11115    }
11116 
11117    ast_mutex_unlock(&iflock);
11118    
11119    astman_append(s, 
11120             "Event: %sShowChannelsComplete\r\n"
11121             "%s"
11122             "\r\n",
11123             dahdi_chan_name,
11124             idText);
11125    return 0;
11126 }

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

Definition at line 10983 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().

10984 {
10985    struct dahdi_pvt *p = NULL;
10986    const char *channel = local_astman_header(m, "Channel", zap_mode);
10987 
10988    if (ast_strlen_zero(channel)) {
10989       astman_send_error(s, m, "No channel specified");
10990       return 0;
10991    }
10992    if (!(p = find_channel(atoi(channel)))) {
10993       astman_send_error(s, m, "No such channel");
10994       return 0;
10995    }
10996    dahdi_fake_event(p,TRANSFER);
10997    local_astman_ack(s, m, "Transfer", zap_mode);
10998 
10999    return 0;
11000 }

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

Definition at line 11012 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().

11013 {
11014    struct dahdi_pvt *p = NULL;
11015    const char *channel = local_astman_header(m, "Channel", zap_mode);
11016 
11017    if (ast_strlen_zero(channel)) {
11018       astman_send_error(s, m, "No channel specified");
11019       return 0;
11020    }
11021    if (!(p = find_channel(atoi(channel)))) {
11022       astman_send_error(s, m, "No such channel");
11023       return 0;
11024    }
11025    dahdi_fake_event(p, HANGUP);
11026    local_astman_ack(s, m, "Hangup", zap_mode);
11027    return 0;
11028 }

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 12367 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 11169 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().

11170 {
11171    struct dahdi_pvt *p;
11172 
11173 #ifdef HAVE_PRI
11174    int i, j;
11175    for (i = 0; i < NUM_SPANS; i++) {
11176       if (pris[i].master != AST_PTHREADT_NULL) 
11177          pthread_cancel(pris[i].master);
11178    }
11179    ast_cli_unregister_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
11180 
11181    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
11182       ast_unregister_application(dahdi_send_keypad_facility_app);
11183    }
11184    ast_unregister_application(zap_send_keypad_facility_app);
11185 #endif
11186    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
11187    local_astman_unregister("DialOffHook");
11188    local_astman_unregister("Hangup");
11189    local_astman_unregister("Transfer");
11190    local_astman_unregister("DNDoff");
11191    local_astman_unregister("DNDon");
11192    local_astman_unregister("ShowChannels");
11193    local_astman_unregister("Restart");
11194    ast_channel_unregister(chan_tech);
11195    ast_mutex_lock(&iflock);
11196    /* Hangup all interfaces if they have an owner */
11197    p = iflist;
11198    while (p) {
11199       if (p->owner)
11200          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
11201       p = p->next;
11202    }
11203    ast_mutex_unlock(&iflock);
11204    ast_mutex_lock(&monlock);
11205    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
11206       pthread_cancel(monitor_thread);
11207       pthread_kill(monitor_thread, SIGURG);
11208       pthread_join(monitor_thread, NULL);
11209    }
11210    monitor_thread = AST_PTHREADT_STOP;
11211    ast_mutex_unlock(&monlock);
11212 
11213    destroy_all_channels();
11214 #ifdef HAVE_PRI      
11215    for (i = 0; i < NUM_SPANS; i++) {
11216       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
11217          pthread_join(pris[i].master, NULL);
11218       for (j = 0; j < NUM_DCHANS; j++) {
11219          dahdi_close_pri_fd(&(pris[i]), j);
11220       }
11221    }
11222 #endif
11223    ast_cond_destroy(&ss_thread_complete);
11224    return 0;
11225 }

static void __unreg_module ( void   )  [static]

Definition at line 12367 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 8839 of file chan_dahdi.c.

References dahdi_pri::internationalprefix, dahdi_pri::localprefix, dahdi_pri::nationalprefix, dahdi_pri::privateprefix, and dahdi_pri::unknownprefix.

08840 {
08841    switch (plan) {
08842    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
08843       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
08844       break;
08845    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
08846       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
08847       break;
08848    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
08849       snprintf(buf, size, "%s%s", pri->localprefix, number);
08850       break;
08851    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
08852       snprintf(buf, size, "%s%s", pri->privateprefix, number);
08853       break;
08854    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
08855       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
08856       break;
08857    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
08858       snprintf(buf, size, "%s", number);
08859       break;
08860    }
08861 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 3908 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().

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

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

Definition at line 8108 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().

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

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 11237 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().

11238 {
11239    char *c, *chan;
11240    int x, start, finish;
11241    struct dahdi_pvt *tmp;
11242 #ifdef HAVE_PRI
11243    struct dahdi_pri *pri;
11244    int trunkgroup, y;
11245 #endif
11246    
11247    if ((reload == 0) && (conf->chan.sig < 0)) {
11248       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
11249       return -1;
11250    }
11251 
11252    c = ast_strdupa(value);
11253 
11254 #ifdef HAVE_PRI
11255    pri = NULL;
11256    if (iscrv) {
11257       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
11258          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d\n", lineno);
11259          return -1;
11260       }
11261       if (trunkgroup < 1) {
11262          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d\n", lineno);
11263          return -1;
11264       }
11265       c += y;
11266       for (y = 0; y < NUM_SPANS; y++) {
11267          if (pris[y].trunkgroup == trunkgroup) {
11268             pri = pris + y;
11269             break;
11270          }
11271       }
11272       if (!pri) {
11273          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d\n", trunkgroup, lineno);
11274          return -1;
11275       }
11276    }
11277 #endif         
11278 
11279    while ((chan = strsep(&c, ","))) {
11280       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
11281          /* Range */
11282       } else if (sscanf(chan, "%d", &start)) {
11283          /* Just one */
11284          finish = start;
11285       } else if (!strcasecmp(chan, "pseudo")) {
11286          finish = start = CHAN_PSEUDO;
11287          if (found_pseudo)
11288             *found_pseudo = 1;
11289       } else {
11290          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
11291          return -1;
11292       }
11293       if (finish < start) {
11294          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
11295          x = finish;
11296          finish = start;
11297          start = x;
11298       }
11299 
11300       for (x = start; x <= finish; x++) {
11301 #ifdef HAVE_PRI
11302          tmp = mkintf(x, conf, pri, reload);
11303 #else       
11304          tmp = mkintf(x, conf, NULL, reload);
11305 #endif         
11306 
11307          if (tmp) {
11308             if (option_verbose > 2) {
11309 #ifdef HAVE_PRI
11310                if (pri)
11311                   ast_verbose(VERBOSE_PREFIX_3 "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
11312                else
11313 #endif
11314                   ast_verbose(VERBOSE_PREFIX_3 "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
11315             }
11316          } else {
11317             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
11318                (reload == 1) ? "reconfigure" : "register", value);
11319             return -1;
11320          }
11321       }
11322    }
11323 
11324    return 0;
11325 }

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

Definition at line 10216 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

10217 {
10218    if (!s || len < 1) {
10219       return;
10220    }
10221    s[0] = '\0';
10222    if (status & DCHAN_PROVISIONED)
10223       strncat(s, "Provisioned, ", len - strlen(s) - 1);
10224    if (!(status & DCHAN_NOTINALARM))
10225       strncat(s, "In Alarm, ", len - strlen(s) - 1);
10226    if (status & DCHAN_UP)
10227       strncat(s, "Up", len - strlen(s) - 1);
10228    else
10229       strncat(s, "Down", len - strlen(s) - 1);
10230    if (active)
10231       strncat(s, ", Active", len - strlen(s) - 1);
10232    else
10233       strncat(s, ", Standby", len - strlen(s) - 1);
10234    s[len - 1] = '\0';
10235 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 1947 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().

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

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

Definition at line 8212 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().

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

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 3960 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().

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

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

Definition at line 10083 of file chan_dahdi.c.

References complete_span_helper().

10084 {
10085    return complete_span_helper(line,word,pos,state,3);
10086 }

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

Definition at line 10088 of file chan_dahdi.c.

References complete_span_helper().

10089 {
10090    return complete_span_helper(line,word,pos,state,4);
10091 }

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

Definition at line 10064 of file chan_dahdi.c.

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

Referenced by complete_span_4(), and complete_span_5().

10065 {
10066    int which, span;
10067    char *ret = NULL;
10068 
10069    if (pos != rpos)
10070       return ret;
10071 
10072    for (which = span = 0; span < NUM_SPANS; span++) {
10073       if (pris[span].pri && ++which > state) {
10074          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
10075             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
10076          }
10077          break;
10078       }
10079    }
10080    return ret;
10081 }

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    zi.chan = 0;
01647    zi.confno = 0;
01648    zi.confmode = 0;
01649    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01650       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01651       return -1;
01652    }
01653    ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01654    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01655    return 0;
01656 }

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

Definition at line 11078 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

11079 {
11080    return __action_dialoffhook(s, m, 0);
11081 }

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

Definition at line 10978 of file chan_dahdi.c.

References __action_dnd(), and s.

10979 {
10980    return __action_dnd(s, m, 0, 0);
10981 }

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

Definition at line 10968 of file chan_dahdi.c.

References __action_dnd(), and s.

10969 {
10970    return __action_dnd(s, m, 0, 1);
10971 }

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

Definition at line 11157 of file chan_dahdi.c.

References __action_restart(), and s.

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

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

Definition at line 11133 of file chan_dahdi.c.

References __action_showchannels(), and s.

11134 {
11135    return __action_showchannels(s, m, 0);
11136 }

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

Definition at line 11007 of file chan_dahdi.c.

References __action_transfer(), and s.

11008 {
11009    return __action_transfer(s, m, 0);
11010 }

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

Definition at line 11035 of file chan_dahdi.c.

References __action_transferhangup(), and s.

11036 {
11037    return __action_transferhangup(s, m, 0);
11038 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 3153 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.

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

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 3561 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.

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

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

Definition at line 2136 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.

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 2108 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().

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

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 1991 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().

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

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

Definition at line 10385 of file chan_dahdi.c.

References dahdi_destroy_channel_bynum(), and RESULT_SHOWUSAGE.

10386 {
10387    int channel;
10388    
10389    if (argc != 4)
10390       return RESULT_SHOWUSAGE;
10391    
10392    channel = atoi(argv[3]);
10393 
10394    return dahdi_destroy_channel_bynum(channel);
10395 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 7041 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().

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

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 1822 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().

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

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1772 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().

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

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 10913 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().

10914 {
10915    if (p) {
10916       switch (mode) {
10917          case TRANSFER:
10918             p->fake_event = DAHDI_EVENT_WINKFLASH;
10919             break;
10920          case HANGUP:
10921             p->fake_event = DAHDI_EVENT_ONHOOK;
10922             break;
10923          default:
10924             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
10925       }
10926    }
10927    return 0;
10928 }

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

Definition at line 3852 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.

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

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

Definition at line 3424 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.

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

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 4015 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().

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

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

Definition at line 4117 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().

04118 {
04119    int res, x;
04120    int index, mysig;
04121    char *c;
04122    struct dahdi_pvt *p = ast->tech_pvt;
04123    pthread_t threadid;
04124    pthread_attr_t attr;
04125    struct ast_channel *chan;
04126    struct ast_frame *f;
04127 
04128    index = dahdi_get_index(ast, p, 0);
04129    mysig = p->sig;
04130    if (p->outsigmod > -1)
04131       mysig = p->outsigmod;
04132    p->subs[index].f.frametype = AST_FRAME_NULL;
04133    p->subs[index].f.subclass = 0;
04134    p->subs[index].f.datalen = 0;
04135    p->subs[index].f.samples = 0;
04136    p->subs[index].f.mallocd = 0;
04137    p->subs[index].f.offset = 0;
04138    p->subs[index].f.src = "dahdi_handle_event";
04139    p->subs[index].f.data = NULL;
04140    f = &p->subs[index].f;
04141 
04142    if (index < 0)
04143       return &p->subs[index].f;
04144    if (p->fake_event) {
04145       res = p->fake_event;
04146       p->fake_event = 0;
04147    } else
04148       res = dahdi_get_event(p->subs[index].dfd);
04149 
04150    if (option_debug)
04151       ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
04152 
04153    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04154       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04155 
04156       ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04157 #ifdef HAVE_PRI
04158       if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
04159          /* absorb event */
04160       } else {
04161 #endif
04162          p->subs[index].f.frametype = AST_FRAME_DTMF_END;
04163          p->subs[index].f.subclass = res & 0xff;
04164 #ifdef HAVE_PRI
04165       }
04166 #endif
04167       dahdi_handle_dtmfup(ast, index, &f);
04168       return f;
04169    }
04170 
04171    if (res & DAHDI_EVENT_DTMFDOWN) {
04172       if (option_debug)
04173          ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
04174       /* Mute conference */
04175       dahdi_confmute(p, 1);
04176       p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
04177       p->subs[index].f.subclass = res & 0xff;
04178       return &p->subs[index].f;
04179    }
04180 
04181    switch (res) {
04182 #ifdef DAHDI_EVENT_EC_DISABLED
04183       case DAHDI_EVENT_EC_DISABLED:
04184          if (option_verbose > 2) 
04185             ast_verbose(VERBOSE_PREFIX_3 "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04186          p->echocanon = 0;
04187          break;
04188 #endif
04189       case DAHDI_EVENT_BITSCHANGED:
04190          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04191       case DAHDI_EVENT_PULSE_START:
04192          /* Stop tone if there's a pulse start and the PBX isn't started */
04193          if (!ast->pbx)
04194             tone_zone_play_tone(p->subs[index].dfd, -1);
04195          break;   
04196       case DAHDI_EVENT_DIALCOMPLETE:
04197          if (p->inalarm) break;
04198          if ((p->radio || (p->oprmode < 0))) break;
04199          if (ioctl(p->subs[index].dfd,DAHDI_DIALING,&x) == -1) {
04200             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04201             return NULL;
04202          }
04203          if (!x) { /* if not still dialing in driver */
04204             dahdi_enable_ec(p);
04205             if (p->echobreak) {
04206                dahdi_train_ec(p);
04207                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04208                p->dop.op = DAHDI_DIAL_OP_REPLACE;
04209                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04210                p->echobreak = 0;
04211             } else {
04212                p->dialing = 0;
04213                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04214                   /* if thru with dialing after offhook */
04215                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04216                      ast_setstate(ast, AST_STATE_UP);
04217                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
04218                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04219                      break;
04220                   } else { /* if to state wait for offhook to dial rest */
04221                      /* we now wait for off hook */
04222                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04223                   }
04224                }
04225                if (ast->_state == AST_STATE_DIALING) {
04226                   if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04227                      ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
04228                   } 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)))) {
04229                      ast_setstate(ast, AST_STATE_RINGING);
04230                   } else if (!p->answeronpolarityswitch) {
04231                      ast_setstate(ast, AST_STATE_UP);
04232                      p->subs[index].f.frametype = AST_FRAME_CONTROL;
04233                      p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04234                      /* If aops=0 and hops=1, this is necessary */
04235                      p->polarity = POLARITY_REV;
04236                   } else {
04237                      /* Start clean, so we can catch the change to REV polarity when party answers */
04238                      p->polarity = POLARITY_IDLE;
04239                   }
04240                }
04241             }
04242          }
04243          break;
04244       case DAHDI_EVENT_ALARM:
04245 #ifdef HAVE_PRI
04246          if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04247             /* T309 is not enabled : hangup calls when alarm occurs */
04248             if (p->call) {
04249                if (p->pri && p->pri->pri) {
04250                   if (!pri_grab(p, p->pri)) {
04251                      pri_hangup(p->pri->pri, p->call, -1);
04252                      pri_destroycall(p->pri->pri, p->call);
04253                      p->call = NULL;
04254                      pri_rel(p->pri);
04255                   } else
04256                      ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04257                } else
04258                   ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04259             }
04260             if (p->owner)
04261                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04262          }
04263          if (p->bearer)
04264             p->bearer->inalarm = 1;
04265          else
04266 #endif
04267          p->inalarm = 1;
04268          res = get_alarms(p);
04269          handle_alarms(p, res);
04270 #ifdef HAVE_LIBPRI
04271          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04272             /* fall through intentionally */
04273          } else {
04274             break;
04275          }
04276 #endif
04277       case DAHDI_EVENT_ONHOOK:
04278          if (p->radio) {
04279             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04280             p->subs[index].f.subclass = AST_CONTROL_RADIO_UNKEY;
04281             break;
04282          }
04283          if (p->oprmode < 0)
04284          {
04285             if (p->oprmode != -1) break;
04286             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04287             {
04288                /* Make sure it starts ringing */
04289                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04290                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04291                save_conference(p->oprpeer);
04292                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04293             }
04294             break;
04295          }
04296          switch (p->sig) {
04297          case SIG_FXOLS:
04298          case SIG_FXOGS:
04299          case SIG_FXOKS:
04300             p->onhooktime = time(NULL);
04301             p->msgstate = -1;
04302             /* Check for some special conditions regarding call waiting */
04303             if (index == SUB_REAL) {
04304                /* The normal line was hung up */
04305                if (p->subs[SUB_CALLWAIT].owner) {
04306                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
04307                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04308                   if (option_verbose > 2) 
04309                      ast_verbose(VERBOSE_PREFIX_3 "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04310                   unalloc_sub(p, SUB_CALLWAIT); 
04311 #if 0
04312                   p->subs[index].needanswer = 0;
04313                   p->subs[index].needringing = 0;
04314 #endif                  
04315                   p->callwaitingrepeat = 0;
04316                   p->cidcwexpire = 0;
04317                   p->owner = NULL;
04318                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04319                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04320                      p->dialing = 1;
04321                   dahdi_ring_phone(p);
04322                } else if (p->subs[SUB_THREEWAY].owner) {
04323                   unsigned int mssinceflash;
04324                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04325                      the private structure -- not especially easy or clean */
04326                   while (p->subs[SUB_THREEWAY].owner && ast_mutex_trylock(&p->subs[SUB_THREEWAY].owner->lock)) {
04327                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04328                      ast_mutex_unlock(&p->lock);
04329                      DEADLOCK_AVOIDANCE(&ast->lock);
04330                      /* We can grab ast and p in that order, without worry.  We should make sure
04331                         nothing seriously bad has happened though like some sort of bizarre double
04332                         masquerade! */
04333                      ast_mutex_lock(&p->lock);
04334                      if (p->owner != ast) {
04335                         ast_log(LOG_WARNING, "This isn't good...\n");
04336                         return NULL;
04337                      }
04338                   }
04339                   if (!p->subs[SUB_THREEWAY].owner) {
04340                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04341                      return NULL;
04342                   }
04343                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04344                   ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
04345                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04346                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04347                         hanging up.  Hangup both channels now */
04348                      if (p->subs[SUB_THREEWAY].owner)
04349                         ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
04350                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04351                      ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04352                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04353                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04354                      if (p->transfer) {
04355                         /* In any case this isn't a threeway call anymore */
04356                         p->subs[SUB_REAL].inthreeway = 0;
04357                         p->subs[SUB_THREEWAY].inthreeway = 0;
04358                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04359                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04360                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04361                            /* Swap subs and dis-own channel */
04362                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04363                            p->owner = NULL;
04364                            /* Ring the phone */
04365                            dahdi_ring_phone(p);
04366                         } else {
04367                            if ((res = attempt_transfer(p)) < 0) {
04368                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04369                               if (p->subs[SUB_THREEWAY].owner)
04370                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04371                            } else if (res) {
04372                               /* Don't actually hang up at this point */
04373                               if (p->subs[SUB_THREEWAY].owner)
04374                                  ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04375                               break;
04376                            }
04377                         }
04378                      } else {
04379                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04380                         if (p->subs[SUB_THREEWAY].owner)
04381                            ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04382                      }
04383                   } else {
04384                      ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
04385                      /* Swap subs and dis-own channel */
04386                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04387                      p->owner = NULL;
04388                      /* Ring the phone */
04389                      dahdi_ring_phone(p);
04390                   }
04391                }
04392             } else {
04393                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", index);
04394             }
04395             /* Fall through */
04396          default:
04397             dahdi_disable_ec(p);
04398             return NULL;
04399          }
04400          break;
04401       case DAHDI_EVENT_RINGOFFHOOK:
04402          if (p->inalarm) break;
04403          if (p->oprmode < 0)
04404          {
04405             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04406             {
04407                /* Make sure it stops ringing */
04408                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04409                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04410                restore_conference(p->oprpeer);
04411             }
04412             break;
04413          }
04414          if (p->radio)
04415          {
04416             p->subs[index].f.frametype = AST_FRAME_CONTROL;
04417             p->subs[index].f.subclass = AST_CONTROL_RADIO_KEY;
04418             break;
04419          }
04420          /* for E911, its supposed to wait for offhook then dial
04421             the second half of the dial string */
04422          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04423             c = strchr(p->dialdest, '/');
04424             if (c)
04425                c++;
04426             else
04427                c = p->dialdest;
04428             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
04429             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
04430             if (strlen(p->dop.dialstr) > 4) {
04431                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
04432                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
04433                p->echorest[sizeof(p->echorest) - 1] = '\0';
04434                p->echobreak = 1;
04435                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
04436             } else
04437                p->echobreak = 0;
04438             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
04439                int saveerr = errno;
04440 
04441                x = DAHDI_ONHOOK;
04442                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04443                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
04444                return NULL;
04445                }
04446             p->dialing = 1;
04447             return &p->subs[index].f;
04448          }
04449          switch (p->sig) {
04450          case SIG_FXOLS:
04451          case SIG_FXOGS:
04452          case SIG_FXOKS:
04453             switch (ast->_state) {
04454             case AST_STATE_RINGING:
04455                dahdi_enable_ec(p);
04456                dahdi_train_ec(p);
04457                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04458                p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04459                /* Make sure it stops ringing */
04460                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04461                ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
04462                if (p->cidspill) {
04463                   /* Cancel any running CallerID spill */
04464                   free(p->cidspill);
04465                   p->cidspill = NULL;
04466                }
04467                p->dialing = 0;
04468                p->callwaitcas = 0;
04469                if (p->confirmanswer) {
04470                   /* Ignore answer if "confirm answer" is enabled */
04471                   p->subs[index].f.frametype = AST_FRAME_NULL;
04472                   p->subs[index].f.subclass = 0;
04473                } else if (!ast_strlen_zero(p->dop.dialstr)) {
04474                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
04475                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04476                   if (res < 0) {
04477                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
04478                      p->dop.dialstr[0] = '\0';
04479                      return NULL;
04480                   } else {
04481                      ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
04482                      p->subs[index].f.frametype = AST_FRAME_NULL;
04483                      p->subs[index].f.subclass = 0;
04484                      p->dialing = 1;
04485                   }
04486                   p->dop.dialstr[0] = '\0';
04487                   ast_setstate(ast, AST_STATE_DIALING);
04488                } else
04489                   ast_setstate(ast, AST_STATE_UP);
04490                return &p->subs[index].f;
04491             case AST_STATE_DOWN:
04492                ast_setstate(ast, AST_STATE_RING);
04493                ast->rings = 1;
04494                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04495                p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
04496                ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
04497                return &p->subs[index].f;
04498             case AST_STATE_UP:
04499                /* Make sure it stops ringing */
04500                dahdi_set_hook(p->subs[index].dfd, DAHDI_OFFHOOK);
04501                /* Okay -- probably call waiting*/
04502                if (ast_bridged_channel(p->owner))
04503                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
04504                p->subs[index].needunhold = 1;
04505                break;
04506             case AST_STATE_RESERVED:
04507                /* Start up dialtone */
04508                if (has_voicemail(p))
04509                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
04510                else
04511                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
04512                break;
04513             default:
04514                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
04515             }
04516             break;
04517          case SIG_FXSLS:
04518          case SIG_FXSGS:
04519          case SIG_FXSKS:
04520             if (ast->_state == AST_STATE_RING) {
04521                p->ringt = p->ringt_base;
04522             }
04523 
04524             /* Fall through */
04525          case SIG_EM:
04526          case SIG_EM_E1:
04527          case SIG_EMWINK:
04528          case SIG_FEATD:
04529          case SIG_FEATDMF:
04530          case SIG_FEATDMF_TA:
04531          case SIG_E911:
04532          case SIG_FGC_CAMA:
04533          case SIG_FGC_CAMAMF:
04534          case SIG_FEATB:
04535          case SIG_SF:
04536          case SIG_SFWINK:
04537          case SIG_SF_FEATD:
04538          case SIG_SF_FEATDMF:
04539          case SIG_SF_FEATB:
04540             if (ast->_state == AST_STATE_PRERING)
04541                ast_setstate(ast, AST_STATE_RING);
04542             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
04543                if (option_debug)
04544                   ast_log(LOG_DEBUG, "Ring detected\n");
04545                p->subs[index].f.frametype = AST_FRAME_CONTROL;
04546                p->subs[index].f.subclass = AST_CONTROL_RING;
04547             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
04548                if (option_debug)
04549                   ast_log(LOG_DEBUG, "Line answered\n");
04550                if (p->confirmanswer) {
04551                   p->subs[index].f.frametype = AST_FRAME_NULL;
04552                   p->subs[index].f.subclass = 0;
04553                } else {
04554                   p->subs[index].f.frametype = AST_FRAME_CONTROL;
04555                   p->subs[index].f.subclass = AST_CONTROL_ANSWER;
04556                   ast_setstate(ast, AST_STATE_UP);
04557                }
04558             } else if (ast->_state != AST_STATE_RING)
04559                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
04560             break;
04561          default:
04562             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
04563          }
04564          break;
04565 #ifdef DAHDI_EVENT_RINGBEGIN
04566       case DAHDI_EVENT_RINGBEGIN:
04567          switch (p->sig) {
04568          case SIG_FXSLS:
04569          case SIG_FXSGS:
04570          case SIG_FXSKS:
04571             if (ast->_state == AST_STATE_RING) {
04572                p->ringt = p->ringt_base;
04573             }
04574             break;
04575          }
04576          break;
04577 #endif         
04578       case DAHDI_EVENT_RINGEROFF:
04579          if (p->inalarm) break;
04580          if ((p->radio || (p->oprmode < 0))) break;
04581          ast->rings++;
04582          if ((ast->rings > p->cidrings) && (p->cidspill)) {
04583             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
04584             free(p->cidspill);
04585             p->cidspill = NULL;
04586             p->callwaitcas = 0;
04587          }
04588          p->subs[index].f.frametype = AST_FRAME_CONTROL;
04589          p->subs[index].f.subclass = AST_CONTROL_RINGING;
04590          break;
04591       case DAHDI_EVENT_RINGERON:
04592          break;
04593       case DAHDI_EVENT_NOALARM:
04594          p->inalarm = 0;
04595 #ifdef HAVE_PRI
04596          /* Extremely unlikely but just in case */
04597          if (p->bearer)
04598             p->bearer->inalarm = 0;
04599 #endif            
04600          if (!p->unknown_alarm) {
04601             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
04602             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
04603                "Channel: %d\r\n", p->channel);
04604          } else {
04605             p->unknown_alarm = 0;
04606          }
04607          break;
04608       case DAHDI_EVENT_WINKFLASH:
04609          if (p->inalarm) break;
04610          if (p->radio) break;
04611          if (p->oprmode < 0) break;
04612          if (p->oprmode > 1)
04613          {
04614             struct dahdi_params par;
04615 
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 2820 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().

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

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

Definition at line 5473 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::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.

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

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

Definition at line 3499 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

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

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

Definition at line 5647 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_SLINEAR, 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().

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

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 8738 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().

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

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

Definition at line 8696 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().

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

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

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

Definition at line 8277 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().

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

static int dahdi_restart ( void   )  [static]

Definition at line 10426 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().

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

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

Definition at line 10519 of file chan_dahdi.c.

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

10520 {
10521    if (argc != 2) {
10522       return RESULT_SHOWUSAGE;
10523    }
10524 
10525    if (dahdi_restart() != 0)
10526       return RESULT_FAILURE;
10527    return RESULT_SUCCESS;
10528 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 3874 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), and dahdi_handle_event().

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

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

Definition at line 2730 of file chan_dahdi.c.

References send_keypad_facility_exec().

Referenced by load_module().

02731 {
02732    return send_keypad_facility_exec(chan, data);
02733 }

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

Definition at line 12240 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, pollfd::events, pollfd::fd, free, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, dahdi_pvt::mate, option_debug, poll(), POLLOUT, PUT_CLID, PUT_CLID_MARKMS, READ_SIZE, pollfd::revents, dahdi_pvt::subs, dahdi_pvt::tdd, TDD_BYTES_PER_CHAR, tdd_generate(), ast_channel::tech_pvt, and TRAILER_MS.

12241 {
12242 #define  END_SILENCE_LEN 400
12243 #define  HEADER_MS 50
12244 #define  TRAILER_MS 5
12245 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
12246 #define  ASCII_BYTES_PER_CHAR 80
12247 
12248    unsigned char *buf,*mybuf;
12249    struct dahdi_pvt *p = c->tech_pvt;
12250    struct pollfd fds[1];
12251    int size,res,fd,len,x;
12252    int bytes=0;
12253    /* Initial carrier (imaginary) */
12254    float cr = 1.0;
12255    float ci = 0.0;
12256    float scont = 0.0;
12257    int index;
12258 
12259    index = dahdi_get_index(c, p, 0);
12260    if (index < 0) {
12261       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
12262       return -1;
12263    }
12264    if (!text[0]) return(0); /* if nothing to send, dont */
12265    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
12266    if (p->mate) 
12267       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
12268    else
12269       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
12270    if (!buf)
12271       return -1;
12272    mybuf = buf;
12273    if (p->mate) {
12274       int codec = AST_LAW(p);
12275       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
12276          PUT_CLID_MARKMS;
12277       }
12278       /* Put actual message */
12279       for (x = 0; text[x]; x++) {
12280          PUT_CLID(text[x]);
12281       }
12282       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
12283          PUT_CLID_MARKMS;
12284       }
12285       len = bytes;
12286       buf = mybuf;
12287    } else {
12288       len = tdd_generate(p->tdd, buf, text);
12289       if (len < 1) {
12290          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
12291          free(mybuf);
12292          return -1;
12293       }
12294    }
12295    memset(buf + len, 0x7f, END_SILENCE_LEN);
12296    len += END_SILENCE_LEN;
12297    fd = p->subs[index].dfd;
12298    while (len) {
12299       if (ast_check_hangup(c)) {
12300          free(mybuf);
12301          return -1;
12302       }
12303       size = len;
12304       if (size > READ_SIZE)
12305          size = READ_SIZE;
12306       fds[0].fd = fd;
12307       fds[0].events = POLLOUT | POLLPRI;
12308       fds[0].revents = 0;
12309       res = poll(fds, 1, -1);
12310       if (!res) {
12311          ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
12312          continue;
12313       }
12314         /* if got exception */
12315       if (fds[0].revents & POLLPRI) {
12316          ast_free(mybuf);
12317          return -1;
12318       }
12319       if (!(fds[0].revents & POLLOUT)) {
12320          ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
12321          continue;
12322       }
12323       res = write(fd, buf, size);
12324       if (res != size) {
12325          if (res == -1) {
12326             free(mybuf);
12327             return -1;
12328          }
12329          if (option_debug)
12330             ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
12331          break;
12332       }
12333       len -= size;
12334       buf += size;
12335    }
12336    free(mybuf);
12337    return(0);
12338 }

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

Definition at line 1974 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().

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

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

Definition at line 8863 of file chan_dahdi.c.

08864 {
08865    int res;
08866    res = ioctl(dfd, DAHDI_SETLAW, &law);
08867    if (res)
08868       return res;
08869    return 0;
08870 }

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 3238 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, pollfd::events, pollfd::fd, 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, poll(), POLLOUT, POLLPRI, READ_SIZE, pollfd::revents, 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.

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

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

Definition at line 10591 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.

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

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

Definition at line 10530 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.

10531 {
10532 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10533 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s\n"
10534    struct dahdi_pvt *tmp = NULL;
10535    char tmps[20] = "";
10536    ast_mutex_t *lock;
10537    struct dahdi_pvt *start;
10538 #ifdef HAVE_PRI
10539    int trunkgroup;
10540    struct dahdi_pri *pri = NULL;
10541    int x;
10542 #endif
10543 
10544    lock = &iflock;
10545    start = iflist;
10546 
10547 #ifdef HAVE_PRI
10548    if (argc == 4) {
10549       if ((trunkgroup = atoi(argv[3])) < 1)
10550          return RESULT_SHOWUSAGE;
10551       for (x = 0; x < NUM_SPANS; x++) {
10552          if (pris[x].trunkgroup == trunkgroup) {
10553             pri = pris + x;
10554             break;
10555          }
10556       }
10557       if (pri) {
10558          start = pri->crvs;
10559          lock = &pri->lock;
10560       } else {
10561          ast_cli(fd, "No such trunk group %d\n", trunkgroup);
10562          return RESULT_FAILURE;
10563       }
10564    } else
10565 #endif
10566    if (argc != 3)
10567       return RESULT_SHOWUSAGE;
10568 
10569    ast_mutex_lock(lock);
10570 #ifdef HAVE_PRI
10571    ast_cli(fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret");
10572 #else
10573    ast_cli(fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret");
10574 #endif   
10575    
10576    tmp = start;
10577    while (tmp) {
10578       if (tmp->channel > 0) {
10579          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
10580       } else
10581          ast_copy_string(tmps, "pseudo", sizeof(tmps));
10582       ast_cli(fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret);
10583       tmp = tmp->next;
10584    }
10585    ast_mutex_unlock(lock);
10586    return RESULT_SUCCESS;
10587 #undef FORMAT
10588 #undef FORMAT2
10589 }

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

Definition at line 10771 of file chan_dahdi.c.

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

10771                                                              {
10772    #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
10773    #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
10774 
10775    int span;
10776    int res;
10777    char alarms[50];
10778 
10779    int ctl;
10780    struct dahdi_spaninfo s;
10781 
10782    if ((ctl = open(DAHDI_FILE_CTL, O_RDWR)) < 0) {
10783       ast_log(LOG_WARNING, "Unable to open " DAHDI_FILE_CTL ": %s\n", strerror(errno));
10784       ast_cli(fd, "No " DAHDI_NAME " interface found.\n");
10785       return RESULT_FAILURE;
10786    }
10787    ast_cli(fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4");
10788 
10789    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
10790       s.spanno = span;
10791       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
10792       if (res) {
10793          continue;
10794       }
10795       alarms[0] = '\0';
10796       if (s.alarms > 0) {
10797          if (s.alarms & DAHDI_ALARM_BLUE)
10798             strcat(alarms, "BLU/");
10799          if (s.alarms & DAHDI_ALARM_YELLOW)
10800             strcat(alarms, "YEL/");
10801          if (s.alarms & DAHDI_ALARM_RED)
10802             strcat(alarms, "RED/");
10803          if (s.alarms & DAHDI_ALARM_LOOPBACK)
10804             strcat(alarms, "LB/");
10805          if (s.alarms & DAHDI_ALARM_RECOVER)
10806             strcat(alarms, "REC/");
10807          if (s.alarms & DAHDI_ALARM_NOTOPEN)
10808             strcat(alarms, "NOP/");
10809          if (!strlen(alarms))
10810             strcat(alarms, "UUU/");
10811          if (strlen(alarms)) {
10812             /* Strip trailing / */
10813             alarms[strlen(alarms) - 1] = '\0';
10814          }
10815       } else {
10816          if (s.numchans)
10817             strcpy(alarms, "OK");
10818          else
10819             strcpy(alarms, "UNCONFIGURED");
10820       }
10821 
10822       ast_cli(fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count);
10823    }
10824    close(ctl);
10825 
10826    return RESULT_SUCCESS;
10827 #undef FORMAT
10828 #undef FORMAT2
10829 }

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 10397 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().

10398 {
10399    struct dahdi_pvt *p;
10400 retry:
10401    ast_mutex_lock(&iflock);
10402     for (p = iflist; p; p = p->next) {
10403       ast_mutex_lock(&p->lock);
10404         if (p->owner && !p->restartpending) {
10405          if (ast_channel_trylock(p->owner)) {
10406             if (option_debug > 2)
10407                ast_verbose("Avoiding deadlock\n");
10408             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
10409             ast_mutex_unlock(&p->lock);
10410             ast_mutex_unlock(&iflock);
10411             goto retry;
10412          }
10413          if (option_debug > 2)
10414             ast_verbose("Softhanging up on %s\n", p->owner->name);
10415          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
10416          p->restartpending = 1;
10417          num_restart_pending++;
10418          ast_channel_unlock(p->owner);
10419       }
10420       ast_mutex_unlock(&p->lock);
10421     }
10422    ast_mutex_unlock(&iflock);
10423 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 1806 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().

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

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

Definition at line 3443 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().

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

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 5863 of file chan_dahdi.c.

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

Referenced by ss_thread().

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

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

Definition at line 5390 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.

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

static void destroy_all_channels ( void   )  [static]

Definition at line 2646 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().

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

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

Definition at line 2596 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().

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

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

Definition at line 2578 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().

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

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 3522 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().

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

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

Definition at line 8641 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().

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

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

Definition at line 7269 of file chan_dahdi.c.

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

Referenced by restart_monitor().

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

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 3540 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().

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

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 1871 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

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

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

Definition at line 1837 of file chan_dahdi.c.

References AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

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

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

Definition at line 10929 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().

10930 {
10931    struct dahdi_pvt *p = iflist;
10932    while (p) {
10933       if (p->channel == channel) {
10934          break;
10935       }
10936       p = p->next;
10937    }
10938    return p;
10939 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

Definition at line 3982 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().

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

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

Definition at line 4097 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().

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

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

Definition at line 10744 of file chan_dahdi.c.

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

10745 {
10746    int i, j;
10747    for (i = 0; i < num_cadence; i++) {
10748       char output[1024];
10749       char tmp[16], tmp2[64];
10750       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
10751       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
10752 
10753       for (j = 0; j < 16; j++) {
10754          if (cadences[i].ringcadence[j] == 0)
10755             break;
10756          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
10757          if (cidrings[i] * 2 - 1 == j)
10758             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
10759          else
10760             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
10761          if (j != 0)
10762             strncat(output, ",", sizeof(output) - strlen(output) - 1);
10763          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
10764       }
10765       ast_cli(fd,"%s\n",output);
10766    }
10767    return 0;
10768 }

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

Definition at line 7061 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.

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

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

Definition at line 10140 of file chan_dahdi.c.

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

10141 {
10142    int span;
10143    int x;
10144    if (argc < 4) {
10145       return RESULT_SHOWUSAGE;
10146    }
10147    span = atoi(argv[3]);
10148    if ((span < 1) || (span > NUM_SPANS)) {
10149       ast_cli(fd, "Invalid span %s.  Should be a number %d to %d\n", argv[3], 1, NUM_SPANS);
10150       return RESULT_SUCCESS;
10151    }
10152    if (!pris[span-1].pri) {
10153       ast_cli(fd, "No PRI running on span %d\n", span);
10154       return RESULT_SUCCESS;
10155    }
10156    for (x = 0; x < NUM_DCHANS; x++) {
10157       if (pris[span-1].dchans[x])
10158          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
10159                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
10160                                                PRI_DEBUG_Q921_STATE);
10161    }
10162    ast_cli(fd, "Enabled debugging on span %d\n", span);
10163    return RESULT_SUCCESS;
10164 }

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

Definition at line 10168 of file chan_dahdi.c.

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

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

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

Definition at line 10191 of file chan_dahdi.c.

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

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

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

Definition at line 10093 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.

10094 {
10095    int myfd;
10096 
10097    if (!strncasecmp(argv[1], "set", 3)) {
10098       if (argc < 5) 
10099          return RESULT_SHOWUSAGE;
10100 
10101       if (ast_strlen_zero(argv[4]))
10102          return RESULT_SHOWUSAGE;
10103 
10104       myfd = open(argv[4], O_CREAT|O_WRONLY, 0600);
10105       if (myfd < 0) {
10106          ast_cli(fd, "Unable to open '%s' for writing\n", argv[4]);
10107          return RESULT_SUCCESS;
10108       }
10109 
10110       ast_mutex_lock(&pridebugfdlock);
10111 
10112       if (pridebugfd >= 0)
10113          close(pridebugfd);
10114 
10115       pridebugfd = myfd;
10116       ast_copy_string(pridebugfilename,argv[4],sizeof(pridebugfilename));
10117       
10118       ast_mutex_unlock(&pridebugfdlock);
10119 
10120       ast_cli(fd, "PRI debug output will be sent to '%s'\n", argv[4]);
10121    } else {
10122       /* Assume it is unset */
10123       ast_mutex_lock(&pridebugfdlock);
10124       close(pridebugfd);
10125       pridebugfd = -1;
10126       ast_cli(fd, "PRI debug output to file disabled\n");
10127       ast_mutex_unlock(&pridebugfdlock);
10128    }
10129 
10130    return RESULT_SUCCESS;
10131 }

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

Definition at line 10297 of file chan_dahdi.c.

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

10298 {
10299    int x;
10300    int span;
10301    int count=0;
10302    int debug=0;
10303 
10304    for (span = 0; span < NUM_SPANS; span++) {
10305            if (pris[span].pri) {
10306          for (x = 0; x < NUM_DCHANS; x++) {
10307             debug = 0;
10308                if (pris[span].dchans[x]) {
10309                   debug = pri_get_debug(pris[span].dchans[x]);
10310                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" );
10311                count++;
10312             }
10313          }
10314       }
10315 
10316    }
10317    ast_mutex_lock(&pridebugfdlock);
10318    if (pridebugfd >= 0) 
10319       ast_cli(fd, "Logging PRI debug to file %s\n", pridebugfilename);
10320    ast_mutex_unlock(&pridebugfdlock);
10321        
10322    if (!count) 
10323       ast_cli(fd, "No debug set or no PRI running\n");
10324    return RESULT_SUCCESS;
10325 }

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

Definition at line 10258 of file chan_dahdi.c.

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

10259 {
10260    int span;
10261    int x;
10262    char status[256];
10263    if (argc < 4)
10264       return RESULT_SHOWUSAGE;
10265    span = atoi(argv[3]);
10266    if ((span < 1) || (span > NUM_SPANS)) {
10267       ast_cli(fd, "Invalid span '%s'.  Should be a number from %d to %d\n", argv[3], 1, NUM_SPANS);
10268       return RESULT_SUCCESS;
10269    }
10270    if (!pris[span-1].pri) {
10271       ast_cli(fd, "No PRI running on span %d\n", span);
10272       return RESULT_SUCCESS;
10273    }
10274    for (x = 0; x < NUM_DCHANS; x++) {
10275       if (pris[span-1].dchannels[x]) {
10276 #ifdef PRI_DUMP_INFO_STR
10277          char *info_str = NULL;
10278 #endif
10279          ast_cli(fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
10280          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
10281          ast_cli(fd, "Status: %s\n", status);
10282 #ifdef PRI_DUMP_INFO_STR
10283          info_str = pri_dump_info_str(pris[span-1].pri);
10284          if (info_str) {
10285             ast_cli(fd, "%s", info_str);
10286             free(info_str);
10287          }
10288 #else
10289          pri_dump_info(pris[span-1].pri);
10290 #endif
10291          ast_cli(fd, "\n");
10292       }
10293    }
10294    return RESULT_SUCCESS;
10295 }

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

Definition at line 10237 of file chan_dahdi.c.

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

10238 {
10239    int span;
10240    int x;
10241    char status[256];
10242    if (argc != 3)
10243       return RESULT_SHOWUSAGE;
10244 
10245    for (span = 0; span < NUM_SPANS; span++) {
10246       if (pris[span].pri) {
10247          for (x = 0; x < NUM_DCHANS; x++) {
10248             if (pris[span].dchannels[x]) {
10249                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
10250                ast_cli(fd, "PRI span %d/%d: %s\n", span + 1, x, status);
10251             }
10252          }
10253       }
10254    }
10255    return RESULT_SUCCESS;
10256 }

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

Definition at line 10134 of file chan_dahdi.c.

References ast_cli(), and RESULT_SUCCESS.

10134                                                              {
10135    ast_cli(fd, "libpri version: %s\n", pri_get_version());
10136    return RESULT_SUCCESS;
10137 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 2069 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().

02070 {
02071 
02072    return ast_app_has_voicemail(p->mailbox, NULL);
02073 }

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 1658 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().

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

static int load_module ( void   )  [static]

Definition at line 12183 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.

12184 {
12185    int res;
12186 
12187 #ifdef HAVE_PRI
12188    int y,i;
12189    memset(pris, 0, sizeof(pris));
12190    for (y = 0; y < NUM_SPANS; y++) {
12191       ast_mutex_init(&pris[y].lock);
12192       pris[y].offset = -1;
12193       pris[y].master = AST_PTHREADT_NULL;
12194       for (i = 0; i < NUM_DCHANS; i++)
12195          pris[y].fds[i] = -1;
12196    }
12197    pri_set_error(dahdi_pri_error);
12198    pri_set_message(dahdi_pri_message);
12199    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12200       ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
12201          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
12202    }
12203    ast_register_application(zap_send_keypad_facility_app, zap_send_keypad_facility_exec,
12204       zap_send_keypad_facility_synopsis, zap_send_keypad_facility_descrip);
12205 #endif
12206    if ((res = setup_dahdi(0))) {
12207       return AST_MODULE_LOAD_DECLINE;
12208    }
12209    if (*dahdi_chan_mode == CHAN_DAHDI_PLUS_ZAP_MODE) {
12210       chan_tech = &dahdi_tech;
12211    } else {
12212       chan_tech = &zap_tech;
12213    }
12214    if (ast_channel_register(chan_tech)) {
12215       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", chan_tech->type);
12216       __unload_module();
12217       return -1;
12218    }
12219 #ifdef HAVE_PRI
12220    ast_string_field_init(&inuse, 16);
12221    ast_string_field_set(&inuse, name, "GR-303InUse");
12222    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
12223 #endif   
12224    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
12225    
12226    memset(round_robin, 0, sizeof(round_robin));
12227    local_astman_register("Transfer", 0, action_transfer, "Transfer Channel");
12228    local_astman_register("Hangup", 0, action_transferhangup, "Hangup Channel");
12229    local_astman_register("DialOffHook", 0, action_dialoffhook, "Dial over channel while offhook");
12230    local_astman_register("DNDon", 0, action_dndon, "Toggle channel Do Not Disturb status ON");
12231    local_astman_register("DNDoff", 0, action_dndoff, "Toggle channel Do Not Disturb status OFF");
12232    local_astman_register("ShowChannels", 0, action_showchannels, "Show status channels");
12233    local_astman_register("Restart", 0, action_restart, "Fully Restart channels (terminates calls)");
12234 
12235    ast_cond_init(&ss_thread_complete, NULL);
12236 
12237    return res;
12238 }

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

Definition at line 7615 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().

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

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

Definition at line 5367 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().

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

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

Definition at line 5844 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

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

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

Definition at line 2781 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().

02782 {
02783    int x = -1;
02784 
02785    for (x = 0; x < NUM_DCHANS; x++) {
02786       if ((pri->dchans[x] == pri->pri))
02787          break;
02788    }
02789 
02790    return pri->fds[x];
02791 }

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

Definition at line 2751 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().

02752 {
02753    bearer->owner = &inuse;
02754    bearer->realcall = crv;
02755    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
02756    if (crv->subs[SUB_REAL].owner)
02757       crv->subs[SUB_REAL].owner->fds[0] = crv->subs[SUB_REAL].dfd;
02758    crv->bearer = bearer;
02759    crv->call = bearer->call;
02760    crv->pri = pri;
02761    return 0;
02762 }

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

Definition at line 8780 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().

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

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

Definition at line 7602 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

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

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

Definition at line 7539 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().

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

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

Definition at line 8872 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(), pollfd::events, pollfd::fd, 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, NUM_DCHANS, 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, pollfd::revents, dahdi_pri::switchtype, and t.

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

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

Definition at line 8519 of file chan_dahdi.c.

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

08520 {
08521    struct dahdi_pvt *p;
08522    p = pri->crvs;
08523    while (p) {
08524       if (p->channel == crv)
08525          return p;
08526       p = p->next;
08527    }
08528    return NULL;
08529 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 2793 of file chan_dahdi.c.

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

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

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

Definition at line 8251 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().

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

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

Definition at line 8532 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.

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

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

Definition at line 8559 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.

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

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 8799 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.

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

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 2741 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

02742 {
02743    int x;
02744    for (x = 0; x < NUM_DCHANS; x++) {
02745       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
02746          return 1;
02747    }
02748    return 0;
02749 }

static char* pri_order ( int  level  )  [static]

Definition at line 2764 of file chan_dahdi.c.

Referenced by handle_pri_show_span().

02765 {
02766    switch (level) {
02767    case 0:
02768       return "Primary";
02769    case 1:
02770       return "Secondary";
02771    case 2:
02772       return "Tertiary";
02773    case 3:
02774       return "Quaternary";
02775    default:
02776       return "<Unknown>";
02777    }     
02778 }

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 7493 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().

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

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

Definition at line 11330 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().

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

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 8823 of file chan_dahdi.c.

Referenced by __oh323_new().

08824 {
08825    switch (redirectingreason) {
08826    case 0:
08827       return "UNKNOWN";
08828    case 1:
08829       return "BUSY";
08830    case 2:
08831       return "NO_REPLY";
08832    case 0xF:
08833       return "UNCONDITIONAL";
08834    default:
08835       return "NOREDIRECT";
08836    }
08837 }

static int reload ( void   )  [static]

Definition at line 12341 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

12342 {
12343    int res = 0;
12344 
12345    res = setup_dahdi(1);
12346    if (res) {
12347       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
12348       return -1;
12349    }
12350    return 0;
12351 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1702 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().

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

static int restart_monitor ( void   )  [static]

Definition at line 7461 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().

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

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2035 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().

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

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 1961 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().

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

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2007 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().

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

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 2075 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().

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

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 2053 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().

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

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

Definition at line 2690 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().

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

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

Definition at line 1942 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

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

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

Definition at line 1924 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

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

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

Definition at line 1905 of file chan_dahdi.c.

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

Referenced by dahdi_setoption(), and set_actual_gain().

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

static int setup_dahdi ( int  reload  )  [static]

Definition at line 12036 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().

12037 {
12038    struct ast_config *cfg;
12039    struct ast_variable *v;
12040    struct dahdi_chan_conf conf = dahdi_chan_conf_default();
12041    int res;
12042 
12043 #ifdef HAVE_PRI
12044    char *c;
12045    int spanno;
12046    int i, x;
12047    int logicalspan;
12048    int trunkgroup;
12049    int dchannels[NUM_DCHANS];
12050 #endif
12051 
12052 #ifdef HAVE_ZAPTEL
12053    int load_from_zapata_conf = 1;
12054 #else
12055    int load_from_zapata_conf = (dahdi_chan_mode == CHAN_ZAP_MODE);
12056 #endif
12057 
12058    if (load_from_zapata_conf) {
12059       if (!(cfg = ast_config_load("zapata.conf"))) {
12060          ast_log(LOG_ERROR, "Unable to load zapata.conf\n");
12061          return 0;
12062       }
12063    } else {
12064       if (!(cfg = ast_config_load("chan_dahdi.conf"))) {
12065          ast_log(LOG_ERROR, "Unable to load chan_dahdi.conf\n");
12066          return 0;
12067       }
12068    }
12069 
12070    /* It's a little silly to lock it, but we mind as well just to be sure */
12071    ast_mutex_lock(&iflock);
12072 #ifdef HAVE_PRI
12073    if (reload != 1) {
12074       /* Process trunkgroups first */
12075       v = ast_variable_browse(cfg, "trunkgroups");
12076       while (v) {
12077          if (!strcasecmp(v->name, "trunkgroup")) {
12078             trunkgroup = atoi(v->value);
12079             if (trunkgroup > 0) {
12080                if ((c = strchr(v->value, ','))) {
12081                   i = 0;
12082                   memset(dchannels, 0, sizeof(dchannels));
12083                   while (c && (i < NUM_DCHANS)) {
12084                      dchannels[i] = atoi(c + 1);
12085                      if (dchannels[i] < 0) {
12086                         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);
12087                      } else
12088                         i++;
12089                      c = strchr(c + 1, ',');
12090                   }
12091                   if (i) {
12092                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
12093                         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);
12094                      } else if (option_verbose > 1)
12095                         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");
12096                   } else
12097                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12098                } else
12099                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
12100             } else
12101                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
12102          } else if (!strcasecmp(v->name, "spanmap")) {
12103             spanno = atoi(v->value);
12104             if (spanno > 0) {
12105                if ((c = strchr(v->value, ','))) {
12106                   trunkgroup = atoi(c + 1);
12107                   if (trunkgroup > 0) {
12108                      if ((c = strchr(c + 1, ','))) 
12109                         logicalspan = atoi(c + 1);
12110                      else
12111                         logicalspan = 0;
12112                      if (logicalspan >= 0) {
12113                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
12114                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12115                         } else if (option_verbose > 1) 
12116                            ast_verbose(VERBOSE_PREFIX_2 "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
12117                      } else
12118                         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);
12119                   } else
12120                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
12121                } else
12122                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
12123             } else
12124                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
12125          } else {
12126             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
12127          }
12128          v = v->next;
12129       }
12130    }
12131 #endif
12132    
12133    /* Copy the default jb config over global_jbconf */
12134    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
12135 
12136    v = ast_variable_browse(cfg, "channels");
12137    res = process_dahdi(&conf, "", v, reload, 0);
12138    ast_mutex_unlock(&iflock);
12139    ast_config_destroy(cfg);
12140    if (res)
12141       return res;
12142    cfg = ast_config_load("users.conf");
12143    if (cfg) {
12144       char *cat;
12145       process_dahdi(&conf, "", ast_variable_browse(cfg, "general"), 1, 1);
12146       for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
12147          if (!strcasecmp(cat, "general"))
12148             continue;
12149          if (!ast_strlen_zero(ast_variable_retrieve(cfg, cat, "dahdichan")) || !ast_strlen_zero(ast_variable_retrieve(cfg, cat, "zapchan"))) {
12150             struct dahdi_chan_conf sect_conf;
12151             memcpy(&sect_conf, &conf, sizeof(sect_conf));
12152 
12153             process_dahdi(&sect_conf, cat, ast_variable_browse(cfg, cat), reload, 0);
12154          }
12155       }
12156       ast_config_destroy(cfg);
12157    }
12158 #ifdef HAVE_PRI
12159    if (reload != 1) {
12160       for (x = 0; x < NUM_SPANS; x++) {
12161          if (pris[x].pvts[0]) {
12162             if (start_pri(pris + x)) {
12163                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
12164                return -1;
12165             } else if (option_verbose > 1)
12166                ast_verbose(VERBOSE_PREFIX_2 "Starting D-Channel on span %d\n", x + 1);
12167          }
12168       }
12169    }
12170 #endif
12171    /* And start the monitor for the first time */
12172    restart_monitor();
12173    return 0;
12174 }

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

Definition at line 5881 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().

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

static int start_pri ( struct dahdi_pri pri  )  [static]

Definition at line 9977 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().

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

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 11227 of file chan_dahdi.c.

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

11228 {
11229 #ifdef HAVE_PRI      
11230    int y;
11231    for (y = 0; y < NUM_SPANS; y++)
11232       ast_mutex_destroy(&pris[y].lock);
11233 #endif
11234    return __unload_module();
11235 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1715 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().

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

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 11073 of file chan_dahdi.c.

References __action_dialoffhook(), and s.

11074 {
11075    return __action_dialoffhook(s, m, 1);
11076 }

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

Definition at line 10973 of file chan_dahdi.c.

References __action_dnd(), and s.

10974 {
10975    return __action_dnd(s, m, 1, 0);
10976 }

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

Definition at line 10963 of file chan_dahdi.c.

References __action_dnd(), and s.

10964 {
10965    return __action_dnd(s, m, 1, 1);
10966 }

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

Definition at line 11152 of file chan_dahdi.c.

References __action_restart(), and s.

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

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

Definition at line 11128 of file chan_dahdi.c.

References __action_showchannels(), and s.

11129 {
11130    return __action_showchannels(s, m, 1);
11131 }

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

Definition at line 11002 of file chan_dahdi.c.

References __action_transfer(), and s.

11003 {
11004    return __action_transfer(s, m, 1);
11005 }

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

Definition at line 11030 of file chan_dahdi.c.

References __action_transferhangup(), and s.

11031 {
11032    return __action_transferhangup(s, m, 1);
11033 }

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

Definition at line 2735 of file chan_dahdi.c.

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

Referenced by load_module().

02736 {
02737    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);  
02738    return send_keypad_facility_exec(chan, data);
02739 }


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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 12367 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 12367 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 10869 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 10874 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 10854 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 10864 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 10859 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 10879 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 10884 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 10347 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

char dahdi_restart_usage[] [static]

Definition at line 10847 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 2677 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 2683 of file chan_dahdi.c.

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

Definition at line 2680 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 10740 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 10839 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 10843 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 = ((ast_mutex_t) 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_extension_state2(), 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 = ((ast_mutex_t) 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 10327 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 10331 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 10335 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 10339 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 10343 of file chan_dahdi.c.

int pridebugfd = -1 [static]

Definition at line 213 of file chan_dahdi.c.

ast_mutex_t pridebugfdlock = ((ast_mutex_t) 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 = ((ast_mutex_t) 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 10835 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 10831 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 = ((ast_mutex_t) 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 2678 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 2686 of file chan_dahdi.c.

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

Definition at line 2681 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 Fri Apr 24 16:26:16 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7