Fri Jun 19 12:10:09 2009

Asterisk developer's documentation


chan_dahdi.c File Reference

DAHDI for Pseudo TDM. More...

#include "asterisk.h"
#include <sys/signal.h>
#include <sys/ioctl.h>
#include <math.h>
#include <ctype.h>
#include <dahdi/user.h>
#include <dahdi/tonezone.h>
#include <libpri.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.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/event.h"
#include "asterisk/devicestate.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  mwi_thread_data
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 CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
#define CALLPROGRESS_FAX_INCOMING   4
#define CALLPROGRESS_FAX_OUTGOING   2
#define CALLPROGRESS_PROGRESS   1
#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_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
#define DAHDI_OVERLAPDIAL_INCOMING   2
#define DAHDI_OVERLAPDIAL_NONE   0
#define DAHDI_OVERLAPDIAL_OUTGOING   1
#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 %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\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 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 PROC_DAHDI_OPT_NOCHAN   (1 << 0)
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
#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_BRI   (0x2000000 | DAHDI_SIG_CLEAR)
#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)
#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 SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)
#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

Enumerations

enum  mwisend_states {
  MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_PAUSE, MWI_SEND_SPILL,
  MWI_SEND_CLEANUP, MWI_SEND_DONE
}

Functions

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 int action_dahdidialoffhook (struct mansession *s, const struct message *m)
static int action_dahdidndoff (struct mansession *s, const struct message *m)
static int action_dahdidndon (struct mansession *s, const struct message *m)
static int action_dahdirestart (struct mansession *s, const struct message *m)
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
static int action_transfer (struct mansession *s, const struct message *m)
static int action_transferhangup (struct mansession *s, const struct message *m)
static char * alarm2str (int alm)
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 int calc_energy (const unsigned char *buf, int len, int law)
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 idx, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
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 char * dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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_dnd (struct dahdi_pvt *dahdichan, int on)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
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, const 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 idx, 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, void *data)
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 char * dahdi_restart_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 char * dahdi_set_dnd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_set_hook (int fd, int hs)
static char * dahdi_set_hwgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_set_swgain (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 char * dahdi_show_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_channels (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * dahdi_show_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 idx)
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 alms)
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_init_event (struct dahdi_pvt *i, int event)
static char * handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_no_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_really_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_unset_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
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 void mwi_event_cb (const struct ast_event *event, void *userdata)
static void * mwi_send_thread (void *data)
static void * mwi_thread (void *data)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static void notify_message (char *mailbox_full, int thereornot)
 Send MWI state change.
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 options)
static void process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line)
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 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 int sigtype_to_signalling (int sigtype)
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)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
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 const char config [] = "chan_dahdi.conf"
static struct ast_cli_entry dahdi_cli []
static struct ast_cli_entry dahdi_pri_cli []
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 struct ast_channel_tech dahdi_tech
static struct ast_jb_conf default_jbconf
static char defaultcic [64] = ""
static char defaultozz [64] = ""
static int distinctiveringaftercid = 0
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_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the interface list (of dahdi_pvt's).
static struct ast_channel inuse
static const char * lbostr []
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_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static ast_cond_t mwi_thread_complete
static int mwi_thread_count = 0
static ast_mutex_t mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int mwisend_rpas = 0
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static char parkinglot [AST_MAX_EXTENSION] = ""
static int pridebugfd = -1
static ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
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_RECURSIVE_MUTEX_INITIALIZER_NP )
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
dahdi_pvtround_robin [32]
static ast_cond_t ss_thread_complete
static int ss_thread_count = 0
static ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char * subnames []
static const char tdesc []
static int usedistinctiveringdetection = 0
static int user_has_defined_cadences = 0


Detailed Description

DAHDI for Pseudo TDM.

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

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

#define CALLPROGRESS_FAX   (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)

Definition at line 224 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmfup().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 223 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 222 of file chan_dahdi.c.

Referenced by dahdi_new().

#define CALLPROGRESS_PROGRESS   1

Definition at line 221 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

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

10,000 ms

Definition at line 330 of file chan_dahdi.c.

Referenced by dahdi_callwait().

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

300 ms

Definition at line 329 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 1314 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 1315 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

#define CHAN_PSEUDO   -2

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

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

500 ms

Definition at line 331 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 511 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 512 of file chan_dahdi.c.

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

Definition at line 218 of file chan_dahdi.c.

Referenced by start_pri().

#define DAHDI_OVERLAPDIAL_INCOMING   2

Definition at line 217 of file chan_dahdi.c.

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

#define DAHDI_OVERLAPDIAL_NONE   0

Definition at line 215 of file chan_dahdi.c.

#define DAHDI_OVERLAPDIAL_OUTGOING   1

Definition at line 216 of file chan_dahdi.c.

Referenced by dahdi_read(), and start_pri().

#define DCHAN_AVAILABLE   (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)

Definition at line 212 of file chan_dahdi.c.

Referenced by pri_find_dchan(), and pri_is_up().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 209 of file chan_dahdi.c.

Referenced by build_status(), and start_pri().

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 208 of file chan_dahdi.c.

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

#define DCHAN_UP   (1 << 2)

Definition at line 210 of file chan_dahdi.c.

#define DEFAULT_CIDRINGS   1

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

Definition at line 149 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

#define DEFAULT_PRI_DEBUG   0

Definition at line 452 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

Definition at line 333 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"

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

#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"

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

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

Definition at line 1239 of file chan_dahdi.c.

#define HANGUP   1

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

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

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 326 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 204 of file chan_dahdi.c.

Referenced by mkintf().

#define MAX_SLAVES   4

Definition at line 514 of file chan_dahdi.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

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

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 1286 of file chan_dahdi.c.

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 203 of file chan_dahdi.c.

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

#define NUM_SPANS   32

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

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

#define POLARITY_REV   1

Definition at line 471 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and handle_init_event().

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

Definition at line 391 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 393 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 392 of file chan_dahdi.c.

Referenced by pri_find_principle().

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 14230 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

process_dahdi() - No warnings on non-existing cofiguration keywords

Definition at line 14232 of file chan_dahdi.c.

Referenced by setup_dahdi().

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

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

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

#define sig2str   dahdi_sig2str

Definition at line 1840 of file chan_dahdi.c.

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

#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)

Definition at line 186 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_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), ss_thread(), and start_pri().

#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)

Definition at line 187 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_queue_frame(), dahdi_read(), dahdi_sig2str(), handle_init_event(), mkintf(), ss_thread(), and start_pri().

#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)

Definition at line 175 of file chan_dahdi.c.

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

#define SIG_EM   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(), and ss_thread().

#define SIG_EM_E1   DAHDI_SIG_EM_E1

Definition at line 194 of file chan_dahdi.c.

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

#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)

Definition at line 171 of file chan_dahdi.c.

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

#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)

Definition at line 174 of file chan_dahdi.c.

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

#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)

Definition at line 172 of file chan_dahdi.c.

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

#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)

Definition at line 173 of file chan_dahdi.c.

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

#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)

Definition at line 176 of file chan_dahdi.c.

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

#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)

Definition at line 177 of file chan_dahdi.c.

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

#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)

Definition at line 178 of file chan_dahdi.c.

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

#define SIG_FXOGS   DAHDI_SIG_FXOGS

Definition at line 183 of file chan_dahdi.c.

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

#define SIG_FXOKS   DAHDI_SIG_FXOKS

Definition at line 184 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(), and ss_thread().

#define SIG_FXOLS   DAHDI_SIG_FXOLS

Definition at line 182 of file chan_dahdi.c.

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

#define SIG_FXSGS   DAHDI_SIG_FXSGS

Definition at line 180 of file chan_dahdi.c.

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

#define SIG_FXSKS   DAHDI_SIG_FXSKS

Definition at line 181 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(), and ss_thread().

#define SIG_FXSLS   DAHDI_SIG_FXSLS

Definition at line 179 of file chan_dahdi.c.

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

#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)

Definition at line 195 of file chan_dahdi.c.

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

#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)

Definition at line 196 of file chan_dahdi.c.

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

#define SIG_PRI   DAHDI_SIG_CLEAR

Definition at line 185 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_queue_frame(), dahdi_read(), dahdi_sig2str(), dahdi_write(), handle_init_event(), mkintf(), and ss_thread().

#define SIG_SF   DAHDI_SIG_SF

Definition at line 189 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_FEATB   (0x0800000 | DAHDI_SIG_SF)

Definition at line 193 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_FEATD   (0x0200000 | DAHDI_SIG_SF)

Definition at line 191 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 192 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 190 of file chan_dahdi.c.

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

#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)

Definition at line 188 of file chan_dahdi.c.

Referenced by dahdi_answer(), dahdi_call(), dahdi_confmute(), dahdi_enable_ec(), dahdi_handle_event(), dahdi_hangup(), dahdi_indicate(), dahdi_new(), dahdi_queue_frame(), dahdi_sig2str(), handle_init_event(), and mkintf().

#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 466 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(), and ss_thread().

#define SUB_REAL   0

Active call

Definition at line 465 of file chan_dahdi.c.

Referenced by __dahdi_exception(), attempt_transfer(), available(), build_device(), bump_gains(), chandup(), check_for_conference(), close_call(), close_client(), 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(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), mwi_send_thread(), mwi_thread(), pri_assign_bearer(), pri_fixup_principle(), process_request(), rcv_mac_addr(), reset_conf(), restore_conference(), restore_gains(), save_conference(), send_callerid(), ss_thread(), TransferCallStep1(), unistim_do_senddigit(), unistim_hangup(), and unistim_senddigit_end().

#define SUB_THREEWAY   2

Three-way call

Definition at line 467 of file chan_dahdi.c.

Referenced by attempt_transfer(), available(), close_call(), dahdi_answer(), dahdi_bridge(), dahdi_get_index(), dahdi_handle_event(), dahdi_hangup(), dahdi_show_channel(), HandleCallOutgoing(), ss_thread(), TransferCallStep1(), unistim_answer(), and unistim_hangup().

#define tdesc   "DAHDI Telephony w/PRI"

Definition at line 15467 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 13316 of file chan_dahdi.c.

Referenced by action_transfer(), and dahdi_fake_event().


Enumeration Type Documentation

enum mwisend_states

Enumerator:
MWI_SEND_SA 
MWI_SEND_SA_WAIT 
MWI_SEND_PAUSE 
MWI_SEND_SPILL 
MWI_SEND_CLEANUP 
MWI_SEND_DONE 

Definition at line 7892 of file chan_dahdi.c.

07892                     {
07893    MWI_SEND_SA,
07894  MWI_SEND_SA_WAIT,
07895  MWI_SEND_PAUSE,
07896  MWI_SEND_SPILL,
07897  MWI_SEND_CLEANUP,
07898  MWI_SEND_DONE
07899 };


Function Documentation

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

Definition at line 5527 of file chan_dahdi.c.

References ast_bridged_channel(), AST_CONTROL_UNHOLD, ast_debug, AST_FRAME_NULL, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tv(), ast_tvnow(), ast_verb, 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, ast_frame::mallocd, ast_channel::name, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

Referenced by dahdi_exception(), and dahdi_read().

05528 {
05529    struct dahdi_pvt *p = ast->tech_pvt;
05530    int res;
05531    int usedindex=-1;
05532    int idx;
05533    struct ast_frame *f;
05534 
05535 
05536    idx = dahdi_get_index(ast, p, 1);
05537    
05538    p->subs[idx].f.frametype = AST_FRAME_NULL;
05539    p->subs[idx].f.datalen = 0;
05540    p->subs[idx].f.samples = 0;
05541    p->subs[idx].f.mallocd = 0;
05542    p->subs[idx].f.offset = 0;
05543    p->subs[idx].f.subclass = 0;
05544    p->subs[idx].f.delivery = ast_tv(0,0);
05545    p->subs[idx].f.src = "dahdi_exception";
05546    p->subs[idx].f.data.ptr = NULL;
05547    
05548    
05549    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
05550       /* If nobody owns us, absorb the event appropriately, otherwise
05551          we loop indefinitely.  This occurs when, during call waiting, the
05552          other end hangs up our channel so that it no longer exists, but we
05553          have neither FLASH'd nor ONHOOK'd to signify our desire to
05554          change to the other channel. */
05555       if (p->fake_event) {
05556          res = p->fake_event;
05557          p->fake_event = 0;
05558       } else
05559          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
05560       /* Switch to real if there is one and this isn't something really silly... */
05561       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
05562          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
05563          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
05564          p->owner = p->subs[SUB_REAL].owner;
05565          if (p->owner && ast_bridged_channel(p->owner))
05566             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05567          p->subs[SUB_REAL].needunhold = 1;
05568       }
05569       switch (res) {
05570       case DAHDI_EVENT_ONHOOK:
05571          dahdi_disable_ec(p);
05572          if (p->owner) {
05573             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
05574             dahdi_ring_phone(p);
05575             p->callwaitingrepeat = 0;
05576             p->cidcwexpire = 0;
05577          } else
05578             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05579          update_conf(p);
05580          break;
05581       case DAHDI_EVENT_RINGOFFHOOK:
05582          dahdi_enable_ec(p);
05583          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
05584          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
05585             p->subs[SUB_REAL].needanswer = 1;
05586             p->dialing = 0;
05587          }
05588          break;
05589       case DAHDI_EVENT_HOOKCOMPLETE:
05590       case DAHDI_EVENT_RINGERON:
05591       case DAHDI_EVENT_RINGEROFF:
05592          /* Do nothing */
05593          break;
05594       case DAHDI_EVENT_WINKFLASH:
05595          p->flashtime = ast_tvnow();
05596          if (p->owner) {
05597             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
05598             if (p->owner->_state != AST_STATE_UP) {
05599                /* Answer if necessary */
05600                usedindex = dahdi_get_index(p->owner, p, 0);
05601                if (usedindex > -1) {
05602                   p->subs[usedindex].needanswer = 1;
05603                }
05604                ast_setstate(p->owner, AST_STATE_UP);
05605             }
05606             p->callwaitingrepeat = 0;
05607             p->cidcwexpire = 0;
05608             if (ast_bridged_channel(p->owner))
05609                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05610             p->subs[SUB_REAL].needunhold = 1;
05611          } else
05612             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
05613          update_conf(p);
05614          break;
05615       default:
05616          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
05617       }
05618       f = &p->subs[idx].f;
05619       return f;
05620    }
05621    if (!(p->radio || (p->oprmode < 0))) 
05622       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
05623    /* If it's not us, return NULL immediately */
05624    if (ast != p->owner) {
05625       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
05626       f = &p->subs[idx].f;
05627       return f;
05628    }
05629    f = dahdi_handle_event(ast);
05630    return f;
05631 }

static void __reg_module ( void   )  [static]

Definition at line 15481 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 13993 of file chan_dahdi.c.

References ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_cond_destroy(), ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), dahdi_cli, dahdi_close_pri_fd(), dahdi_pri_cli, dahdi_tech, destroy_all_channels(), iflist, iflock, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, and pris.

Referenced by load_module(), and unload_module().

13994 {
13995    struct dahdi_pvt *p;
13996 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13997    int i, j;
13998 #endif
13999 
14000 #ifdef HAVE_PRI
14001    for (i = 0; i < NUM_SPANS; i++) {
14002       if (pris[i].master != AST_PTHREADT_NULL) 
14003          pthread_cancel(pris[i].master);
14004    }
14005    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14006    ast_unregister_application(dahdi_send_keypad_facility_app);
14007 #endif
14008 #if defined(HAVE_SS7)
14009    for (i = 0; i < NUM_SPANS; i++) {
14010       if (linksets[i].master != AST_PTHREADT_NULL)
14011          pthread_cancel(linksets[i].master);
14012       }
14013    ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14014 #endif
14015 
14016    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14017    ast_manager_unregister( "DAHDIDialOffhook" );
14018    ast_manager_unregister( "DAHDIHangup" );
14019    ast_manager_unregister( "DAHDITransfer" );
14020    ast_manager_unregister( "DAHDIDNDoff" );
14021    ast_manager_unregister( "DAHDIDNDon" );
14022    ast_manager_unregister("DAHDIShowChannels");
14023    ast_manager_unregister("DAHDIRestart");
14024    ast_channel_unregister(&dahdi_tech);
14025    ast_mutex_lock(&iflock);
14026    /* Hangup all interfaces if they have an owner */
14027    p = iflist;
14028    while (p) {
14029       if (p->owner)
14030          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14031       p = p->next;
14032    }
14033    ast_mutex_unlock(&iflock);
14034    ast_mutex_lock(&monlock);
14035    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14036       pthread_cancel(monitor_thread);
14037       pthread_kill(monitor_thread, SIGURG);
14038       pthread_join(monitor_thread, NULL);
14039    }
14040    monitor_thread = AST_PTHREADT_STOP;
14041    ast_mutex_unlock(&monlock);
14042 
14043    destroy_all_channels();
14044 
14045 #if defined(HAVE_PRI)
14046    for (i = 0; i < NUM_SPANS; i++) {
14047       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14048          pthread_join(pris[i].master, NULL);
14049       for (j = 0; j < NUM_DCHANS; j++) {
14050          dahdi_close_pri_fd(&(pris[i]), j);
14051       }
14052    }
14053 #endif
14054 
14055 #if defined(HAVE_SS7)
14056    for (i = 0; i < NUM_SPANS; i++) {
14057       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14058          pthread_join(linksets[i].master, NULL);
14059       for (j = 0; j < NUM_DCHANS; j++) {
14060          dahdi_close_ss7_fd(&(linksets[i]), j);
14061       }
14062    }
14063 #endif
14064 
14065    ast_cond_destroy(&mwi_thread_complete);
14066    ast_cond_destroy(&ss_thread_complete);
14067    return 0;
14068 }

static void __unreg_module ( void   )  [static]

Definition at line 15481 of file chan_dahdi.c.

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

Definition at line 13423 of file chan_dahdi.c.

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

Referenced by load_module().

13424 {
13425    struct dahdi_pvt *p = NULL;
13426    const char *channel = astman_get_header(m, "DAHDIChannel");
13427    const char *number = astman_get_header(m, "Number");
13428    int i;
13429 
13430    if (ast_strlen_zero(channel)) {
13431       astman_send_error(s, m, "No channel specified");
13432       return 0;
13433    }
13434    if (ast_strlen_zero(number)) {
13435       astman_send_error(s, m, "No number specified");
13436       return 0;
13437    }
13438    p = find_channel(atoi(channel));
13439    if (!p) {
13440       astman_send_error(s, m, "No such channel");
13441       return 0;
13442    }
13443    if (!p->owner) {
13444       astman_send_error(s, m, "Channel does not have it's owner");
13445       return 0;
13446    }
13447    for (i = 0; i < strlen(number); i++) {
13448       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13449       dahdi_queue_frame(p, &f, NULL); 
13450    }
13451    astman_send_ack(s, m, "DAHDIDialOffhook");
13452    return 0;
13453 }

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

Definition at line 13366 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, find_channel(), and s.

Referenced by load_module().

13367 {
13368    struct dahdi_pvt *p = NULL;
13369    const char *channel = astman_get_header(m, "DAHDIChannel");
13370 
13371    if (ast_strlen_zero(channel)) {
13372       astman_send_error(s, m, "No channel specified");
13373       return 0;
13374    }
13375    p = find_channel(atoi(channel));
13376    if (!p) {
13377       astman_send_error(s, m, "No such channel");
13378       return 0;
13379    }
13380    p->dnd = 0;
13381    astman_send_ack(s, m, "DND Disabled");
13382    return 0;
13383 }

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

Definition at line 13347 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_pvt::dnd, find_channel(), and s.

Referenced by load_module().

13348 {
13349    struct dahdi_pvt *p = NULL;
13350    const char *channel = astman_get_header(m, "DAHDIChannel");
13351 
13352    if (ast_strlen_zero(channel)) {
13353       astman_send_error(s, m, "No channel specified");
13354       return 0;
13355    }
13356    p = find_channel(atoi(channel));
13357    if (!p) {
13358       astman_send_error(s, m, "No such channel");
13359       return 0;
13360    }
13361    p->dnd = 1;
13362    astman_send_ack(s, m, "DND Enabled");
13363    return 0;
13364 }

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

Definition at line 12621 of file chan_dahdi.c.

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

Referenced by load_module().

12622 {
12623    if (dahdi_restart() != 0) {
12624       astman_send_error(s, m, "Failed rereading DAHDI configuration");
12625       return 1;
12626    }
12627    astman_send_ack(s, m, "DAHDIRestart: Success");
12628    return 0;
12629 }

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

Definition at line 13455 of file chan_dahdi.c.

References ast_channel::accountcode, alarm2str(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), dahdi_pvt::channel, dahdi_pvt::context, dahdi_pvt::dnd, get_alarms(), iflist, iflock, ast_channel::name, dahdi_pvt::next, dahdi_pvt::owner, s, dahdi_pvt::sig, sig2str, and ast_channel::uniqueid.

Referenced by load_module().

13456 {
13457    struct dahdi_pvt *tmp = NULL;
13458    const char *id = astman_get_header(m, "ActionID");
13459    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13460    char idText[256] = "";
13461    int channels = 0;
13462    int dahdichanquery = -1;
13463    if (!ast_strlen_zero(dahdichannel)) {
13464       dahdichanquery = atoi(dahdichannel);
13465    }
13466 
13467    astman_send_ack(s, m, "DAHDI channel status will follow");
13468    if (!ast_strlen_zero(id))
13469       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13470 
13471    ast_mutex_lock(&iflock);
13472    
13473    tmp = iflist;
13474    while (tmp) {
13475       if (tmp->channel > 0) {
13476          int alm = get_alarms(tmp);
13477 
13478          /* If a specific channel is queried for, only deliver status for that channel */
13479          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13480             continue;
13481 
13482          channels++;
13483          if (tmp->owner) {
13484             /* Add data if we have a current call */
13485             astman_append(s,
13486                "Event: DAHDIShowChannels\r\n"
13487                "DAHDIChannel: %d\r\n"
13488                "Channel: %s\r\n"
13489                "Uniqueid: %s\r\n"
13490                "AccountCode: %s\r\n"
13491                "Signalling: %s\r\n"
13492                "SignallingCode: %d\r\n"
13493                "Context: %s\r\n"
13494                "DND: %s\r\n"
13495                "Alarm: %s\r\n"
13496                "%s"
13497                "\r\n",
13498                tmp->channel, 
13499                tmp->owner->name,
13500                tmp->owner->uniqueid,
13501                tmp->owner->accountcode,
13502                sig2str(tmp->sig), 
13503                tmp->sig,
13504                tmp->context, 
13505                tmp->dnd ? "Enabled" : "Disabled",
13506                alarm2str(alm), idText);
13507          } else {
13508             astman_append(s,
13509                "Event: DAHDIShowChannels\r\n"
13510                "DAHDIChannel: %d\r\n"
13511                "Signalling: %s\r\n"
13512                "SignallingCode: %d\r\n"
13513                "Context: %s\r\n"
13514                "DND: %s\r\n"
13515                "Alarm: %s\r\n"
13516                "%s"
13517                "\r\n",
13518                tmp->channel, sig2str(tmp->sig), tmp->sig, 
13519                tmp->context, 
13520                tmp->dnd ? "Enabled" : "Disabled",
13521                alarm2str(alm), idText);
13522          }
13523       } 
13524 
13525       tmp = tmp->next;
13526    }
13527 
13528    ast_mutex_unlock(&iflock);
13529    
13530    astman_append(s, 
13531       "Event: DAHDIShowChannelsComplete\r\n"
13532       "%s"
13533       "Items: %d\r\n"
13534       "\r\n", 
13535       idText,
13536       channels);
13537    return 0;
13538 }

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

Definition at line 13385 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), s, and TRANSFER.

Referenced by load_module().

13386 {
13387    struct dahdi_pvt *p = NULL;
13388    const char *channel = astman_get_header(m, "DAHDIChannel");
13389 
13390    if (ast_strlen_zero(channel)) {
13391       astman_send_error(s, m, "No channel specified");
13392       return 0;
13393    }
13394    p = find_channel(atoi(channel));
13395    if (!p) {
13396       astman_send_error(s, m, "No such channel");
13397       return 0;
13398    }
13399    dahdi_fake_event(p,TRANSFER);
13400    astman_send_ack(s, m, "DAHDITransfer");
13401    return 0;
13402 }

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

Definition at line 13404 of file chan_dahdi.c.

References ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), dahdi_pvt::channel, dahdi_fake_event(), find_channel(), HANGUP, and s.

Referenced by load_module().

13405 {
13406    struct dahdi_pvt *p = NULL;
13407    const char *channel = astman_get_header(m, "DAHDIChannel");
13408 
13409    if (ast_strlen_zero(channel)) {
13410       astman_send_error(s, m, "No channel specified");
13411       return 0;
13412    }
13413    p = find_channel(atoi(channel));
13414    if (!p) {
13415       astman_send_error(s, m, "No such channel");
13416       return 0;
13417    }
13418    dahdi_fake_event(p,HANGUP);
13419    astman_send_ack(s, m, "DAHDIHangup");
13420    return 0;
13421 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 1745 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

01746 {
01747    int x;
01748    for (x = 0; x < ARRAY_LEN(alarms); x++) {
01749       if (alarms[x].alarm & alm)
01750          return alarms[x].name;
01751    }
01752    return alm ? "Unknown Alarm" : "No Alarm";
01753 }

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

Definition at line 1541 of file chan_dahdi.c.

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

Referenced by build_device(), dahdi_handle_event(), dahdi_request(), HandleCallOutgoing(), rcv_mac_addr(), and ss_thread().

01542 {
01543    struct dahdi_bufferinfo bi;
01544    int res;
01545    if (p->subs[x].dfd >= 0) {
01546       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01547       return -1;
01548    }
01549 
01550    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01551    if (p->subs[x].dfd <= -1) {
01552       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01553       return -1;
01554    }
01555 
01556    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01557    if (!res) {
01558       bi.txbufpolicy = p->buf_policy;
01559       bi.rxbufpolicy = p->buf_policy;
01560       bi.numbufs = p->buf_no;
01561       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01562       if (res < 0) {
01563          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01564       }
01565    } else 
01566       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01567 
01568    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01569       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01570       dahdi_close_sub(p, x);
01571       p->subs[x].dfd = -1;
01572       return -1;
01573    }
01574    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01575    return 0;
01576 }

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

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

10824 {
10825    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10826       snprintf(buf, size, "%s", number);
10827       return;
10828    }
10829    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10830       if (size) {
10831          *buf = '\0';
10832       }
10833       return;
10834    }
10835    switch (plan) {
10836    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10837       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10838       break;
10839    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10840       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10841       break;
10842    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10843       snprintf(buf, size, "%s%s", pri->localprefix, number);
10844       break;
10845    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10846       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10847       break;
10848    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10849       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10850       break;
10851    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10852       snprintf(buf, size, "%s", number);
10853       break;
10854    }
10855 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 4509 of file chan_dahdi.c.

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

Referenced by close_call(), dahdi_handle_event(), handle_request(), and local_attended_transfer().

04510 {
04511    /* In order to transfer, we need at least one of the channels to
04512       actually be in a call bridge.  We can't conference two applications
04513       together (but then, why would we want to?) */
04514    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
04515       /* The three-way person we're about to transfer to could still be in MOH, so
04516          stop if now if appropriate */
04517       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
04518          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
04519       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
04520          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
04521       }
04522       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
04523          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
04524       }
04525        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
04526          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04527                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
04528          return -1;
04529       }
04530       /* Orphan the channel after releasing the lock */
04531       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04532       unalloc_sub(p, SUB_THREEWAY);
04533    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04534       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04535       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
04536          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
04537       }
04538       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
04539          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04540       }
04541       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
04542          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04543                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
04544          return -1;
04545       }
04546       /* Three-way is now the REAL */
04547       swap_subs(p, SUB_THREEWAY, SUB_REAL);
04548       ast_channel_unlock(p->subs[SUB_REAL].owner);
04549       unalloc_sub(p, SUB_THREEWAY);
04550       /* Tell the caller not to hangup */
04551       return 1;
04552    } else {
04553       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04554          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
04555       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04556       return -1;
04557    }
04558    return 0;
04559 }

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

Definition at line 9259 of file chan_dahdi.c.

References ast_channel::_state, ast_debug, 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, dahdi_pvt::locallyblocked, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::radio, dahdi_pvt::remotelyblocked, 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_ptr_build_va(), and dahdi_request().

09260 {
09261    int res;
09262    struct dahdi_params par;
09263 
09264    /* First, check group matching */
09265    if (groupmatch) {
09266       if ((p->group & groupmatch) != groupmatch)
09267          return 0;
09268       *groupmatched = 1;
09269    }
09270    /* Check to see if we have a channel match */
09271    if (channelmatch != -1) {
09272       if (p->channel != channelmatch)
09273          return 0;
09274       *channelmatched = 1;
09275    }
09276    /* We're at least busy at this point */
09277    if (busy) {
09278       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09279          *busy = 1;
09280    }
09281    /* If do not disturb, definitely not */
09282    if (p->dnd)
09283       return 0;
09284    /* If guard time, definitely not */
09285    if (p->guardtime && (time(NULL) < p->guardtime)) 
09286       return 0;
09287 
09288    if (p->locallyblocked || p->remotelyblocked)
09289       return 0;
09290       
09291    /* If no owner definitely available */
09292    if (!p->owner) {
09293 #ifdef HAVE_PRI
09294       /* Trust PRI */
09295       if (p->pri) {
09296          if (p->resetting || p->call)
09297             return 0;
09298          else
09299             return 1;
09300       }
09301 #endif
09302 #ifdef HAVE_SS7
09303       /* Trust SS7 */
09304       if (p->ss7) {
09305          if (p->ss7call)
09306             return 0;
09307          else
09308             return 1;
09309       }
09310 #endif
09311       if (!(p->radio || (p->oprmode < 0)))
09312       {
09313          if (!p->sig || (p->sig == SIG_FXSLS))
09314             return 1;
09315          /* Check hook state */
09316          if (p->subs[SUB_REAL].dfd > -1) {
09317             memset(&par, 0, sizeof(par));
09318             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09319          } else {
09320             /* Assume not off hook on CVRS */
09321             res = 0;
09322             par.rxisoffhook = 0;
09323          }
09324          if (res) {
09325             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09326          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09327             /* When "onhook" that means no battery on the line, and thus
09328               it is out of service..., if it's on a TDM card... If it's a channel
09329               bank, there is no telling... */
09330             if (par.rxbits > -1)
09331                return 1;
09332             if (par.rxisoffhook)
09333                return 1;
09334             else
09335                return 0;
09336          } else if (par.rxisoffhook) {
09337             ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09338             /* Not available when the other end is off hook */
09339 #ifdef DAHDI_CHECK_HOOKSTATE
09340             return 0;
09341 #else
09342             return 1;
09343 #endif
09344          }
09345       }
09346       return 1;
09347    }
09348 
09349    /* If it's not an FXO, forget about call wait */
09350    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09351       return 0;
09352 
09353    if (!p->callwaiting) {
09354       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09355       return 0;
09356    }
09357 
09358    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09359       /* If there is already a call waiting call, then we can't take a second one */
09360       return 0;
09361    }
09362    
09363    if ((p->owner->_state != AST_STATE_UP) &&
09364        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09365       /* If the current call is not up, then don't allow the call */
09366       return 0;
09367    }
09368    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09369       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09370       return 0;
09371    }
09372    /* We're cool */
09373    return 1;
09374 }

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

References ast_log(), ast_strdupa, ast_verb, dahdi_chan_conf::chan, chan, CHAN_PSEUDO, HAVE_PRI, dahdi_chan_conf::is_sig_auto, LOG_ERROR, mkintf(), NUM_SPANS, dahdi_pri::pri, pris, dahdi_pvt::sig, sig2str, strsep(), and dahdi_pri::trunkgroup.

Referenced by process_dahdi().

14087 {
14088    char *c, *chan;
14089    int x, start, finish;
14090    struct dahdi_pvt *tmp;
14091 #ifdef HAVE_PRI
14092    struct dahdi_pri *pri;
14093    int trunkgroup, y;
14094 #endif
14095    
14096    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14097       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14098       return -1;
14099    }
14100 
14101    c = ast_strdupa(value);
14102 
14103 #ifdef HAVE_PRI
14104    pri = NULL;
14105    if (iscrv) {
14106       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
14107          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14108          return -1;
14109       }
14110       if (trunkgroup < 1) {
14111          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14112          return -1;
14113       }
14114       c += y;
14115       for (y = 0; y < NUM_SPANS; y++) {
14116          if (pris[y].trunkgroup == trunkgroup) {
14117             pri = pris + y;
14118             break;
14119          }
14120       }
14121       if (!pri) {
14122          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14123          return -1;
14124       }
14125    }
14126 #endif         
14127 
14128    while ((chan = strsep(&c, ","))) {
14129       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
14130          /* Range */
14131       } else if (sscanf(chan, "%d", &start)) {
14132          /* Just one */
14133          finish = start;
14134       } else if (!strcasecmp(chan, "pseudo")) {
14135          finish = start = CHAN_PSEUDO;
14136          if (found_pseudo)
14137             *found_pseudo = 1;
14138       } else {
14139          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14140          return -1;
14141       }
14142       if (finish < start) {
14143          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14144          x = finish;
14145          finish = start;
14146          start = x;
14147       }
14148 
14149       for (x = start; x <= finish; x++) {
14150 #ifdef HAVE_PRI
14151          tmp = mkintf(x, conf, pri, reload);
14152 #else       
14153          tmp = mkintf(x, conf, NULL, reload);
14154 #endif         
14155 
14156          if (tmp) {
14157 #ifdef HAVE_PRI
14158                if (pri)
14159                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14160                else
14161 #endif
14162                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14163          } else {
14164             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14165                (reload == 1) ? "reconfigure" : "register", value);
14166             return -1;
14167          }
14168       }
14169    }
14170 
14171    return 0;
14172 }

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

Definition at line 12252 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

12253 {
12254    if (!s || len < 1) {
12255       return;
12256    }
12257    s[0] = '\0';
12258    if (status & DCHAN_PROVISIONED)
12259       strncat(s, "Provisioned, ", len - strlen(s) - 1);
12260    if (!(status & DCHAN_NOTINALARM))
12261       strncat(s, "In Alarm, ", len - strlen(s) - 1);
12262    if (status & DCHAN_UP)
12263       strncat(s, "Up", len - strlen(s) - 1);
12264    else
12265       strncat(s, "Down", len - strlen(s) - 1);
12266    if (active)
12267       strncat(s, ", Active", len - strlen(s) - 1);
12268    else
12269       strncat(s, ", Standby", len - strlen(s) - 1);
12270    s[len - 1] = '\0';
12271 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 2200 of file chan_dahdi.c.

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

Referenced by mwi_thread(), and ss_thread().

02201 {
02202    int res;
02203 
02204    /* Bump receive gain by value stored in cid_rxgain */
02205    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02206    if (res) {
02207       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02208       return -1;
02209    }
02210 
02211    return 0;
02212 }

static int calc_energy ( const unsigned char *  buf,
int  len,
int  law 
) [static]

Definition at line 7744 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by mwi_thread().

07745 {
07746    int x;
07747    int sum = 0;
07748 
07749    if (!len)
07750       return 0;
07751 
07752    for (x = 0; x < len; x++)
07753       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07754 
07755    return sum / len;
07756 }

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

Definition at line 9376 of file chan_dahdi.c.

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

Referenced by dahdi_request().

09377 {
09378    struct dahdi_pvt *p;
09379    struct dahdi_bufferinfo bi;
09380    int res;
09381    
09382    if ((p = ast_malloc(sizeof(*p)))) {
09383       memcpy(p, src, sizeof(struct dahdi_pvt));
09384       ast_mutex_init(&p->lock);
09385       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09386       /* Allocate a dahdi structure */
09387       if (p->subs[SUB_REAL].dfd < 0) {
09388          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09389          destroy_dahdi_pvt(&p);
09390          return NULL;
09391       }
09392       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09393       if (!res) {
09394          bi.txbufpolicy = src->buf_policy;
09395          bi.rxbufpolicy = src->buf_policy;
09396          bi.numbufs = src->buf_no;
09397          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09398          if (res < 0) {
09399             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09400          }
09401       } else
09402          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09403    }
09404    p->destroy = 1;
09405    p->next = iflist;
09406    p->prev = NULL;
09407    iflist = p;
09408    if (iflist->next)
09409       iflist->next->prev = p;
09410    return p;
09411 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 4561 of file chan_dahdi.c.

References ast_log(), ast_verb, dahdi_pvt::channel, dahdi_pvt::confno, errno, dahdi_pvt::master, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_handle_event().

04562 {
04563    struct dahdi_confinfo ci;
04564    /* Fine if we already have a master, etc */
04565    if (p->master || (p->confno > -1))
04566       return 0;
04567    memset(&ci, 0, sizeof(ci));
04568    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04569       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04570       return 0;
04571    }
04572    /* If we have no master and don't have a confno, then 
04573       if we're in a conference, it's probably a MeetMe room or
04574       some such, so don't let us 3-way out! */
04575    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04576       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04577       return 1;
04578    }
04579    return 0;
04580 }

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

Definition at line 12077 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

12078 {
12079    return complete_span_helper(line,word,pos,state,3);
12080 }

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

Definition at line 12082 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_no_debug(), and handle_pri_really_debug().

12083 {
12084    return complete_span_helper(line,word,pos,state,4);
12085 }

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

Definition at line 12058 of file chan_dahdi.c.

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

Referenced by complete_span_4(), and complete_span_5().

12059 {
12060    int which, span;
12061    char *ret = NULL;
12062 
12063    if (pos != rpos)
12064       return ret;
12065 
12066    for (which = span = 0; span < NUM_SPANS; span++) {
12067       if (pris[span].pri && ++which > state) {
12068          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
12069             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12070          }
12071          break;
12072       }
12073    }
12074    return ret;
12075 }

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

Definition at line 1842 of file chan_dahdi.c.

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

Referenced by update_conf().

01843 {
01844    /* If the conference already exists, and we're already in it
01845       don't bother doing anything */
01846    struct dahdi_confinfo zi;
01847    
01848    memset(&zi, 0, sizeof(zi));
01849    zi.chan = 0;
01850 
01851    if (slavechannel > 0) {
01852       /* If we have only one slave, do a digital mon */
01853       zi.confmode = DAHDI_CONF_DIGITALMON;
01854       zi.confno = slavechannel;
01855    } else {
01856       if (!idx) {
01857          /* Real-side and pseudo-side both participate in conference */
01858          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01859             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01860       } else
01861          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01862       zi.confno = p->confno;
01863    }
01864    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01865       return 0;
01866    if (c->dfd < 0)
01867       return 0;
01868    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01869       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01870       return -1;
01871    }
01872    if (slavechannel < 1) {
01873       p->confno = zi.confno;
01874    }
01875    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01876    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01877    return 0;
01878 }

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

Definition at line 1891 of file chan_dahdi.c.

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

Referenced by dahdi_unlink(), and update_conf().

01892 {
01893    struct dahdi_confinfo zi;
01894    if (/* Can't delete if there's no dfd */
01895       (c->dfd < 0) ||
01896       /* Don't delete from the conference if it's not our conference */
01897       !isourconf(p, c)
01898       /* Don't delete if we don't think it's conferenced at all (implied) */
01899       ) return 0;
01900    memset(&zi, 0, sizeof(zi));
01901    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01902       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01903       return -1;
01904    }
01905    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01906    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01907    return 0;
01908 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 3749 of file chan_dahdi.c.

References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_RINGING, AST_STATE_UP, ast_tvnow(), 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_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_BRI, SIG_BRI_PTMP, 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, SIG_SS7, dahdi_pvt::span, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.

03750 {
03751    struct dahdi_pvt *p = ast->tech_pvt;
03752    int res = 0;
03753    int idx;
03754    int oldstate = ast->_state;
03755    ast_setstate(ast, AST_STATE_UP);
03756    ast_mutex_lock(&p->lock);
03757    idx = dahdi_get_index(ast, p, 0);
03758    if (idx < 0)
03759       idx = SUB_REAL;
03760    /* nothing to do if a radio channel */
03761    if ((p->radio || (p->oprmode < 0))) {
03762       ast_mutex_unlock(&p->lock);
03763       return 0;
03764    }
03765    switch (p->sig) {
03766    case SIG_FXSLS:
03767    case SIG_FXSGS:
03768    case SIG_FXSKS:
03769       p->ringt = 0;
03770       /* Fall through */
03771    case SIG_EM:
03772    case SIG_EM_E1:
03773    case SIG_EMWINK:
03774    case SIG_FEATD:
03775    case SIG_FEATDMF:
03776    case SIG_FEATDMF_TA:
03777    case SIG_E911:
03778    case SIG_FGC_CAMA:
03779    case SIG_FGC_CAMAMF:
03780    case SIG_FEATB:
03781    case SIG_SF:
03782    case SIG_SFWINK:
03783    case SIG_SF_FEATD:
03784    case SIG_SF_FEATDMF:
03785    case SIG_SF_FEATB:
03786    case SIG_FXOLS:
03787    case SIG_FXOGS:
03788    case SIG_FXOKS:
03789       /* Pick up the line */
03790       ast_debug(1, "Took %s off hook\n", ast->name);
03791       if (p->hanguponpolarityswitch) {
03792          p->polaritydelaytv = ast_tvnow();
03793       }
03794       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
03795       tone_zone_play_tone(p->subs[idx].dfd, -1);
03796       p->dialing = 0;
03797       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
03798          if (oldstate == AST_STATE_RINGING) {
03799             ast_debug(1, "Finally swapping real and threeway\n");
03800             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
03801             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03802             p->owner = p->subs[SUB_REAL].owner;
03803          }
03804       }
03805       if (p->sig & __DAHDI_SIG_FXS) {
03806          dahdi_enable_ec(p);
03807          dahdi_train_ec(p);
03808       }
03809       break;
03810 #ifdef HAVE_PRI
03811    case SIG_BRI:
03812    case SIG_BRI_PTMP:
03813    case SIG_PRI:
03814       /* Send a pri acknowledge */
03815       if (!pri_grab(p, p->pri)) {
03816          p->proceeding = 1;
03817          p->dialing = 0;
03818          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
03819          pri_rel(p->pri);
03820       } else {
03821          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03822          res = -1;
03823       }
03824       break;
03825 #endif
03826 #ifdef HAVE_SS7
03827    case SIG_SS7:
03828       if (!ss7_grab(p, p->ss7)) {
03829          p->proceeding = 1;
03830          res = isup_anm(p->ss7->ss7, p->ss7call);
03831          ss7_rel(p->ss7);
03832       } else {
03833          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
03834          res = -1;
03835       }
03836       break;
03837 #endif
03838    case 0:
03839       ast_mutex_unlock(&p->lock);
03840       return 0;
03841    default:
03842       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
03843       res = -1;
03844    }
03845    ast_mutex_unlock(&p->lock);
03846    return res;
03847 }

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 4161 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_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), dahdi_pvt::call, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, master, ast_channel::name, 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, and update_conf().

04162 {
04163    struct ast_channel *who;
04164    struct dahdi_pvt *p0, *p1, *op0, *op1;
04165    struct dahdi_pvt *master = NULL, *slave = NULL;
04166    struct ast_frame *f;
04167    int inconf = 0;
04168    int nothingok = 1;
04169    int ofd0, ofd1;
04170    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
04171    int os0 = -1, os1 = -1;
04172    int priority = 0;
04173    struct ast_channel *oc0, *oc1;
04174    enum ast_bridge_result res;
04175 
04176 #ifdef PRI_2BCT
04177    int triedtopribridge = 0;
04178    q931_call *q931c0 = NULL, *q931c1 = NULL;
04179 #endif
04180 
04181    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
04182       There is code below to handle it properly until DTMF is actually seen,
04183       but due to currently unresolved issues it's ignored...
04184    */
04185 
04186    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
04187       return AST_BRIDGE_FAILED_NOWARN;
04188 
04189    ast_channel_lock(c0);
04190    while (ast_channel_trylock(c1)) {
04191       CHANNEL_DEADLOCK_AVOIDANCE(c0);
04192    }
04193 
04194    p0 = c0->tech_pvt;
04195    p1 = c1->tech_pvt;
04196    /* cant do pseudo-channels here */
04197    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
04198       ast_channel_unlock(c0);
04199       ast_channel_unlock(c1);
04200       return AST_BRIDGE_FAILED_NOWARN;
04201    }
04202 
04203    oi0 = dahdi_get_index(c0, p0, 0);
04204    oi1 = dahdi_get_index(c1, p1, 0);
04205    if ((oi0 < 0) || (oi1 < 0)) {
04206       ast_channel_unlock(c0);
04207       ast_channel_unlock(c1);
04208       return AST_BRIDGE_FAILED;
04209    }
04210 
04211    op0 = p0 = c0->tech_pvt;
04212    op1 = p1 = c1->tech_pvt;
04213    ofd0 = c0->fds[0];
04214    ofd1 = c1->fds[0];
04215    oc0 = p0->owner;
04216    oc1 = p1->owner;
04217 
04218    if (ast_mutex_trylock(&p0->lock)) {
04219       /* Don't block, due to potential for deadlock */
04220       ast_channel_unlock(c0);
04221       ast_channel_unlock(c1);
04222       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04223       return AST_BRIDGE_RETRY;
04224    }
04225    if (ast_mutex_trylock(&p1->lock)) {
04226       /* Don't block, due to potential for deadlock */
04227       ast_mutex_unlock(&p0->lock);
04228       ast_channel_unlock(c0);
04229       ast_channel_unlock(c1);
04230       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
04231       return AST_BRIDGE_RETRY;
04232    }
04233 
04234    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04235       if (p0->owner && p1->owner) {
04236          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
04237          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
04238             master = p0;
04239             slave = p1;
04240             inconf = 1;
04241          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
04242             master = p1;
04243             slave = p0;
04244             inconf = 1;
04245          } else {
04246             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
04247             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
04248                p0->channel,
04249                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04250                p0->subs[SUB_REAL].inthreeway, p0->channel,
04251                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
04252                p1->subs[SUB_REAL].inthreeway);
04253          }
04254          nothingok = 0;
04255       }
04256    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
04257       if (p1->subs[SUB_THREEWAY].inthreeway) {
04258          master = p1;
04259          slave = p0;
04260          nothingok = 0;
04261       }
04262    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
04263       if (p0->subs[SUB_THREEWAY].inthreeway) {
04264          master = p0;
04265          slave = p1;
04266          nothingok = 0;
04267       }
04268    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
04269       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise, 
04270          don't put us in anything */
04271       if (p1->subs[SUB_CALLWAIT].inthreeway) {
04272          master = p1;
04273          slave = p0;
04274          nothingok = 0;
04275       }
04276    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
04277       /* Same as previous */
04278       if (p0->subs[SUB_CALLWAIT].inthreeway) {
04279          master = p0;
04280          slave = p1;
04281          nothingok = 0;
04282       }
04283    }
04284    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
04285       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
04286    if (master && slave) {
04287       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
04288          in an active threeway call with a channel that is ringing, we should
04289          indicate ringing. */
04290       if ((oi1 == SUB_THREEWAY) && 
04291           p1->subs[SUB_THREEWAY].inthreeway && 
04292           p1->subs[SUB_REAL].owner && 
04293           p1->subs[SUB_REAL].inthreeway && 
04294           (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04295          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
04296          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
04297          os1 = p1->subs[SUB_REAL].owner->_state;
04298       } else {
04299          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
04300          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
04301       }
04302       if ((oi0 == SUB_THREEWAY) && 
04303           p0->subs[SUB_THREEWAY].inthreeway && 
04304           p0->subs[SUB_REAL].owner && 
04305           p0->subs[SUB_REAL].inthreeway && 
04306           (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
04307          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
04308          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
04309          os0 = p0->subs[SUB_REAL].owner->_state;
04310       } else {
04311          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
04312          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
04313       }
04314       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
04315          if (!p0->echocanbridged || !p1->echocanbridged) {
04316             /* Disable echo cancellation if appropriate */
04317             dahdi_disable_ec(p0);
04318             dahdi_disable_ec(p1);
04319          }
04320       }
04321       dahdi_link(slave, master);
04322       master->inconference = inconf;
04323    } else if (!nothingok)
04324       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
04325 
04326    update_conf(p0);
04327    update_conf(p1);
04328    t0 = p0->subs[SUB_REAL].inthreeway;
04329    t1 = p1->subs[SUB_REAL].inthreeway;
04330 
04331    ast_mutex_unlock(&p0->lock);
04332    ast_mutex_unlock(&p1->lock);
04333 
04334    ast_channel_unlock(c0);
04335    ast_channel_unlock(c1);
04336 
04337    /* Native bridge failed */
04338    if ((!master || !slave) && !nothingok) {
04339       dahdi_enable_ec(p0);
04340       dahdi_enable_ec(p1);
04341       return AST_BRIDGE_FAILED;
04342    }
04343    
04344    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04345 
04346    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04347       disable_dtmf_detect(op0);
04348 
04349    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04350       disable_dtmf_detect(op1);
04351 
04352    for (;;) {
04353       struct ast_channel *c0_priority[2] = {c0, c1};
04354       struct ast_channel *c1_priority[2] = {c1, c0};
04355 
04356       /* Here's our main loop...  Start by locking things, looking for private parts, 
04357          and then balking if anything is wrong */
04358       
04359       ast_channel_lock(c0);
04360       while (ast_channel_trylock(c1)) {
04361          CHANNEL_DEADLOCK_AVOIDANCE(c0);
04362       }
04363 
04364       p0 = c0->tech_pvt;
04365       p1 = c1->tech_pvt;
04366 
04367       if (op0 == p0)
04368          i0 = dahdi_get_index(c0, p0, 1);
04369       if (op1 == p1)
04370          i1 = dahdi_get_index(c1, p1, 1);
04371 
04372       ast_channel_unlock(c0);
04373       ast_channel_unlock(c1);
04374 
04375       if (!timeoutms || 
04376           (op0 != p0) ||
04377           (op1 != p1) || 
04378           (ofd0 != c0->fds[0]) || 
04379           (ofd1 != c1->fds[0]) ||
04380           (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) || 
04381           (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) || 
04382           (oc0 != p0->owner) || 
04383           (oc1 != p1->owner) ||
04384           (t0 != p0->subs[SUB_REAL].inthreeway) ||
04385           (t1 != p1->subs[SUB_REAL].inthreeway) ||
04386           (oi0 != i0) ||
04387           (oi1 != i1)) {
04388          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
04389             op0->channel, oi0, op1->channel, oi1);
04390          res = AST_BRIDGE_RETRY;
04391          goto return_from_bridge;
04392       }
04393 
04394 #ifdef PRI_2BCT
04395       q931c0 = p0->call;
04396       q931c1 = p1->call;
04397       if (p0->transfer && p1->transfer 
04398           && q931c0 && q931c1 
04399           && !triedtopribridge) {
04400          pri_channel_bridge(q931c0, q931c1);
04401          triedtopribridge = 1;
04402       }
04403 #endif
04404 
04405       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
04406       if (!who) {
04407          ast_debug(1, "Ooh, empty read...\n");
04408          continue;
04409       }
04410       f = ast_read(who);
04411       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
04412          *fo = f;
04413          *rc = who;
04414          res = AST_BRIDGE_COMPLETE;
04415          goto return_from_bridge;
04416       }
04417       if (f->frametype == AST_FRAME_DTMF) {
04418          if ((who == c0) && p0->pulsedial) {
04419             ast_write(c1, f);
04420          } else if ((who == c1) && p1->pulsedial) {
04421             ast_write(c0, f);
04422          } else {
04423             *fo = f;
04424             *rc = who;
04425             res = AST_BRIDGE_COMPLETE;
04426             goto return_from_bridge;
04427          }
04428       }
04429       ast_frfree(f);
04430       
04431       /* Swap who gets priority */
04432       priority = !priority;
04433    }
04434 
04435 return_from_bridge:
04436    if (op0 == p0)
04437       dahdi_enable_ec(p0);
04438 
04439    if (op1 == p1)
04440       dahdi_enable_ec(p1);
04441 
04442    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
04443       enable_dtmf_detect(op0);
04444 
04445    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
04446       enable_dtmf_detect(op1);
04447 
04448    dahdi_unlink(slave, master, 1);
04449 
04450    return res;
04451 }

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

Definition at line 2463 of file chan_dahdi.c.

References ast_channel::_state, ast_callerid_generate(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_debug, ast_free, 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_verb, 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_ani2, 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, 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_ERROR, 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, 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_BRI, SIG_BRI_PTMP, 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, SIG_SS7, 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, and dahdi_pvt::whichwink.

02464 {
02465    struct dahdi_pvt *p = ast->tech_pvt;
02466    int x, res, idx,mysig;
02467    char *c, *n, *l;
02468 #ifdef HAVE_PRI
02469    char *s = NULL;
02470 #endif
02471    char dest[256]; /* must be same length as p->dialdest */
02472    ast_mutex_lock(&p->lock);
02473    ast_copy_string(dest, rdest, sizeof(dest));
02474    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
02475    if ((ast->_state == AST_STATE_BUSY)) {
02476       p->subs[SUB_REAL].needbusy = 1;
02477       ast_mutex_unlock(&p->lock);
02478       return 0;
02479    }
02480    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02481       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
02482       ast_mutex_unlock(&p->lock);
02483       return -1;
02484    }
02485    p->dialednone = 0;
02486    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
02487    {
02488       /* Special pseudo -- automatically up */
02489       ast_setstate(ast, AST_STATE_UP); 
02490       ast_mutex_unlock(&p->lock);
02491       return 0;
02492    }
02493    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
02494    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
02495    if (res)
02496       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
02497    p->outgoing = 1;
02498 
02499    set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02500 
02501    mysig = p->sig;
02502    if (p->outsigmod > -1)
02503       mysig = p->outsigmod;
02504 
02505    switch (mysig) {
02506    case SIG_FXOLS:
02507    case SIG_FXOGS:
02508    case SIG_FXOKS:
02509       if (p->owner == ast) {
02510          /* Normal ring, on hook */
02511          
02512          /* Don't send audio while on hook, until the call is answered */
02513          p->dialing = 1;
02514          if (p->use_callerid) {
02515             /* Generate the Caller-ID spill if desired */
02516             if (p->cidspill) {
02517                ast_log(LOG_WARNING, "cidspill already exists??\n");
02518                ast_free(p->cidspill);
02519             }
02520             p->callwaitcas = 0;
02521             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
02522                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
02523                p->cidpos = 0;
02524                send_callerid(p);
02525             }
02526          }
02527          /* Choose proper cadence */
02528          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
02529             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
02530                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
02531             p->cidrings = cidrings[p->distinctivering - 1];
02532          } else {
02533             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
02534                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
02535             p->cidrings = p->sendcalleridafter;
02536          }
02537 
02538          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
02539          c = strchr(dest, '/');
02540          if (c)
02541             c++;
02542          if (c && (strlen(c) < p->stripmsd)) {
02543             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02544             c = NULL;
02545          }
02546          if (c) {
02547             p->dop.op = DAHDI_DIAL_OP_REPLACE;
02548             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
02549             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
02550          } else {
02551             p->dop.dialstr[0] = '\0';
02552          }
02553          x = DAHDI_RING;
02554          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
02555             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
02556             ast_mutex_unlock(&p->lock);
02557             return -1;
02558          }
02559          p->dialing = 1;
02560       } else {
02561          /* Call waiting call */
02562          p->callwaitrings = 0;
02563          if (ast->cid.cid_num)
02564             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
02565          else
02566             p->callwait_num[0] = '\0';
02567          if (ast->cid.cid_name)
02568             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
02569          else
02570             p->callwait_name[0] = '\0';
02571          /* Call waiting tone instead */
02572          if (dahdi_callwait(ast)) {
02573             ast_mutex_unlock(&p->lock);
02574             return -1;
02575          }
02576          /* Make ring-back */
02577          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
02578             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
02579             
02580       }
02581       n = ast->cid.cid_name;
02582       l = ast->cid.cid_num;
02583       if (l)
02584          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
02585       else
02586          p->lastcid_num[0] = '\0';
02587       if (n)
02588          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
02589       else
02590          p->lastcid_name[0] = '\0';
02591       ast_setstate(ast, AST_STATE_RINGING);
02592       idx = dahdi_get_index(ast, p, 0);
02593       if (idx > -1) {
02594          p->subs[idx].needringing = 1;
02595       }
02596       break;
02597    case SIG_FXSLS:
02598    case SIG_FXSGS:
02599    case SIG_FXSKS:
02600    case SIG_EMWINK:
02601    case SIG_EM:
02602    case SIG_EM_E1:
02603    case SIG_FEATD:
02604    case SIG_FEATDMF:
02605    case SIG_E911:
02606    case SIG_FGC_CAMA:
02607    case SIG_FGC_CAMAMF:
02608    case SIG_FEATB:
02609    case SIG_SFWINK:
02610    case SIG_SF:
02611    case SIG_SF_FEATD:
02612    case SIG_SF_FEATDMF:
02613    case SIG_FEATDMF_TA:
02614    case SIG_SF_FEATB:
02615       c = strchr(dest, '/');
02616       if (c)
02617          c++;
02618       else
02619          c = "";
02620       if (strlen(c) < p->stripmsd) {
02621          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02622          ast_mutex_unlock(&p->lock);
02623          return -1;
02624       }
02625 #ifdef HAVE_PRI
02626       /* Start the trunk, if not GR-303 */
02627       if (!p->pri) {
02628 #endif
02629          x = DAHDI_START;
02630          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02631          if (res < 0) {
02632             if (errno != EINPROGRESS) {
02633                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
02634                ast_mutex_unlock(&p->lock);
02635                return -1;
02636             }
02637          }
02638 #ifdef HAVE_PRI
02639       }
02640 #endif
02641       ast_debug(1, "Dialing '%s'\n", c);
02642       p->dop.op = DAHDI_DIAL_OP_REPLACE;
02643 
02644       c += p->stripmsd;
02645 
02646       switch (mysig) {
02647       case SIG_FEATD:
02648          l = ast->cid.cid_num;
02649          if (l) 
02650             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
02651          else
02652             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
02653          break;
02654       case SIG_FEATDMF:
02655          l = ast->cid.cid_num;
02656          if (l) 
02657             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
02658          else
02659             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
02660          break;
02661       case SIG_FEATDMF_TA:
02662       {
02663          const char *cic, *ozz;
02664 
02665          /* If you have to go through a Tandem Access point you need to use this */
02666          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
02667          if (!ozz)
02668             ozz = defaultozz;
02669          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
02670          if (!cic)
02671             cic = defaultcic;
02672          if (!ozz || !cic) {
02673             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
02674             ast_mutex_unlock(&p->lock);
02675             return -1;
02676          }
02677          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
02678          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
02679          p->whichwink = 0;
02680       }
02681          break;
02682       case SIG_E911:
02683          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
02684          break;
02685       case SIG_FGC_CAMA:
02686          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
02687          break;
02688       case SIG_FGC_CAMAMF:
02689       case SIG_FEATB:
02690          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
02691          break;
02692       default:
02693          if (p->pulse)
02694             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
02695          else
02696             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
02697          break;
02698       }
02699 
02700       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
02701          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
02702          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
02703          p->echorest[sizeof(p->echorest) - 1] = '\0';
02704          p->echobreak = 1;
02705          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
02706       } else
02707          p->echobreak = 0;
02708       if (!res) {
02709          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
02710             int saveerr = errno;
02711 
02712             x = DAHDI_ONHOOK;
02713             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
02714             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
02715             ast_mutex_unlock(&p->lock);
02716             return -1;
02717          }
02718       } else
02719          ast_debug(1, "Deferring dialing...\n");
02720 
02721       p->dialing = 1;
02722       if (ast_strlen_zero(c))
02723          p->dialednone = 1;
02724       ast_setstate(ast, AST_STATE_DIALING);
02725       break;
02726    case 0:
02727       /* Special pseudo -- automatically up*/
02728       ast_setstate(ast, AST_STATE_UP);
02729       break;      
02730    case SIG_PRI:
02731    case SIG_BRI:
02732    case SIG_BRI_PTMP:
02733    case SIG_SS7:
02734       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
02735       p->dialdest[0] = '\0';
02736       p->dialing = 1;
02737       break;
02738    default:
02739       ast_debug(1, "not yet implemented\n");
02740       ast_mutex_unlock(&p->lock);
02741       return -1;
02742    }
02743 #ifdef HAVE_SS7
02744    if (p->ss7) {
02745       char ss7_called_nai;
02746       int called_nai_strip;
02747       char ss7_calling_nai;
02748       int calling_nai_strip;
02749       const char *charge_str = NULL;
02750       const char *gen_address = NULL;
02751       const char *gen_digits = NULL;
02752       const char *gen_dig_type = NULL;
02753       const char *gen_dig_scheme = NULL;
02754       const char *gen_name = NULL;
02755       const char *jip_digits = NULL;
02756       const char *lspi_ident = NULL;
02757       const char *rlt_flag = NULL;
02758       const char *call_ref_id = NULL;
02759       const char *call_ref_pc = NULL;
02760       const char *send_far = NULL;
02761 
02762       c = strchr(dest, '/');
02763       if (c) {
02764          c++;
02765       } else {
02766          c = "";
02767       }
02768       if (strlen(c) < p->stripmsd) {
02769          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02770          ast_mutex_unlock(&p->lock);
02771          return -1;
02772       }
02773 
02774       if (!p->hidecallerid) {
02775          l = ast->cid.cid_num;
02776       } else {
02777          l = NULL;
02778       }
02779 
02780       if (ss7_grab(p, p->ss7)) {
02781          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
02782          ast_mutex_unlock(&p->lock);
02783          return -1;
02784       }
02785       p->digital = IS_DIGITAL(ast->transfercapability);
02786       p->ss7call = isup_new_call(p->ss7->ss7);
02787 
02788       if (!p->ss7call) {
02789          ss7_rel(p->ss7);
02790          ast_mutex_unlock(&p->lock);
02791          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
02792          return -1;
02793       }
02794 
02795       called_nai_strip = 0;
02796       ss7_called_nai = p->ss7->called_nai;
02797       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
02798          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02799             called_nai_strip = strlen(p->ss7->internationalprefix);
02800             ss7_called_nai = SS7_NAI_INTERNATIONAL;
02801          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02802             called_nai_strip = strlen(p->ss7->nationalprefix);
02803             ss7_called_nai = SS7_NAI_NATIONAL;
02804          } else {
02805             ss7_called_nai = SS7_NAI_SUBSCRIBER;
02806          }
02807       }
02808       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
02809 
02810       calling_nai_strip = 0;
02811       ss7_calling_nai = p->ss7->calling_nai;
02812       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
02813          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
02814             calling_nai_strip = strlen(p->ss7->internationalprefix);
02815             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
02816          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
02817             calling_nai_strip = strlen(p->ss7->nationalprefix);
02818             ss7_calling_nai = SS7_NAI_NATIONAL;
02819          } else {
02820             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
02821          }
02822       }
02823       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
02824          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
02825          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
02826 
02827       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
02828       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
02829 
02830       ast_channel_lock(ast);
02831       /* Set the charge number if it is set */
02832       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
02833       if (charge_str)
02834          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
02835       
02836       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
02837       if (gen_address)
02838          isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
02839       
02840       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
02841       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
02842       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
02843       if (gen_digits)
02844          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme)); 
02845       
02846       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
02847       if (gen_name)
02848          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
02849 
02850       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
02851       if (jip_digits)
02852          isup_set_jip_digits(p->ss7call, jip_digits);
02853       
02854       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
02855       if (lspi_ident)
02856          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00); 
02857       
02858       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
02859       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
02860          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
02861       }
02862       
02863       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
02864       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
02865       if (call_ref_id && call_ref_pc) {
02866          isup_set_callref(p->ss7call, atoi(call_ref_id),
02867                 call_ref_pc ? atoi(call_ref_pc) : 0);
02868       }
02869       
02870       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
02871       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
02872          (isup_far(p->ss7->ss7, p->ss7call));
02873       
02874       ast_channel_unlock(ast);
02875 
02876       isup_iam(p->ss7->ss7, p->ss7call);
02877       ast_setstate(ast, AST_STATE_DIALING);
02878       ss7_rel(p->ss7);
02879    }
02880 #endif /* HAVE_SS7 */
02881 #ifdef HAVE_PRI
02882    if (p->pri) {
02883       struct pri_sr *sr;
02884 #ifdef SUPPORT_USERUSER
02885       const char *useruser;
02886 #endif
02887       int pridialplan;
02888       int dp_strip;
02889       int prilocaldialplan;
02890       int ldp_strip;
02891       int exclusive;
02892       const char *rr_str;
02893       int redirect_reason;
02894 
02895       c = strchr(dest, '/');
02896       if (c) {
02897          c++;
02898       } else {
02899          c = "";
02900       }
02901 
02902       l = NULL;
02903       n = NULL;
02904       if (!p->hidecallerid) {
02905          l = ast->cid.cid_num;
02906          if (!p->hidecalleridname) {
02907             n = ast->cid.cid_name;
02908          }
02909       }
02910 
02911       if (strlen(c) < p->stripmsd) {
02912          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
02913          ast_mutex_unlock(&p->lock);
02914          return -1;
02915       }
02916       if (mysig != SIG_FXSKS) {
02917          p->dop.op = DAHDI_DIAL_OP_REPLACE;
02918          s = strchr(c + p->stripmsd, 'w');
02919          if (s) {
02920             if (strlen(s) > 1)
02921                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
02922             else
02923                p->dop.dialstr[0] = '\0';
02924             *s = '\0';
02925          } else {
02926             p->dop.dialstr[0] = '\0';
02927          }
02928       }
02929       if (pri_grab(p, p->pri)) {
02930          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
02931          ast_mutex_unlock(&p->lock);
02932          return -1;
02933       }
02934       if (!(p->call = pri_new_call(p->pri->pri))) {
02935          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
02936          pri_rel(p->pri);
02937          ast_mutex_unlock(&p->lock);
02938          return -1;
02939       }
02940       if (!(sr = pri_sr_new())) {
02941          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
02942          pri_rel(p->pri);
02943          ast_mutex_unlock(&p->lock);
02944       }
02945       if (p->bearer || (mysig == SIG_FXSKS)) {
02946          if (p->bearer) {
02947             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
02948             p->bearer->call = p->call;
02949          } else
02950             ast_debug(1, "I'm being setup with no bearer right now...\n");
02951 
02952          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
02953       }
02954       p->digital = IS_DIGITAL(ast->transfercapability);
02955       /* Add support for exclusive override */
02956       if (p->priexclusive)
02957          exclusive = 1;
02958       else {
02959       /* otherwise, traditional behavior */
02960          if (p->pri->nodetype == PRI_NETWORK)
02961             exclusive = 0;
02962          else
02963             exclusive = 1;
02964       }
02965       
02966       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
02967       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability, 
02968                (p->digital ? -1 : 
02969                   ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
02970       if (p->pri->facilityenable)
02971          pri_facility_enable(p->pri->pri);
02972 
02973       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
02974       dp_strip = 0;
02975       pridialplan = p->pri->dialplan - 1;
02976       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
02977          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
02978             if (pridialplan == -2) {
02979                dp_strip = strlen(p->pri->internationalprefix);
02980             }
02981             pridialplan = PRI_INTERNATIONAL_ISDN;
02982          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
02983             if (pridialplan == -2) {
02984                dp_strip = strlen(p->pri->nationalprefix);
02985             }
02986             pridialplan = PRI_NATIONAL_ISDN;
02987          } else {
02988             pridialplan = PRI_LOCAL_ISDN;
02989          }
02990       }
02991       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
02992          switch (c[p->stripmsd]) {
02993          case 'U':
02994             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
02995             break;
02996          case 'I':
02997             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
02998             break;
02999          case 'N':
03000             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03001             break;
03002          case 'L':
03003             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03004             break;
03005          case 'S':
03006             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03007             break;
03008          case 'V':
03009             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03010             break;
03011          case 'R':
03012             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03013             break;
03014          case 'u':
03015             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03016             break;
03017          case 'e':
03018             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03019             break;
03020          case 'x':
03021             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03022             break;
03023          case 'f':
03024             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03025             break;
03026          case 'n':
03027             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03028             break;
03029          case 'p':
03030             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03031             break;
03032          case 'r':
03033             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03034             break;
03035          default:
03036             if (isalpha(c[p->stripmsd])) {
03037                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03038                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03039             }
03040             break;
03041          }
03042          c++;
03043       }
03044       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03045 
03046       ldp_strip = 0;
03047       prilocaldialplan = p->pri->localdialplan - 1;
03048       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03049          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03050             if (prilocaldialplan == -2) {
03051                ldp_strip = strlen(p->pri->internationalprefix);
03052             }
03053             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03054          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03055             if (prilocaldialplan == -2) {
03056                ldp_strip = strlen(p->pri->nationalprefix);
03057             }
03058             prilocaldialplan = PRI_NATIONAL_ISDN;
03059          } else {
03060             prilocaldialplan = PRI_LOCAL_ISDN;
03061          }
03062       }
03063       if (l != NULL) {
03064          while (*l > '9' && *l != '*' && *l != '#') {
03065             switch (*l) {
03066             case 'U':
03067                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03068                break;
03069             case 'I':
03070                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03071                break;
03072             case 'N':
03073                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03074                break;
03075             case 'L':
03076                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03077                break;
03078             case 'S':
03079                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03080                break;
03081             case 'V':
03082                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03083                break;
03084             case 'R':
03085                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03086                break;
03087             case 'u':
03088                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03089                break;
03090             case 'e':
03091                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03092                break;
03093             case 'x':
03094                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03095                break;
03096             case 'f':
03097                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03098                break;
03099             case 'n':
03100                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03101                break;
03102             case 'p':
03103                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03104                break;
03105             case 'r':
03106                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03107                break;
03108             default:
03109                if (isalpha(*l)) {
03110                   ast_log(LOG_WARNING,
03111                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03112                      *l > 'Z' ? "NPI" : "TON", *l);
03113                }
03114                break;
03115             }
03116             l++;
03117          }
03118       }
03119       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03120          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03121       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03122          if (!strcasecmp(rr_str, "UNKNOWN"))
03123             redirect_reason = 0;
03124          else if (!strcasecmp(rr_str, "BUSY"))
03125             redirect_reason = 1;
03126          else if (!strcasecmp(rr_str, "NO_REPLY"))
03127             redirect_reason = 2;
03128          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03129             redirect_reason = 15;
03130          else
03131             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03132       } else
03133          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03134       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03135 
03136 #ifdef SUPPORT_USERUSER
03137       /* User-user info */
03138       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03139 
03140       if (useruser)
03141          pri_sr_set_useruser(sr, useruser);
03142 #endif
03143 
03144       if (pri_setup(p->pri->pri, p->call, sr)) {
03145          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n", 
03146             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03147          pri_rel(p->pri);
03148          ast_mutex_unlock(&p->lock);
03149          pri_sr_free(sr);
03150          return -1;
03151       }
03152       pri_sr_free(sr);
03153       ast_setstate(ast, AST_STATE_DIALING);
03154       pri_rel(p->pri);
03155    }
03156 #endif      
03157    ast_mutex_unlock(&p->lock);
03158    return 0;
03159 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

Definition at line 2423 of file chan_dahdi.c.

References ast_free, 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, LOG_WARNING, READ_SIZE, save_conference(), send_callerid(), and ast_channel::tech_pvt.

Referenced by dahdi_call(), and dahdi_read().

02424 {
02425    struct dahdi_pvt *p = ast->tech_pvt;
02426    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02427    if (p->cidspill) {
02428       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02429       ast_free(p->cidspill);
02430    }
02431    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02432       return -1;
02433    save_conference(p);
02434    /* Silence */
02435    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02436    if (!p->callwaitrings && p->callwaitingcallerid) {
02437       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02438       p->callwaitcas = 1;
02439       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02440    } else {
02441       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02442       p->callwaitcas = 0;
02443       p->cidlen = 2400 + READ_SIZE * 4;
02444    }
02445    p->cidpos = 0;
02446    send_callerid(p);
02447    
02448    return 0;
02449 }

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

01108                                                             {
01109    /* recall that if a field is not included here it is initialized
01110     * to 0 or equivalent
01111     */
01112    struct dahdi_chan_conf conf = {
01113 #ifdef HAVE_PRI
01114       .pri = {
01115          .nsf = PRI_NSF_NONE,
01116          .switchtype = PRI_SWITCH_NI2,
01117          .dialplan = PRI_UNKNOWN + 1,
01118          .localdialplan = PRI_NATIONAL_ISDN + 1,
01119          .nodetype = PRI_CPE,
01120 
01121          .minunused = 2,
01122          .idleext = "",
01123          .idledial = "",
01124          .internationalprefix = "",
01125          .nationalprefix = "",
01126          .localprefix = "",
01127          .privateprefix = "",
01128          .unknownprefix = "",
01129          .resetinterval = -1,
01130       },
01131 #endif
01132 #ifdef HAVE_SS7
01133       .ss7 = {
01134          .called_nai = SS7_NAI_NATIONAL,
01135          .calling_nai = SS7_NAI_NATIONAL,
01136          .internationalprefix = "",
01137          .nationalprefix = "",
01138          .subscriberprefix = "",
01139          .unknownprefix = ""
01140       },
01141 #endif
01142       .chan = {
01143          .context = "default",
01144          .cid_num = "",
01145          .cid_name = "",
01146          .mohinterpret = "default",
01147          .mohsuggest = "",
01148          .parkinglot = "",
01149          .transfertobusy = 1,
01150 
01151          .cid_signalling = CID_SIG_BELL,
01152          .cid_start = CID_START_RING,
01153          .dahditrcallerid = 0,
01154          .use_callerid = 1,
01155          .sig = -1,
01156          .outsigmod = -1,
01157 
01158          .cid_rxgain = +5.0,
01159 
01160          .tonezone = -1,
01161 
01162          .echocancel.head.tap_length = 1,
01163 
01164          .busycount = 3,
01165          .busycompare = 0,
01166          .busytonelength = 0,
01167          .busyquietlength = 0,
01168          .busyfuzziness = 0,
01169          .silencethreshold = 0,
01170 
01171          .accountcode = "",
01172 
01173          .mailbox = "",
01174 
01175 
01176          .polarityonanswerdelay = 600,
01177 
01178          .sendcalleridafter = DEFAULT_CIDRINGS,
01179       
01180          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01181          .buf_no = numbufs
01182       },
01183       .timing = {
01184          .prewinktime = -1,
01185          .preflashtime = -1,
01186          .winktime = -1,
01187          .flashtime = -1,
01188          .starttime = -1,
01189          .rxwinktime = -1,
01190          .rxflashtime = -1,
01191          .debouncetime = -1
01192       },
01193       .is_sig_auto = 1,
01194       .smdi_port = "/dev/ttyS0",
01195    };
01196 
01197    return conf;
01198 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 1503 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

01504 {
01505    if (fd > 0)
01506       close(fd);
01507 }

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

Definition at line 1516 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

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

01517 {
01518    dahdi_close(pri->fds[fd_num]);
01519    pri->fds[fd_num] = -1;
01520 }

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

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

01510 {
01511    dahdi_close(chan_pvt->subs[sub_num].dfd);
01512    chan_pvt->subs[sub_num].dfd = -1;
01513 }

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

Definition at line 2244 of file chan_dahdi.c.

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

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

02245 {
02246    int x, y, res;
02247    x = muted;
02248    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02249       y = 1;
02250       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02251       if (res)
02252          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02253    }
02254    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02255    if (res < 0)
02256       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02257    return res;
02258 }

static char* dahdi_destroy_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12429 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_destroy_channel_bynum(), RESULT_SUCCESS, and ast_cli_entry::usage.

12430 {
12431    int channel;
12432    int ret;
12433    switch (cmd) {
12434    case CLI_INIT:
12435       e->command = "dahdi destroy channel";
12436       e->usage = 
12437          "Usage: dahdi destroy channel <chan num>\n"
12438          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12439       return NULL;
12440    case CLI_GENERATE:
12441       return NULL;   
12442    }
12443    if (a->argc != 4)
12444       return CLI_SHOWUSAGE;
12445    
12446    channel = atoi(a->argv[3]);
12447    ret = dahdi_destroy_channel_bynum(channel);
12448    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12449 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

08055 {
08056    struct dahdi_pvt *tmp = NULL;
08057    struct dahdi_pvt *prev = NULL;
08058 
08059    tmp = iflist;
08060    while (tmp) {
08061       if (tmp->channel == channel) {
08062          int x = DAHDI_FLASH;
08063          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 */
08064          destroy_channel(prev, tmp, 1);
08065          ast_module_unref(ast_module_info->self);
08066          return RESULT_SUCCESS;
08067       }
08068       prev = tmp;
08069       tmp = tmp->next;
08070    }
08071    return RESULT_FAILURE;
08072 }

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

Definition at line 1611 of file chan_dahdi.c.

References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, chan, dahdi_get_index(), dahdi_pvt::dialdest, dahdi_pvt::dialing, digit_to_dtmfindex(), errno, dahdi_pvt::lock, 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_BRI, SIG_BRI_PTMP, SIG_PRI, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

01612 {
01613    struct dahdi_pvt *pvt;
01614    int idx;
01615    int dtmf = -1;
01616    
01617    pvt = chan->tech_pvt;
01618 
01619    ast_mutex_lock(&pvt->lock);
01620 
01621    idx = dahdi_get_index(chan, pvt, 0);
01622 
01623    if ((idx != SUB_REAL) || !pvt->owner)
01624       goto out;
01625 
01626 #ifdef HAVE_PRI
01627    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 
01628          && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01629       if (pvt->setup_ack) {
01630          if (!pri_grab(pvt, pvt->pri)) {
01631             pri_information(pvt->pri->pri, pvt->call, digit);
01632             pri_rel(pvt->pri);
01633          } else
01634             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01635       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01636          int res;
01637          ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01638          res = strlen(pvt->dialdest);
01639          pvt->dialdest[res++] = digit;
01640          pvt->dialdest[res] = '\0';
01641       }
01642       goto out;
01643    }
01644 #endif
01645    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01646       goto out;
01647 
01648    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01649       int res;
01650       struct dahdi_dialoperation zo = {
01651          .op = DAHDI_DIAL_OP_APPEND,
01652       };
01653 
01654       zo.dialstr[0] = 'T';
01655       zo.dialstr[1] = digit;
01656       zo.dialstr[2] = '\0';
01657       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01658          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01659       else
01660          pvt->dialing = 1;
01661    } else {
01662       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01663       pvt->dialing = 1;
01664       pvt->begindigit = digit;
01665    }
01666 
01667 out:
01668    ast_mutex_unlock(&pvt->lock);
01669 
01670    return 0;
01671 }

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

Definition at line 1673 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, chan, dahdi_get_index(), dahdi_pvt::dialing, dahdi_pvt::lock, dahdi_pvt::owner, dahdi_pvt::pulse, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

01674 {
01675    struct dahdi_pvt *pvt;
01676    int res = 0;
01677    int idx;
01678    int x;
01679    
01680    pvt = chan->tech_pvt;
01681 
01682    ast_mutex_lock(&pvt->lock);
01683    
01684    idx = dahdi_get_index(chan, pvt, 0);
01685 
01686    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
01687       goto out;
01688 
01689 #ifdef HAVE_PRI
01690    /* This means that the digit was already sent via PRI signalling */
01691    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01692          && !pvt->begindigit)
01693       goto out;
01694 #endif
01695 
01696    if (pvt->begindigit) {
01697       x = -1;
01698       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01699       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01700       pvt->dialing = 0;
01701       pvt->begindigit = 0;
01702    }
01703 
01704 out:
01705    ast_mutex_unlock(&pvt->lock);
01706 
01707    return res;
01708 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2073 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::echocanon, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

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

02074 {
02075    int res;
02076 
02077    if (p->echocanon) {
02078       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02079 
02080       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02081 
02082       if (res)
02083          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02084       else
02085          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02086    }
02087 
02088    p->echocanon = 0;
02089 }

static void dahdi_dnd ( struct dahdi_pvt dahdichan,
int  on 
) [static]

enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel

Parameters:
dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
on 1 to enable, 0 to disable
chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.

Bug:
the use of the word "channel" for those dahdichans is really confusing.

Definition at line 6517 of file chan_dahdi.c.

References ast_verb, dahdi_pvt::channel, dahdi_pvt::dnd, EVENT_FLAG_SYSTEM, and manager_event.

Referenced by dahdi_set_dnd(), and ss_thread().

06518 {
06519    /* Do not disturb */
06520    dahdichan->dnd = on;
06521    ast_verb(3, "%s DND on channel %d\n", 
06522          on? "Enabled" : "Disabled",
06523          dahdichan->channel);
06524    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06525          "Channel: DAHDI/%d\r\n"
06526          "Status: %s\r\n", dahdichan->channel,
06527          on? "enabled" : "disabled");
06528 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2024 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::digital, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::head, LOG_WARNING, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, SIG_SS7, SUB_REAL, and dahdi_pvt::subs.

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

02025 {
02026    int x;
02027    int res;
02028    if (!p)
02029       return;
02030    if (p->echocanon) {
02031       ast_debug(1, "Echo cancellation already on\n");
02032       return;
02033    }
02034    if (p->digital) {
02035       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02036       return;
02037    }
02038    if (p->echocancel.head.tap_length) {
02039       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02040          x = 1;
02041          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02042          if (res)
02043             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02044       }
02045       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02046       if (res)  {
02047          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02048       } else {
02049          p->echocanon = 1;
02050          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02051       }
02052    } else
02053       ast_debug(1, "No echo cancellation requested\n");
02054 }

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

Definition at line 5633 of file chan_dahdi.c.

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

05634 {
05635    struct dahdi_pvt *p = ast->tech_pvt;
05636    struct ast_frame *f;
05637    ast_mutex_lock(&p->lock);
05638    f = __dahdi_exception(ast);
05639    ast_mutex_unlock(&p->lock);
05640    return f;
05641 }

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

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

13320 {
13321    if (p) {
13322       switch (mode) {
13323          case TRANSFER:
13324             p->fake_event = DAHDI_EVENT_WINKFLASH;
13325             break;
13326          case HANGUP:
13327             p->fake_event = DAHDI_EVENT_ONHOOK;
13328             break;
13329          default:
13330             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
13331       }
13332    }
13333    return 0;
13334 }

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

Definition at line 4453 of file chan_dahdi.c.

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

04454 {
04455    struct dahdi_pvt *p = newchan->tech_pvt;
04456    int x;
04457    ast_mutex_lock(&p->lock);
04458    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04459    if (p->owner == oldchan) {
04460       p->owner = newchan;
04461    }
04462    for (x = 0; x < 3; x++)
04463       if (p->subs[x].owner == oldchan) {
04464          if (!x)
04465             dahdi_unlink(NULL, p, 0);
04466          p->subs[x].owner = newchan;
04467       }
04468    if (newchan->_state == AST_STATE_RINGING) 
04469       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04470    update_conf(p);
04471    ast_mutex_unlock(&p->lock);
04472    return 0;
04473 }

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

Definition at line 4030 of file chan_dahdi.c.

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

04031 {
04032    struct dahdi_pvt *p = chan->tech_pvt;
04033    
04034    if (!strcasecmp(data, "rxgain")) {
04035       ast_mutex_lock(&p->lock);
04036       snprintf(buf, len, "%f", p->rxgain);
04037       ast_mutex_unlock(&p->lock);   
04038    } else if (!strcasecmp(data, "txgain")) {
04039       ast_mutex_lock(&p->lock);
04040       snprintf(buf, len, "%f", p->txgain);
04041       ast_mutex_unlock(&p->lock);   
04042    } else {
04043       ast_copy_string(buf, "", len);
04044    }
04045    return 0;
04046 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 303 of file chan_dahdi.c.

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

00304 {
00305    int j;
00306    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00307       return -1;
00308    return j;
00309 }

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

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

01318 {
01319    int res;
01320    if (p->subs[SUB_REAL].owner == ast)
01321       res = 0;
01322    else if (p->subs[SUB_CALLWAIT].owner == ast)
01323       res = 1;
01324    else if (p->subs[SUB_THREEWAY].owner == ast)
01325       res = 2;
01326    else {
01327       res = -1;
01328       if (!nullok)
01329          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01330    }
01331    return res;
01332 }

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

Definition at line 4614 of file chan_dahdi.c.

References ast_async_goto(), ast_channel_lock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_debug, ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_NULL, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, dahdi_pvt::callprogress, CALLPROGRESS_FAX, 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, dahdi_pvt::lock, LOG_NOTICE, ast_channel::macrocontext, ast_channel::name, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

Referenced by dahdi_handle_event(), and dahdi_read().

04615 {
04616    struct dahdi_pvt *p = ast->tech_pvt;
04617    struct ast_frame *f = *dest;
04618 
04619    ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
04620 
04621    if (p->confirmanswer) {
04622       ast_debug(1, "Confirm answer on %s!\n", ast->name);
04623       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
04624          of a DTMF digit */
04625       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04626       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04627       *dest = &p->subs[idx].f;
04628       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
04629       p->confirmanswer = 0;
04630    } else if (p->callwaitcas) {
04631       if ((f->subclass == 'A') || (f->subclass == 'D')) {
04632          ast_debug(1, "Got some DTMF, but it's for the CAS\n");
04633          if (p->cidspill)
04634             ast_free(p->cidspill);
04635          send_cwcidspill(p);
04636       }
04637       p->callwaitcas = 0;
04638       p->subs[idx].f.frametype = AST_FRAME_NULL;
04639       p->subs[idx].f.subclass = 0;
04640       *dest = &p->subs[idx].f;
04641    } else if (f->subclass == 'f') {
04642       /* Fax tone -- Handle and return NULL */
04643       if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
04644          p->faxhandled = 1;
04645          if (strcmp(ast->exten, "fax")) {
04646             const char *target_context = S_OR(ast->macrocontext, ast->context);
04647 
04648             /* We need to unlock 'ast' here because ast_exists_extension has the
04649              * potential to start autoservice on the channel. Such action is prone
04650              * to deadlock.
04651              */
04652             ast_mutex_unlock(&p->lock);
04653             ast_channel_unlock(ast);
04654             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
04655                ast_channel_lock(ast);
04656                ast_mutex_lock(&p->lock);
04657                ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
04658                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
04659                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
04660                if (ast_async_goto(ast, target_context, "fax", 1))
04661                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
04662             } else {
04663                ast_channel_lock(ast);
04664                ast_mutex_lock(&p->lock);
04665                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
04666             }
04667          } else {
04668             ast_debug(1, "Already in a fax extension, not redirecting\n");
04669          }
04670       } else {
04671          ast_debug(1, "Fax already handled\n");
04672       }
04673       dahdi_confmute(p, 0);
04674       p->subs[idx].f.frametype = AST_FRAME_NULL;
04675       p->subs[idx].f.subclass = 0;
04676       *dest = &p->subs[idx].f;
04677    }
04678 }

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

Definition at line 4691 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_trylock, ast_channel_unlock, 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_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), 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_verb, attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, chan, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, 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_get_event(), dahdi_get_index(), dahdi_handle_dtmfup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_ring_phone(), dahdi_set_hook(), dahdi_train_ec(), dahdi_pvt::dahditrcallerid, ast_frame::data, ast_frame::datalen, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, 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, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::inalarm, dahdi_subchannel::inthreeway, 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, 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, ast_frame::ptr, 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_BRI, SIG_BRI_PTMP, 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, SIG_SS7, 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(), update_conf(), and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

04692 {
04693    int res, x;
04694    int idx, mysig;
04695    char *c;
04696    struct dahdi_pvt *p = ast->tech_pvt;
04697    pthread_t threadid;
04698    struct ast_channel *chan;
04699    struct ast_frame *f;
04700 
04701    idx = dahdi_get_index(ast, p, 0);
04702    mysig = p->sig;
04703    if (p->outsigmod > -1)
04704       mysig = p->outsigmod;
04705    p->subs[idx].f.frametype = AST_FRAME_NULL;
04706    p->subs[idx].f.subclass = 0;
04707    p->subs[idx].f.datalen = 0;
04708    p->subs[idx].f.samples = 0;
04709    p->subs[idx].f.mallocd = 0;
04710    p->subs[idx].f.offset = 0;
04711    p->subs[idx].f.src = "dahdi_handle_event";
04712    p->subs[idx].f.data.ptr = NULL;
04713    f = &p->subs[idx].f;
04714 
04715    if (idx < 0)
04716       return &p->subs[idx].f;
04717    if (p->fake_event) {
04718       res = p->fake_event;
04719       p->fake_event = 0;
04720    } else
04721       res = dahdi_get_event(p->subs[idx].dfd);
04722 
04723    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
04724 
04725    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
04726       p->pulsedial =  (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
04727       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
04728 #ifdef HAVE_PRI
04729       if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
04730          /* absorb event */
04731       } else {
04732 #endif
04733          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
04734          p->subs[idx].f.subclass = res & 0xff;
04735 #ifdef HAVE_PRI
04736       }
04737 #endif
04738       dahdi_handle_dtmfup(ast, idx, &f);
04739       return f;
04740    }
04741 
04742    if (res & DAHDI_EVENT_DTMFDOWN) {
04743       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
04744       /* Mute conference */
04745       dahdi_confmute(p, 1);
04746       p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
04747       p->subs[idx].f.subclass = res & 0xff;
04748       return &p->subs[idx].f;
04749    }
04750 
04751    switch (res) {
04752       case DAHDI_EVENT_EC_DISABLED:
04753          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
04754          p->echocanon = 0;
04755          break;
04756       case DAHDI_EVENT_BITSCHANGED:
04757          ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
04758       case DAHDI_EVENT_PULSE_START:
04759          /* Stop tone if there's a pulse start and the PBX isn't started */
04760          if (!ast->pbx)
04761             tone_zone_play_tone(p->subs[idx].dfd, -1);
04762          break;   
04763       case DAHDI_EVENT_DIALCOMPLETE:
04764          if (p->inalarm) break;
04765          if ((p->radio || (p->oprmode < 0))) break;
04766          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
04767             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
04768             return NULL;
04769          }
04770          if (!x) { /* if not still dialing in driver */
04771             dahdi_enable_ec(p);
04772             if (p->echobreak) {
04773                dahdi_train_ec(p);
04774                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
04775                p->dop.op = DAHDI_DIAL_OP_REPLACE;
04776                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
04777                p->echobreak = 0;
04778             } else {
04779                p->dialing = 0;
04780                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
04781                   /* if thru with dialing after offhook */
04782                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
04783                      ast_setstate(ast, AST_STATE_UP);
04784                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04785                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04786                      break;
04787                   } else { /* if to state wait for offhook to dial rest */
04788                      /* we now wait for off hook */
04789                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
04790                   }
04791                }
04792                if (ast->_state == AST_STATE_DIALING) {
04793                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
04794                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
04795                   } 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)))) {
04796                      ast_setstate(ast, AST_STATE_RINGING);
04797                   } else if (!p->answeronpolarityswitch) {
04798                      ast_setstate(ast, AST_STATE_UP);
04799                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04800                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
04801                      /* If aops=0 and hops=1, this is necessary */
04802                      p->polarity = POLARITY_REV;
04803                   } else {
04804                      /* Start clean, so we can catch the change to REV polarity when party answers */
04805                      p->polarity = POLARITY_IDLE;
04806                   }
04807                }
04808             }
04809          }
04810          break;
04811       case DAHDI_EVENT_ALARM:
04812 #ifdef HAVE_PRI
04813          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04814             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
04815                /* T309 is not enabled : hangup calls when alarm occurs */
04816                if (p->call) {
04817                   if (p->pri && p->pri->pri) {
04818                      if (!pri_grab(p, p->pri)) {
04819                         pri_hangup(p->pri->pri, p->call, -1);
04820                         pri_destroycall(p->pri->pri, p->call);
04821                         p->call = NULL;
04822                         pri_rel(p->pri);
04823                      } else
04824                         ast_log(LOG_WARNING, "Failed to grab PRI!\n");
04825                   } else
04826                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
04827                }
04828                if (p->owner)
04829                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
04830             }
04831          }
04832          if (p->bearer)
04833             p->bearer->inalarm = 1;
04834          else
04835 #endif
04836          p->inalarm = 1;
04837          res = get_alarms(p);
04838          handle_alarms(p, res);
04839 #ifdef HAVE_PRI
04840          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
04841             /* fall through intentionally */
04842          } else {
04843             break;
04844          }
04845 #endif
04846 #ifdef HAVE_SS7
04847          if (p->sig == SIG_SS7)
04848             break;
04849 #endif
04850       case DAHDI_EVENT_ONHOOK:
04851          if (p->radio) {
04852             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04853             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
04854             break;
04855          }
04856          if (p->oprmode < 0)
04857          {
04858             if (p->oprmode != -1) break;
04859             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04860             {
04861                /* Make sure it starts ringing */
04862                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04863                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
04864                save_conference(p->oprpeer);
04865                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
04866             }
04867             break;
04868          }
04869          switch (p->sig) {
04870          case SIG_FXOLS:
04871          case SIG_FXOGS:
04872          case SIG_FXOKS:
04873             p->onhooktime = time(NULL);
04874             p->msgstate = -1;
04875             /* Check for some special conditions regarding call waiting */
04876             if (idx == SUB_REAL) {
04877                /* The normal line was hung up */
04878                if (p->subs[SUB_CALLWAIT].owner) {
04879                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
04880                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04881                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
04882                   unalloc_sub(p, SUB_CALLWAIT); 
04883 #if 0
04884                   p->subs[idx].needanswer = 0;
04885                   p->subs[idx].needringing = 0;
04886 #endif                  
04887                   p->callwaitingrepeat = 0;
04888                   p->cidcwexpire = 0;
04889                   p->owner = NULL;
04890                   /* Don't start streaming audio yet if the incoming call isn't up yet */
04891                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
04892                      p->dialing = 1;
04893                   dahdi_ring_phone(p);
04894                } else if (p->subs[SUB_THREEWAY].owner) {
04895                   unsigned int mssinceflash;
04896                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
04897                      the private structure -- not especially easy or clean */
04898                   while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
04899                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
04900                      DLA_UNLOCK(&p->lock);
04901                      CHANNEL_DEADLOCK_AVOIDANCE(ast);
04902                      /* We can grab ast and p in that order, without worry.  We should make sure
04903                         nothing seriously bad has happened though like some sort of bizarre double
04904                         masquerade! */
04905                      DLA_LOCK(&p->lock);
04906                      if (p->owner != ast) {
04907                         ast_log(LOG_WARNING, "This isn't good...\n");
04908                         return NULL;
04909                      }
04910                   }
04911                   if (!p->subs[SUB_THREEWAY].owner) {
04912                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
04913                      return NULL;
04914                   }
04915                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
04916                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
04917                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
04918                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on 
04919                         hanging up.  Hangup both channels now */
04920                      if (p->subs[SUB_THREEWAY].owner)
04921                         ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
04922                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04923                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
04924                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04925                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
04926                      if (p->transfer) {
04927                         /* In any case this isn't a threeway call anymore */
04928                         p->subs[SUB_REAL].inthreeway = 0;
04929                         p->subs[SUB_THREEWAY].inthreeway = 0;
04930                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
04931                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
04932                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04933                            /* Swap subs and dis-own channel */
04934                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
04935                            p->owner = NULL;
04936                            /* Ring the phone */
04937                            dahdi_ring_phone(p);
04938                         } else {
04939                            if ((res = attempt_transfer(p)) < 0) {
04940                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04941                               if (p->subs[SUB_THREEWAY].owner)
04942                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04943                            } else if (res) {
04944                               /* Don't actually hang up at this point */
04945                               if (p->subs[SUB_THREEWAY].owner)
04946                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04947                               break;
04948                            }
04949                         }
04950                      } else {
04951                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
04952                         if (p->subs[SUB_THREEWAY].owner)
04953                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04954                      }
04955                   } else {
04956                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
04957                      /* Swap subs and dis-own channel */
04958                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
04959                      p->owner = NULL;
04960                      /* Ring the phone */
04961                      dahdi_ring_phone(p);
04962                   }
04963                }
04964             } else {
04965                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
04966             }
04967             /* Fall through */
04968          default:
04969             dahdi_disable_ec(p);
04970             return NULL;
04971          }
04972          break;
04973       case DAHDI_EVENT_RINGOFFHOOK:
04974          if (p->inalarm) break;
04975          if (p->oprmode < 0)
04976          {
04977             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
04978             {
04979                /* Make sure it stops ringing */
04980                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
04981                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
04982                restore_conference(p->oprpeer);
04983             }
04984             break;
04985          }
04986          if (p->radio)
04987          {
04988             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
04989             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
04990             break;
04991          }
04992          /* for E911, its supposed to wait for offhook then dial
04993             the second half of the dial string */
04994          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
04995             c = strchr(p->dialdest, '/');
04996             if (c)
04997                c++;
04998             else
04999                c = p->dialdest;
05000             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
05001             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
05002             if (strlen(p->dop.dialstr) > 4) {
05003                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
05004                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
05005                p->echorest[sizeof(p->echorest) - 1] = '\0';
05006                p->echobreak = 1;
05007                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
05008             } else
05009                p->echobreak = 0;
05010             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
05011                int saveerr = errno;
05012 
05013                x = DAHDI_ONHOOK;
05014                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05015                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
05016                return NULL;
05017                }
05018             p->dialing = 1;
05019             return &p->subs[idx].f;
05020          }
05021          switch (p->sig) {
05022          case SIG_FXOLS:
05023          case SIG_FXOGS:
05024          case SIG_FXOKS:
05025             switch (ast->_state) {
05026             case AST_STATE_RINGING:
05027                dahdi_enable_ec(p);
05028                dahdi_train_ec(p);
05029                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05030                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05031                /* Make sure it stops ringing */
05032                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05033                ast_debug(1, "channel %d answered\n", p->channel);
05034                if (p->cidspill) {
05035                   /* Cancel any running CallerID spill */
05036                   ast_free(p->cidspill);
05037                   p->cidspill = NULL;
05038                }
05039                p->dialing = 0;
05040                p->callwaitcas = 0;
05041                if (p->confirmanswer) {
05042                   /* Ignore answer if "confirm answer" is enabled */
05043                   p->subs[idx].f.frametype = AST_FRAME_NULL;
05044                   p->subs[idx].f.subclass = 0;
05045                } else if (!ast_strlen_zero(p->dop.dialstr)) {
05046                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
05047                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05048                   if (res < 0) {
05049                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05050                      p->dop.dialstr[0] = '\0';
05051                      return NULL;
05052                   } else {
05053                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
05054                      p->subs[idx].f.frametype = AST_FRAME_NULL;
05055                      p->subs[idx].f.subclass = 0;
05056                      p->dialing = 1;
05057                   }
05058                   p->dop.dialstr[0] = '\0';
05059                   ast_setstate(ast, AST_STATE_DIALING);
05060                } else
05061                   ast_setstate(ast, AST_STATE_UP);
05062                return &p->subs[idx].f;
05063             case AST_STATE_DOWN:
05064                ast_setstate(ast, AST_STATE_RING);
05065                ast->rings = 1;
05066                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05067                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
05068                ast_debug(1, "channel %d picked up\n", p->channel);
05069                return &p->subs[idx].f;
05070             case AST_STATE_UP:
05071                /* Make sure it stops ringing */
05072                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
05073                /* Okay -- probably call waiting*/
05074                if (ast_bridged_channel(p->owner))
05075                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
05076                p->subs[idx].needunhold = 1;
05077                break;
05078             case AST_STATE_RESERVED:
05079                /* Start up dialtone */
05080                if (has_voicemail(p))
05081                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
05082                else
05083                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
05084                break;
05085             default:
05086                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
05087             }
05088             break;
05089          case SIG_FXSLS:
05090          case SIG_FXSGS:
05091          case SIG_FXSKS:
05092             if (ast->_state == AST_STATE_RING) {
05093                p->ringt = p->ringt_base;
05094             }
05095 
05096             /* If we get a ring then we cannot be in 
05097              * reversed polarity. So we reset to idle */
05098             ast_debug(1, "Setting IDLE polarity due "
05099                "to ring. Old polarity was %d\n", 
05100                p->polarity);
05101             p->polarity = POLARITY_IDLE;
05102 
05103             /* Fall through */
05104          case SIG_EM:
05105          case SIG_EM_E1:
05106          case SIG_EMWINK:
05107          case SIG_FEATD:
05108          case SIG_FEATDMF:
05109          case SIG_FEATDMF_TA:
05110          case SIG_E911:
05111          case SIG_FGC_CAMA:
05112          case SIG_FGC_CAMAMF:
05113          case SIG_FEATB:
05114          case SIG_SF:
05115          case SIG_SFWINK:
05116          case SIG_SF_FEATD:
05117          case SIG_SF_FEATDMF:
05118          case SIG_SF_FEATB:
05119             if (ast->_state == AST_STATE_PRERING)
05120                ast_setstate(ast, AST_STATE_RING);
05121             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
05122                ast_debug(1, "Ring detected\n");
05123                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05124                p->subs[idx].f.subclass = AST_CONTROL_RING;
05125             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
05126                ast_debug(1, "Line answered\n");
05127                if (p->confirmanswer) {
05128                   p->subs[idx].f.frametype = AST_FRAME_NULL;
05129                   p->subs[idx].f.subclass = 0;
05130                } else {
05131                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05132                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05133                   ast_setstate(ast, AST_STATE_UP);
05134                }
05135             } else if (ast->_state != AST_STATE_RING)
05136                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
05137             break;
05138          default:
05139             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
05140          }
05141          break;
05142       case DAHDI_EVENT_RINGBEGIN:
05143          switch (p->sig) {
05144          case SIG_FXSLS:
05145          case SIG_FXSGS:
05146          case SIG_FXSKS:
05147             if (ast->_state == AST_STATE_RING) {
05148                p->ringt = p->ringt_base;
05149             }
05150             break;
05151          }
05152          break;
05153       case DAHDI_EVENT_RINGEROFF:
05154          if (p->inalarm) break;
05155          if ((p->radio || (p->oprmode < 0))) break;
05156          ast->rings++;
05157          if ((ast->rings > p->cidrings) && (p->cidspill)) {
05158             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
05159             ast_free(p->cidspill);
05160             p->cidspill = NULL;
05161             p->callwaitcas = 0;
05162          }
05163          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05164          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05165          break;
05166       case DAHDI_EVENT_RINGERON:
05167          break;
05168       case DAHDI_EVENT_NOALARM:
05169          p->inalarm = 0;
05170 #ifdef HAVE_PRI
05171          /* Extremely unlikely but just in case */
05172          if (p->bearer)
05173             p->bearer->inalarm = 0;
05174 #endif            
05175          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
05176          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
05177                         "Channel: %d\r\n", p->channel);
05178          break;
05179       case DAHDI_EVENT_WINKFLASH:
05180          if (p->inalarm) break;
05181          if (p->radio) break;
05182          if (p->oprmode < 0) break;
05183          if (p->oprmode > 1)
05184          {
05185             struct dahdi_params par;
05186 
05187             memset(&par, 0, sizeof(par));
05188             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
05189             {
05190                if (!par.rxisoffhook)
05191                {
05192                   /* Make sure it stops ringing */
05193                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05194                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
05195                   save_conference(p);
05196                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05197                }
05198             }
05199             break;
05200          }
05201          /* Remember last time we got a flash-hook */
05202          p->flashtime = ast_tvnow();
05203          switch (mysig) {
05204          case SIG_FXOLS:
05205          case SIG_FXOGS:
05206          case SIG_FXOKS:
05207             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
05208                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
05209             p->callwaitcas = 0;
05210 
05211             if (idx != SUB_REAL) {
05212                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
05213                goto winkflashdone;
05214             }
05215             
05216             if (p->subs[SUB_CALLWAIT].owner) {
05217                /* Swap to call-wait */
05218                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
05219                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
05220                p->owner = p->subs[SUB_REAL].owner;
05221                ast_debug(1, "Making %s the new owner\n", p->owner->name);
05222                if (p->owner->_state == AST_STATE_RINGING) {
05223                   ast_setstate(p->owner, AST_STATE_UP);
05224                   p->subs[SUB_REAL].needanswer = 1;
05225                }
05226                p->callwaitingrepeat = 0;
05227                p->cidcwexpire = 0;
05228                /* Start music on hold if appropriate */
05229                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
05230                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
05231                      S_OR(p->mohsuggest, NULL),
05232                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05233                }
05234                p->subs[SUB_CALLWAIT].needhold = 1;
05235                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05236                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
05237                      S_OR(p->mohsuggest, NULL),
05238                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05239                }
05240                p->subs[SUB_REAL].needunhold = 1;
05241             } else if (!p->subs[SUB_THREEWAY].owner) {
05242                if (!p->threewaycalling) {
05243                   /* Just send a flash if no 3-way calling */
05244                   p->subs[SUB_REAL].needflash = 1;
05245                   goto winkflashdone;
05246                } else if (!check_for_conference(p)) {
05247                   char cid_num[256];
05248                   char cid_name[256];
05249 
05250                   cid_num[0] = 0;
05251                   cid_name[0] = 0;
05252                   if (p->dahditrcallerid && p->owner) {
05253                      if (p->owner->cid.cid_num)
05254                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
05255                      if (p->owner->cid.cid_name)
05256                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
05257                   }
05258                   /* XXX This section needs much more error checking!!! XXX */
05259                   /* Start a 3-way call if feasible */
05260                   if (!((ast->pbx) ||
05261                         (ast->_state == AST_STATE_UP) ||
05262                         (ast->_state == AST_STATE_RING))) {
05263                      ast_debug(1, "Flash when call not up or ringing\n");
05264                      goto winkflashdone;
05265                   }
05266                   if (alloc_sub(p, SUB_THREEWAY)) {
05267                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
05268                      goto winkflashdone;
05269                   }
05270                   /* Make new channel */
05271                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
05272                   if (p->dahditrcallerid) {
05273                      if (!p->origcid_num)
05274                         p->origcid_num = ast_strdup(p->cid_num);
05275                      if (!p->origcid_name)
05276                         p->origcid_name = ast_strdup(p->cid_name);
05277                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
05278                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
05279                   }
05280                   /* Swap things around between the three-way and real call */
05281                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
05282                   /* Disable echo canceller for better dialing */
05283                   dahdi_disable_ec(p);
05284                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
05285                   if (res)
05286                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
05287                   p->owner = chan;
05288                   if (!chan) {
05289                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
05290                   } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
05291                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
05292                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
05293                      dahdi_enable_ec(p);
05294                      ast_hangup(chan);
05295                   } else {
05296                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05297                      int way3bridge = 0, cdr3way = 0;
05298                      
05299                      if (!other) {
05300                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05301                      } else
05302                         way3bridge = 1;
05303                      
05304                      if (p->subs[SUB_THREEWAY].owner->cdr)
05305                         cdr3way = 1;
05306                      
05307                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
05308 
05309                      /* Start music on hold if appropriate */
05310                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05311                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
05312                            S_OR(p->mohsuggest, NULL),
05313                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
05314                      }
05315                      p->subs[SUB_THREEWAY].needhold = 1;
05316                   }
05317                }
05318             } else {
05319                /* Already have a 3 way call */
05320                if (p->subs[SUB_THREEWAY].inthreeway) {
05321                   /* Call is already up, drop the last person */
05322                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
05323                   /* If the primary call isn't answered yet, use it */
05324                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
05325                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
05326                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05327                      p->owner = p->subs[SUB_REAL].owner;
05328                   }
05329                   /* Drop the last call and stop the conference */
05330                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
05331                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05332                   p->subs[SUB_REAL].inthreeway = 0;
05333                   p->subs[SUB_THREEWAY].inthreeway = 0;
05334                } else {
05335                   /* Lets see what we're up to */
05336                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
05337                       (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
05338                      int otherindex = SUB_THREEWAY;
05339                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
05340                      int way3bridge = 0, cdr3way = 0;
05341                      
05342                      if (!other) {
05343                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
05344                      } else
05345                         way3bridge = 1;
05346                      
05347                      if (p->subs[SUB_THREEWAY].owner->cdr)
05348                         cdr3way = 1;
05349 
05350                      ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
05351                      /* Put them in the threeway, and flip */
05352                      p->subs[SUB_THREEWAY].inthreeway = 1;
05353                      p->subs[SUB_REAL].inthreeway = 1;
05354                      if (ast->_state == AST_STATE_UP) {
05355                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
05356                         otherindex = SUB_REAL;
05357                      }
05358                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
05359                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
05360                      p->subs[otherindex].needunhold = 1;
05361                      p->owner = p->subs[SUB_REAL].owner;
05362                      if (ast->_state == AST_STATE_RINGING) {
05363                         ast_debug(1, "Enabling ringtone on real and threeway\n");
05364                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05365                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05366                      }
05367                   } else {
05368                      ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
05369                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05370                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05371                      p->owner = p->subs[SUB_REAL].owner;
05372                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
05373                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05374                      p->subs[SUB_REAL].needunhold = 1;
05375                      dahdi_enable_ec(p);
05376                   }
05377                      
05378                }
05379             }
05380          winkflashdone:              
05381             update_conf(p);
05382             break;
05383          case SIG_EM:
05384          case SIG_EM_E1:
05385          case SIG_EMWINK:
05386          case SIG_FEATD:
05387          case SIG_SF:
05388          case SIG_SFWINK:
05389          case SIG_SF_FEATD:
05390          case SIG_FXSLS:
05391          case SIG_FXSGS:
05392             if (option_debug) {
05393                if (p->dialing)
05394                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
05395                else
05396                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
05397             }
05398             break;
05399          case SIG_FEATDMF_TA:
05400             switch (p->whichwink) {
05401             case 0:
05402                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05403                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
05404                break;
05405             case 1:
05406                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
05407                break;
05408             case 2:
05409                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
05410                return NULL;
05411             }
05412             p->whichwink++;
05413             /* Fall through */
05414          case SIG_FEATDMF:
05415          case SIG_E911:
05416          case SIG_FGC_CAMAMF:
05417          case SIG_FGC_CAMA:
05418          case SIG_FEATB:
05419          case SIG_SF_FEATDMF:
05420          case SIG_SF_FEATB:
05421             /* FGD MF *Must* wait for wink */
05422             if (!ast_strlen_zero(p->dop.dialstr)) {
05423                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05424                if (res < 0) {
05425                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05426                   p->dop.dialstr[0] = '\0';
05427                   return NULL;
05428                } else 
05429                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05430             }
05431             p->dop.dialstr[0] = '\0';
05432             break;
05433          default:
05434             ast_log(LOG_WARNING, "Don't know how to handle ring/off hoook for signalling %d\n", p->sig);
05435          }
05436          break;
05437       case DAHDI_EVENT_HOOKCOMPLETE:
05438          if (p->inalarm) break;
05439          if ((p->radio || (p->oprmode < 0))) break;
05440          switch (mysig) {
05441          case SIG_FXSLS:  /* only interesting for FXS */
05442          case SIG_FXSGS:
05443          case SIG_FXSKS:
05444          case SIG_EM:
05445          case SIG_EM_E1:
05446          case SIG_EMWINK:
05447          case SIG_FEATD:
05448          case SIG_SF:
05449          case SIG_SFWINK:
05450          case SIG_SF_FEATD:
05451             if (!ast_strlen_zero(p->dop.dialstr)) {
05452                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05453                if (res < 0) {
05454                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
05455                   p->dop.dialstr[0] = '\0';
05456                   return NULL;
05457                } else 
05458                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
05459             }
05460             p->dop.dialstr[0] = '\0';
05461             p->dop.op = DAHDI_DIAL_OP_REPLACE;
05462             break;
05463          case SIG_FEATDMF:
05464          case SIG_FEATDMF_TA:
05465          case SIG_E911:
05466          case SIG_FGC_CAMA:
05467          case SIG_FGC_CAMAMF:
05468          case SIG_FEATB:
05469          case SIG_SF_FEATDMF:
05470          case SIG_SF_FEATB:
05471             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
05472             break;
05473          default:
05474             break;
05475          }
05476          break;
05477       case DAHDI_EVENT_POLARITY:
05478          /*
05479           * If we get a Polarity Switch event, check to see
05480           * if we should change the polarity state and
05481           * mark the channel as UP or if this is an indication
05482           * of remote end disconnect.
05483           */
05484          if (p->polarity == POLARITY_IDLE) {
05485             p->polarity = POLARITY_REV;
05486             if (p->answeronpolarityswitch &&
05487                 ((ast->_state == AST_STATE_DIALING) ||
05488                 (ast->_state == AST_STATE_RINGING))) {
05489                ast_debug(1, "Answering on polarity switch!\n");
05490                ast_setstate(p->owner, AST_STATE_UP);
05491                if (p->hanguponpolarityswitch) {
05492                   p->polaritydelaytv = ast_tvnow();
05493                }
05494             } else
05495                ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
05496 
05497          } 
05498          /* Removed else statement from here as it was preventing hangups from ever happening*/
05499          /* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
05500          if (p->hanguponpolarityswitch &&
05501             (p->polarityonanswerdelay > 0) &&
05502                 (p->polarity == POLARITY_REV) &&
05503             ((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
05504                                 /* Added log_debug information below to provide a better indication of what is going on */
05505             ast_debug(1, "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) );
05506          
05507             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
05508                ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
05509                ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
05510                p->polarity = POLARITY_IDLE;
05511             } else
05512                ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
05513 
05514          } else {
05515             p->polarity = POLARITY_IDLE;
05516             ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
05517          }
05518                         /* Added more log_debug information below to provide a better indication of what is going on */
05519          ast_debug(1, "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) );
05520          break;
05521       default:
05522          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
05523    }
05524    return &p->subs[idx].f;
05525 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 3391 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_debug, ast_dsp_free(), ast_dsp_set_digitmode(), ast_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_verb, 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, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_pvt::muting, 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, 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, dahdi_pvt::rlt, S_OR, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SS7, dahdi_pvt::span, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), and update_conf().

Referenced by pri_dchannel().

03392 {
03393    int res;
03394    int idx,x, law;
03395    /*static int restore_gains(struct dahdi_pvt *p);*/
03396    struct dahdi_pvt *p = ast->tech_pvt;
03397    struct dahdi_pvt *tmp = NULL;
03398    struct dahdi_pvt *prev = NULL;
03399    struct dahdi_params par;
03400 
03401    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
03402    if (!ast->tech_pvt) {
03403       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
03404       return 0;
03405    }
03406    
03407    ast_mutex_lock(&p->lock);
03408    
03409    idx = dahdi_get_index(ast, p, 1);
03410 
03411    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03412       x = 1;
03413       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03414    }
03415 
03416    x = 0;
03417    dahdi_confmute(p, 0);
03418    p->muting = 0;
03419    restore_gains(p);
03420    if (p->origcid_num) {
03421       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
03422       ast_free(p->origcid_num);
03423       p->origcid_num = NULL;
03424    }  
03425    if (p->origcid_name) {
03426       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
03427       ast_free(p->origcid_name);
03428       p->origcid_name = NULL;
03429    }  
03430    if (p->dsp)
03431       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
03432    p->exten[0] = '\0';
03433 
03434    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
03435       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
03436    p->ignoredtmf = 0;
03437    
03438    if (idx > -1) {
03439       /* Real channel, do some fixup */
03440       p->subs[idx].owner = NULL;
03441       p->subs[idx].needanswer = 0;
03442       p->subs[idx].needflash = 0;
03443       p->subs[idx].needringing = 0;
03444       p->subs[idx].needbusy = 0;
03445       p->subs[idx].needcongestion = 0;
03446       p->subs[idx].linear = 0;
03447       p->subs[idx].needcallerid = 0;
03448       p->polarity = POLARITY_IDLE;
03449       dahdi_setlinear(p->subs[idx].dfd, 0);
03450       if (idx == SUB_REAL) {
03451          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
03452             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
03453             if (p->subs[SUB_CALLWAIT].inthreeway) {
03454                /* We had flipped over to answer a callwait and now it's gone */
03455                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
03456                /* Move to the call-wait, but un-own us until they flip back. */
03457                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03458                unalloc_sub(p, SUB_CALLWAIT);
03459                p->owner = NULL;
03460             } else {
03461                /* The three way hung up, but we still have a call wait */
03462                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
03463                swap_subs(p, SUB_THREEWAY, SUB_REAL);
03464                unalloc_sub(p, SUB_THREEWAY);
03465                if (p->subs[SUB_REAL].inthreeway) {
03466                   /* This was part of a three way call.  Immediately make way for
03467                      another call */
03468                   ast_debug(1, "Call was complete, setting owner to former third call\n");
03469                   p->owner = p->subs[SUB_REAL].owner;
03470                } else {
03471                   /* This call hasn't been completed yet...  Set owner to NULL */
03472                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03473                   p->owner = NULL;
03474                }
03475                p->subs[SUB_REAL].inthreeway = 0;
03476             }
03477          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
03478             /* Move to the call-wait and switch back to them. */
03479             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
03480             unalloc_sub(p, SUB_CALLWAIT);
03481             p->owner = p->subs[SUB_REAL].owner;
03482             if (p->owner->_state != AST_STATE_UP)
03483                p->subs[SUB_REAL].needanswer = 1;
03484             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
03485                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
03486          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
03487             swap_subs(p, SUB_THREEWAY, SUB_REAL);
03488             unalloc_sub(p, SUB_THREEWAY);
03489             if (p->subs[SUB_REAL].inthreeway) {
03490                /* This was part of a three way call.  Immediately make way for
03491                   another call */
03492                ast_debug(1, "Call was complete, setting owner to former third call\n");
03493                p->owner = p->subs[SUB_REAL].owner;
03494             } else {
03495                /* This call hasn't been completed yet...  Set owner to NULL */
03496                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
03497                p->owner = NULL;
03498             }
03499             p->subs[SUB_REAL].inthreeway = 0;
03500          }
03501       } else if (idx == SUB_CALLWAIT) {
03502          /* Ditch the holding callwait call, and immediately make it availabe */
03503          if (p->subs[SUB_CALLWAIT].inthreeway) {
03504             /* This is actually part of a three way, placed on hold.  Place the third part
03505                on music on hold now */
03506             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
03507                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD, 
03508                   S_OR(p->mohsuggest, NULL),
03509                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03510             }
03511             p->subs[SUB_THREEWAY].inthreeway = 0;
03512             /* Make it the call wait now */
03513             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
03514             unalloc_sub(p, SUB_THREEWAY);
03515          } else
03516             unalloc_sub(p, SUB_CALLWAIT);
03517       } else if (idx == SUB_THREEWAY) {
03518          if (p->subs[SUB_CALLWAIT].inthreeway) {
03519             /* The other party of the three way call is currently in a call-wait state.
03520                Start music on hold for them, and take the main guy out of the third call */
03521             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
03522                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD, 
03523                   S_OR(p->mohsuggest, NULL),
03524                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
03525             }
03526             p->subs[SUB_CALLWAIT].inthreeway = 0;
03527          }
03528          p->subs[SUB_REAL].inthreeway = 0;
03529          /* If this was part of a three way call index, let us make
03530             another three way call */
03531          unalloc_sub(p, SUB_THREEWAY);
03532       } else {
03533          /* This wasn't any sort of call, but how are we an index? */
03534          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
03535       }
03536    }
03537 
03538    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
03539       p->owner = NULL;
03540       p->ringt = 0;
03541       p->distinctivering = 0;
03542       p->confirmanswer = 0;
03543       p->cidrings = 1;
03544       p->outgoing = 0;
03545       p->digital = 0;
03546       p->faxhandled = 0;
03547       p->pulsedial = 0;
03548       p->onhooktime = time(NULL);
03549 #if defined(HAVE_PRI) || defined(HAVE_SS7)
03550       p->proceeding = 0;
03551       p->dialing = 0;
03552       p->progress = 0;
03553       p->alerting = 0;
03554       p->setup_ack = 0;
03555       p->rlt = 0;
03556 #endif      
03557       if (p->dsp) {
03558          ast_dsp_free(p->dsp);
03559          p->dsp = NULL;
03560       }
03561 
03562       law = DAHDI_LAW_DEFAULT;
03563       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
03564       if (res < 0) 
03565          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
03566       /* Perform low level hangup if no owner left */
03567 #ifdef HAVE_SS7
03568       if (p->ss7) {
03569          if (p->ss7call) {
03570             if (!ss7_grab(p, p->ss7)) {
03571                if (!p->alreadyhungup) {
03572                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
03573                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03574 
03575                   if (cause) {
03576                      if (atoi(cause))
03577                         icause = atoi(cause);
03578                   }
03579                   isup_rel(p->ss7->ss7, p->ss7call, icause);
03580                   ss7_rel(p->ss7);
03581                   p->alreadyhungup = 1;
03582                } else
03583                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
03584             } else {
03585                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
03586                res = -1;
03587             }
03588          }
03589       }
03590 #endif
03591 #ifdef HAVE_PRI
03592       if (p->pri) {
03593 #ifdef SUPPORT_USERUSER
03594          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
03595 #endif
03596 
03597          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
03598          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
03599             if (!pri_grab(p, p->pri)) {
03600                if (p->alreadyhungup) {
03601                   ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
03602 
03603 #ifdef SUPPORT_USERUSER
03604                   pri_call_set_useruser(p->call, useruser);
03605 #endif
03606 
03607                   pri_hangup(p->pri->pri, p->call, -1);
03608                   p->call = NULL;
03609                   if (p->bearer) 
03610                      p->bearer->call = NULL;
03611                } else {
03612                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
03613                   int icause = ast->hangupcause ? ast->hangupcause : -1;
03614                   ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
03615 
03616 #ifdef SUPPORT_USERUSER
03617                   pri_call_set_useruser(p->call, useruser);
03618 #endif
03619 
03620                   p->alreadyhungup = 1;
03621                   if (p->bearer)
03622                      p->bearer->alreadyhungup = 1;
03623                   if (cause) {
03624                      if (atoi(cause))
03625                         icause = atoi(cause);
03626                   }
03627                   pri_hangup(p->pri->pri, p->call, icause);
03628                }
03629                if (res < 0) 
03630                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
03631                pri_rel(p->pri);        
03632             } else {
03633                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
03634                res = -1;
03635             }
03636          } else {
03637             if (p->bearer)
03638                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
03639             p->call = NULL;
03640             res = 0;
03641          }
03642       }
03643 #endif
03644       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7) && (p->sig != SIG_BRI) && (p->sig != SIG_BRI_PTMP)))
03645          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
03646       if (res < 0) {
03647          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
03648       }
03649       switch (p->sig) {
03650       case SIG_FXOGS:
03651       case SIG_FXOLS:
03652       case SIG_FXOKS:
03653          memset(&par, 0, sizeof(par));
03654          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
03655          if (!res) {
03656 #if 0
03657             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
03658 #endif
03659             /* If they're off hook, try playing congestion */
03660             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
03661                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
03662             else
03663                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03664          }
03665          break;
03666       case SIG_FXSGS:
03667       case SIG_FXSLS:
03668       case SIG_FXSKS:
03669          /* Make sure we're not made available for at least two seconds assuming
03670             we were actually used for an inbound or outbound call. */
03671          if (ast->_state != AST_STATE_RESERVED) {
03672             time(&p->guardtime);
03673             p->guardtime += 2;
03674          }
03675          break;
03676       default:
03677          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
03678       }
03679       if (p->cidspill)
03680          ast_free(p->cidspill);
03681       if (p->sig)
03682          dahdi_disable_ec(p);
03683       x = 0;
03684       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
03685       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
03686       p->didtdd = 0;
03687       p->cidspill = NULL;
03688       p->callwaitcas = 0;
03689       p->callwaiting = p->permcallwaiting;
03690       p->hidecallerid = p->permhidecallerid;
03691       p->dialing = 0;
03692       p->rdnis[0] = '\0';
03693       update_conf(p);
03694       reset_conf(p);
03695       /* Restore data mode */
03696       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
03697          x = 0;
03698          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
03699       }
03700 #ifdef HAVE_PRI
03701       if (p->bearer) {
03702          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
03703          /* Free up the bearer channel as well, and
03704             don't use its file descriptor anymore */
03705          update_conf(p->bearer);
03706          reset_conf(p->bearer);
03707          p->bearer->owner = NULL;
03708          p->bearer->realcall = NULL;
03709          p->bearer = NULL;
03710          p->subs[SUB_REAL].dfd = -1;
03711          p->pri = NULL;
03712       }
03713 #endif
03714       if (num_restart_pending == 0)
03715          restart_monitor();
03716    }
03717 
03718    p->callwaitingrepeat = 0;
03719    p->cidcwexpire = 0;
03720    p->oprmode = 0;
03721    ast->tech_pvt = NULL;
03722    ast_mutex_unlock(&p->lock);
03723    ast_module_unref(ast_module_info->self);
03724    ast_verb(3, "Hungup '%s'\n", ast->name);
03725 
03726    ast_mutex_lock(&iflock);
03727 
03728    if (p->restartpending) {
03729       num_restart_pending--;
03730    }
03731 
03732    tmp = iflist;
03733    prev = NULL;
03734    if (p->destroy) {
03735       while (tmp) {
03736          if (tmp == p) {
03737             destroy_channel(prev, tmp, 0);
03738             break;
03739          } else {
03740             prev = tmp;
03741             tmp = tmp->next;
03742          }
03743       }
03744    }
03745    ast_mutex_unlock(&iflock);
03746    return 0;
03747 }

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

Definition at line 6047 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_debug, 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, chan, dahdi_enable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::digital, dahdi_pvt::dop, errno, ast_channel::hangupcause, ISTRUNK, dahdi_pvt::lock, dahdi_pvt::mohinterpret, ast_channel::name, 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::rlt, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SS7, dahdi_pvt::span, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

06048 {
06049    struct dahdi_pvt *p = chan->tech_pvt;
06050    int res=-1;
06051    int idx;
06052    int func = DAHDI_FLASH;
06053    ast_mutex_lock(&p->lock);
06054    idx = dahdi_get_index(chan, p, 0);
06055    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
06056    if (idx == SUB_REAL) {
06057       switch (condition) {
06058       case AST_CONTROL_BUSY:
06059 #ifdef HAVE_PRI
06060          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06061             chan->hangupcause = AST_CAUSE_USER_BUSY;
06062             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06063             res = 0;
06064          } else if (!p->progress && 
06065                ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06066                && p->pri && !p->outgoing) {
06067             if (p->pri->pri) {      
06068                if (!pri_grab(p, p->pri)) {
06069                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06070                   pri_rel(p->pri);
06071                }
06072                else
06073                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06074             }
06075             p->progress = 1;
06076             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06077          } else
06078 #endif
06079             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
06080          break;
06081       case AST_CONTROL_RINGING:
06082 #ifdef HAVE_PRI
06083          if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 
06084                && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06085             if (p->pri->pri) {      
06086                if (!pri_grab(p, p->pri)) {
06087                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06088                   pri_rel(p->pri);
06089                }
06090                else
06091                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06092             }
06093             p->alerting = 1;
06094          }
06095 
06096 #endif
06097 #ifdef HAVE_SS7
06098          if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
06099             if (p->ss7->ss7) {
06100                ss7_grab(p, p->ss7);
06101                
06102                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06103                   p->rlt = 1;
06104                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
06105                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
06106                p->alerting = 1;
06107                ss7_rel(p->ss7);
06108             }
06109          }
06110 #endif
06111             
06112          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
06113          
06114          if (chan->_state != AST_STATE_UP) {
06115             if ((chan->_state != AST_STATE_RING) ||
06116                ((p->sig != SIG_FXSKS) &&
06117              (p->sig != SIG_FXSLS) &&
06118              (p->sig != SIG_FXSGS)))
06119             ast_setstate(chan, AST_STATE_RINGING);
06120          }
06121          break;
06122       case AST_CONTROL_PROCEEDING:
06123          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
06124 #ifdef HAVE_PRI
06125          if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06126                && p->pri && !p->outgoing) {
06127             if (p->pri->pri) {      
06128                if (!pri_grab(p, p->pri)) {
06129                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06130                   pri_rel(p->pri);
06131                }
06132                else
06133                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06134             }
06135             p->proceeding = 1;
06136             p->dialing = 0;
06137          }
06138 #endif
06139 #ifdef HAVE_SS7
06140          /* This IF sends the FAR for an answered ALEG call */
06141          if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
06142             if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
06143                p->rlt = 1; 
06144          }
06145             
06146          if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
06147             if (p->ss7->ss7) {
06148                ss7_grab(p, p->ss7);
06149                isup_acm(p->ss7->ss7, p->ss7call);
06150                p->proceeding = 1;
06151                ss7_rel(p->ss7);
06152 
06153             }
06154          }
06155 #endif
06156          /* don't continue in ast_indicate */
06157          res = 0;
06158          break;
06159       case AST_CONTROL_PROGRESS:
06160          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
06161 #ifdef HAVE_PRI
06162          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
06163          if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
06164                && p->pri && !p->outgoing) {
06165             if (p->pri->pri) {      
06166                if (!pri_grab(p, p->pri)) {
06167                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06168                   pri_rel(p->pri);
06169                }
06170                else
06171                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06172             }
06173             p->progress = 1;
06174          }
06175 #endif
06176 #ifdef HAVE_SS7
06177          if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
06178             if (p->ss7->ss7) {
06179                ss7_grab(p, p->ss7);
06180                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
06181                p->progress = 1;
06182                ss7_rel(p->ss7);
06183                /* enable echo canceler here on SS7 calls */
06184                dahdi_enable_ec(p);
06185 
06186             }
06187          }
06188 #endif
06189          /* don't continue in ast_indicate */
06190          res = 0;
06191          break;
06192       case AST_CONTROL_CONGESTION:
06193          chan->hangupcause = AST_CAUSE_CONGESTION;
06194 #ifdef HAVE_PRI
06195          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
06196             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
06197             chan->_softhangup |= AST_SOFTHANGUP_DEV;
06198             res = 0;
06199          } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) 
06200                && p->pri && !p->outgoing) {
06201             if (p->pri) {     
06202                if (!pri_grab(p, p->pri)) {
06203                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
06204                   pri_rel(p->pri);
06205                } else
06206                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06207             }
06208             p->progress = 1;
06209             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06210          } else
06211 #endif
06212             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06213          break;
06214       case AST_CONTROL_HOLD:
06215 #ifdef HAVE_PRI
06216          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06217             if (!pri_grab(p, p->pri)) {
06218                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
06219                pri_rel(p->pri);
06220             } else
06221                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06222          } else
06223 #endif
06224             ast_moh_start(chan, data, p->mohinterpret);
06225          break;
06226       case AST_CONTROL_UNHOLD:
06227 #ifdef HAVE_PRI
06228          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
06229             if (!pri_grab(p, p->pri)) {
06230                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
06231                pri_rel(p->pri);
06232             } else
06233                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);       
06234          } else
06235 #endif
06236             ast_moh_stop(chan);
06237          break;
06238       case AST_CONTROL_RADIO_KEY:
06239          if (p->radio) 
06240              res =  dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06241          res = 0;
06242          break;
06243       case AST_CONTROL_RADIO_UNKEY:
06244          if (p->radio)
06245              res =  dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
06246          res = 0;
06247          break;
06248       case AST_CONTROL_FLASH:
06249          /* flash hookswitch */
06250          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
06251             /* Clear out the dial buffer */
06252             p->dop.dialstr[0] = '\0';
06253             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
06254                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
06255                   chan->name, strerror(errno));
06256             } else
06257                res = 0;
06258          } else
06259             res = 0;
06260          break;
06261       case AST_CONTROL_SRCUPDATE:
06262          res = 0;
06263          break;
06264       case -1:
06265          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06266          break;
06267       }
06268    } else
06269       res = 0;
06270    ast_mutex_unlock(&p->lock);
06271    return res;
06272 }

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

Definition at line 4105 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

04105                                                                           {
04106    int x;
04107    if (!slave || !master) {
04108       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04109       return;
04110    }
04111    for (x = 0; x < MAX_SLAVES; x++) {
04112       if (!master->slaves[x]) {
04113          master->slaves[x] = slave;
04114          break;
04115       }
04116    }
04117    if (x >= MAX_SLAVES) {
04118       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04119       master->slaves[MAX_SLAVES - 1] = slave;
04120    }
04121    if (slave->master) 
04122       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04123    slave->master = master;
04124    
04125    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04126 }

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

Definition at line 6274 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_channel_set_fd(), ast_copy_string(), ast_debug, ast_devstate_changed_literal(), 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_digitmode(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_state_chan2dev(), AST_STATE_RING, ast_str_alloca, ast_str_set(), ast_strdup, ast_string_field_set, ast_strlen_zero(), AST_TRANS_CAP_DIGITAL, 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, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, CANBUSYDETECT, CANPROGRESSDETECT, CHAN_PSEUDO, dahdi_pvt::channel, ast_channel::cid, ast_callerid::cid_ani, dahdi_pvt::cid_ani2, ast_callerid::cid_ani2, 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_confmute(), dahdi_setlinear(), dahdi_tech, 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_DIGIT_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, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, dahdi_pvt::muting, ast_variable::name, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, SIG_SS7, dahdi_pvt::silencethreshold, ast_str::str, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, ast_variable::value, dahdi_pvt::vars, and ast_channel::writeformat.

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

06275 {
06276    struct ast_channel *tmp;
06277    int deflaw;
06278    int res;
06279    int x,y;
06280    int features;
06281    struct ast_str *chan_name;
06282    struct ast_variable *v;
06283    struct dahdi_params ps;
06284    if (i->subs[idx].owner) {
06285       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
06286       return NULL;
06287    }
06288    y = 1;
06289    chan_name = ast_str_alloca(32);
06290    do {
06291 #ifdef HAVE_PRI
06292       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
06293          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
06294       else
06295 #endif
06296       if (i->channel == CHAN_PSEUDO)
06297          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
06298       else  
06299          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
06300       for (x = 0; x < 3; x++) {
06301          if ((idx != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name + 6))
06302             break;
06303       }
06304       y++;
06305    } while (x < 3);
06306    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", chan_name->str);
06307    if (!tmp)
06308       return NULL;
06309    tmp->tech = &dahdi_tech;
06310    memset(&ps, 0, sizeof(ps));
06311    ps.channo = i->channel;
06312    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
06313    if (res) {
06314       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
06315       ps.curlaw = DAHDI_LAW_MULAW;
06316    }
06317    if (ps.curlaw == DAHDI_LAW_ALAW)
06318       deflaw = AST_FORMAT_ALAW;
06319    else
06320       deflaw = AST_FORMAT_ULAW;
06321    if (law) {
06322       if (law == DAHDI_LAW_ALAW)
06323          deflaw = AST_FORMAT_ALAW;
06324       else
06325          deflaw = AST_FORMAT_ULAW;
06326    }
06327    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
06328    tmp->nativeformats = deflaw;
06329    /* Start out assuming ulaw since it's smaller :) */
06330    tmp->rawreadformat = deflaw;
06331    tmp->readformat = deflaw;
06332    tmp->rawwriteformat = deflaw;
06333    tmp->writeformat = deflaw;
06334    i->subs[idx].linear = 0;
06335    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
06336    features = 0;
06337    if (idx == SUB_REAL) {
06338       if (i->busydetect && CANBUSYDETECT(i))
06339          features |= DSP_FEATURE_BUSY_DETECT;
06340       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
06341          features |= DSP_FEATURE_CALL_PROGRESS;
06342       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) || 
06343           (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
06344          features |= DSP_FEATURE_FAX_DETECT;
06345       }
06346       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
06347       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
06348          i->hardwaredtmf = 0;
06349          features |= DSP_FEATURE_DIGIT_DETECT;
06350       } else if (NEED_MFDETECT(i)) {
06351          i->hardwaredtmf = 1;
06352          features |= DSP_FEATURE_DIGIT_DETECT;
06353       }
06354    }
06355    if (features) {
06356       if (i->dsp) {
06357          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
06358       } else {
06359          if (i->channel != CHAN_PSEUDO)
06360             i->dsp = ast_dsp_new();
06361          else
06362             i->dsp = NULL;
06363          if (i->dsp) {
06364             i->dsp_features = features;
06365 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06366             /* We cannot do progress detection until receives PROGRESS message */
06367             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
06368                /* Remember requested DSP features, don't treat
06369                   talking as ANSWER */
06370                i->dsp_features = features & ~DSP_PROGRESS_TALK;
06371                features = 0;
06372             }
06373 #endif
06374             ast_dsp_set_features(i->dsp, features);
06375             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
06376             if (!ast_strlen_zero(progzone))
06377                ast_dsp_set_call_progress_zone(i->dsp, progzone);
06378             if (i->busydetect && CANBUSYDETECT(i)) {
06379                if(i->silencethreshold > 0)
06380                   ast_dsp_set_threshold(i->dsp, i->silencethreshold);
06381                ast_dsp_set_busy_count(i->dsp, i->busycount);
06382                if(i->busytonelength > 0)
06383                   ast_dsp_set_busy_pattern(i->dsp, i->busytonelength, i->busyquietlength, i->busyfuzziness);
06384                if((i->busytonelength == i->busyquietlength) && i->busycompare)
06385                   ast_dsp_set_busy_compare(i->dsp, i->busycompare);
06386             }
06387          }
06388       }
06389    }
06390       
06391    if (state == AST_STATE_RING)
06392       tmp->rings = 1;
06393    tmp->tech_pvt = i;
06394    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
06395       /* Only FXO signalled stuff can be picked up */
06396       tmp->callgroup = i->callgroup;
06397       tmp->pickupgroup = i->pickupgroup;
06398    }
06399    if (!ast_strlen_zero(i->parkinglot))
06400       ast_string_field_set(tmp, parkinglot, i->parkinglot);
06401    if (!ast_strlen_zero(i->language))
06402       ast_string_field_set(tmp, language, i->language);
06403    if (!i->owner)
06404       i->owner = tmp;
06405    if (!ast_strlen_zero(i->accountcode))
06406       ast_string_field_set(tmp, accountcode, i->accountcode);
06407    if (i->amaflags)
06408       tmp->amaflags = i->amaflags;
06409    i->subs[idx].owner = tmp;
06410    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
06411    ast_string_field_set(tmp, call_forward, i->call_forward);
06412    /* If we've been told "no ADSI" then enforce it */
06413    if (!i->adsi)
06414       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
06415    if (!ast_strlen_zero(i->exten))
06416       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
06417    if (!ast_strlen_zero(i->rdnis))
06418       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
06419    if (!ast_strlen_zero(i->dnid))
06420       tmp->cid.cid_dnid = ast_strdup(i->dnid);
06421 
06422    /* Don't use ast_set_callerid() here because it will
06423     * generate a needless NewCallerID event */
06424 #ifdef PRI_ANI
06425    if (!ast_strlen_zero(i->cid_ani))
06426       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
06427    else  
06428       tmp->cid.cid_ani = ast_strdup(i->cid_num);
06429 #else
06430    tmp->cid.cid_ani = ast_strdup(i->cid_num);
06431 #endif
06432    tmp->cid.cid_pres = i->callingpres;
06433    tmp->cid.cid_ton = i->cid_ton;
06434    tmp->cid.cid_ani2 = i->cid_ani2;
06435 #if defined(HAVE_PRI) || defined(HAVE_SS7)
06436    tmp->transfercapability = transfercapability;
06437    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
06438    if (transfercapability & AST_TRANS_CAP_DIGITAL)
06439       i->digital = 1;
06440    /* Assume calls are not idle calls unless we're told differently */
06441    i->isidlecall = 0;
06442    i->alreadyhungup = 0;
06443 #endif
06444    /* clear the fake event in case we posted one before we had ast_channel */
06445    i->fake_event = 0;
06446    /* Assure there is no confmute on this channel */
06447    dahdi_confmute(i, 0);
06448    i->muting = 0;
06449    /* Configure the new channel jb */
06450    ast_jb_configure(tmp, &global_jbconf);
06451 
06452    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
06453 
06454    for (v = i->vars ; v ; v = v->next)
06455                 pbx_builtin_setvar_helper(tmp, v->name, v->value);
06456 
06457    if (startpbx) {
06458       if (ast_pbx_start(tmp)) {
06459          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
06460          ast_hangup(tmp);
06461          i->owner = NULL;
06462          return NULL;
06463       }
06464    }
06465 
06466    ast_module_ref(ast_module_info->self);
06467    return tmp;
06468 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1456 of file chan_dahdi.c.

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

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

01457 {
01458    int fd;
01459    int isnum;
01460    int chan = 0;
01461    int bs;
01462    int x;
01463    isnum = 1;
01464    for (x = 0; x < strlen(fn); x++) {
01465       if (!isdigit(fn[x])) {
01466          isnum = 0;
01467          break;
01468       }
01469    }
01470    if (isnum) {
01471       chan = atoi(fn);
01472       if (chan < 1) {
01473          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01474          return -1;
01475       }
01476       fn = "/dev/dahdi/channel";
01477    }
01478    fd = open(fn, O_RDWR | O_NONBLOCK);
01479    if (fd < 0) {
01480       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01481       return -1;
01482    }
01483    if (chan) {
01484       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01485          x = errno;
01486          close(fd);
01487          errno = x;
01488          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01489          return -1;
01490       }
01491    }
01492    bs = READ_SIZE;
01493    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01494       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01495       x = errno;
01496       close(fd);
01497       errno = x;
01498       return -1;
01499    }
01500    return fd;
01501 }

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

Definition at line 10725 of file chan_dahdi.c.

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

Referenced by dahdi_restart(), and load_module().

10726 {
10727    int x, y;
10728    int dchan = -1, span = -1;
10729    int dchancount = 0;
10730 
10731    if (pri) {
10732       for (x = 0; x < NUM_SPANS; x++) {
10733          for (y = 0; y < NUM_DCHANS; y++) {
10734             if (pris[x].dchans[y])
10735                dchancount++;
10736 
10737             if (pris[x].dchans[y] == pri)
10738                dchan = y;
10739          }
10740          if (dchan >= 0) {
10741             span = x;
10742             break;
10743          }
10744          dchancount = 0;
10745       }
10746       if ((dchancount > 1) && (span > -1))
10747          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10748       else
10749          ast_log(LOG_ERROR, "%s", s);
10750    } else
10751       ast_log(LOG_ERROR, "%s", s);
10752 
10753    ast_mutex_lock(&pridebugfdlock);
10754 
10755    if (pridebugfd >= 0) {
10756       if (write(pridebugfd, s, strlen(s)) < 0) {
10757          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10758       }
10759    }
10760 
10761    ast_mutex_unlock(&pridebugfdlock);
10762 }

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

Definition at line 10686 of file chan_dahdi.c.

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

Referenced by dahdi_restart(), and load_module().

10687 {
10688    int x, y;
10689    int dchan = -1, span = -1;
10690    int dchancount = 0;
10691 
10692    if (pri) {
10693       for (x = 0; x < NUM_SPANS; x++) {
10694          for (y = 0; y < NUM_DCHANS; y++) {
10695             if (pris[x].dchans[y])
10696                dchancount++;
10697 
10698             if (pris[x].dchans[y] == pri)
10699                dchan = y;
10700          }
10701          if (dchan >= 0) {
10702             span = x;
10703             break;
10704          }
10705          dchancount = 0;
10706       }
10707       if (dchancount > 1 && (span > -1))
10708          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10709       else
10710          ast_verbose("%s", s);
10711    } else
10712       ast_verbose("%s", s);
10713 
10714    ast_mutex_lock(&pridebugfdlock);
10715 
10716    if (pridebugfd >= 0) {
10717       if (write(pridebugfd, s, strlen(s)) < 0) {
10718          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10719       }
10720    }
10721 
10722    ast_mutex_unlock(&pridebugfdlock);
10723 }

static void dahdi_queue_frame ( struct dahdi_pvt p,
struct ast_frame f,
void *  data 
) [static]

Definition at line 1362 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_unlock(), ast_queue_frame(), DEADLOCK_AVOIDANCE, f, dahdi_pvt::lock, dahdi_pri::lock, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, and SIG_SS7.

Referenced by action_dahdidialoffhook().

01363 {
01364 #ifdef HAVE_PRI
01365    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01366 #endif
01367 #ifdef HAVE_SS7
01368    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01369 #endif
01370    /* We must unlock the PRI to avoid the possibility of a deadlock */
01371 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01372    if (data) {
01373       switch (p->sig) {
01374 #ifdef HAVE_PRI
01375       case SIG_BRI:
01376       case SIG_BRI_PTMP:
01377       case SIG_PRI:
01378          ast_mutex_unlock(&pri->lock);
01379          break;
01380 #endif
01381 #ifdef HAVE_SS7
01382       case SIG_SS7:
01383          ast_mutex_unlock(&ss7->lock);
01384          break;
01385 #endif
01386       default:
01387          break;
01388       }
01389    }
01390 #endif      
01391    for (;;) {
01392       if (p->owner) {
01393          if (ast_channel_trylock(p->owner)) {
01394             DEADLOCK_AVOIDANCE(&p->lock);
01395          } else {
01396             ast_queue_frame(p->owner, f);
01397             ast_channel_unlock(p->owner);
01398             break;
01399          }
01400       } else
01401          break;
01402    }
01403 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01404    if (data) {
01405       switch (p->sig) {
01406 #ifdef HAVE_PRI
01407       case SIG_BRI:
01408       case SIG_BRI_PTMP:
01409       case SIG_PRI:
01410          ast_mutex_lock(&pri->lock);
01411          break;
01412 #endif
01413 #ifdef HAVE_SS7
01414       case SIG_SS7:
01415          ast_mutex_lock(&ss7->lock);
01416          break;
01417 #endif
01418       default:
01419          break;
01420       }
01421    }
01422 
01423 #endif      
01424 }

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

Definition at line 5643 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_debug, ast_dsp_process(), ast_dsp_was_muted(), 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_verb, dahdi_subchannel::buffer, dahdi_pvt::busydetect, dahdi_pvt::callprogress, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, dahdi_pvt::callwaitrings, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, CHECK_BLOCKING, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_callwait(), dahdi_confmute(), dahdi_get_index(), dahdi_handle_dtmfup(), DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_setlinear(), ast_frame::data, ast_frame::datalen, 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, dahdi_pvt::lock, ast_frame::mallocd, dahdi_pvt::muting, 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, dahdi_pvt::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::proceeding, ast_frame::ptr, 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_BRI, SIG_BRI_PTMP, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), and ast_channel::tech_pvt.

05644 {
05645    struct dahdi_pvt *p = ast->tech_pvt;
05646    int res;
05647    int idx;
05648    void *readbuf;
05649    struct ast_frame *f;
05650 
05651    while (ast_mutex_trylock(&p->lock)) {
05652       CHANNEL_DEADLOCK_AVOIDANCE(ast);
05653    }
05654 
05655    idx = dahdi_get_index(ast, p, 0);
05656    
05657    /* Hang up if we don't really exist */
05658    if (idx < 0)   {
05659       ast_log(LOG_WARNING, "We dont exist?\n");
05660       ast_mutex_unlock(&p->lock);
05661       return NULL;
05662    }
05663    
05664    if ((p->radio || (p->oprmode < 0)) && p->inalarm) return NULL;
05665 
05666    p->subs[idx].f.frametype = AST_FRAME_NULL;
05667    p->subs[idx].f.datalen = 0;
05668    p->subs[idx].f.samples = 0;
05669    p->subs[idx].f.mallocd = 0;
05670    p->subs[idx].f.offset = 0;
05671    p->subs[idx].f.subclass = 0;
05672    p->subs[idx].f.delivery = ast_tv(0,0);
05673    p->subs[idx].f.src = "dahdi_read";
05674    p->subs[idx].f.data.ptr = NULL;
05675    
05676    /* make sure it sends initial key state as first frame */
05677    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
05678    {
05679       struct dahdi_params ps;
05680 
05681       memset(&ps, 0, sizeof(ps));
05682       ps.channo = p->channel;
05683       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
05684          ast_mutex_unlock(&p->lock);
05685          return NULL;
05686       }
05687       p->firstradio = 1;
05688       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05689       if (ps.rxisoffhook)
05690       {
05691          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
05692       }
05693       else
05694       {
05695          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05696       }
05697       ast_mutex_unlock(&p->lock);
05698       return &p->subs[idx].f;
05699    }
05700    if (p->ringt == 1) {
05701       ast_mutex_unlock(&p->lock);
05702       return NULL;
05703    }
05704    else if (p->ringt > 0) 
05705       p->ringt--;
05706 
05707    if (p->subs[idx].needringing) {
05708       /* Send ringing frame if requested */
05709       p->subs[idx].needringing = 0;
05710       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05711       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
05712       ast_setstate(ast, AST_STATE_RINGING);
05713       ast_mutex_unlock(&p->lock);
05714       return &p->subs[idx].f;
05715    }
05716 
05717    if (p->subs[idx].needbusy) {
05718       /* Send busy frame if requested */
05719       p->subs[idx].needbusy = 0;
05720       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05721       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
05722       ast_mutex_unlock(&p->lock);
05723       return &p->subs[idx].f;
05724    }
05725 
05726    if (p->subs[idx].needcongestion) {
05727       /* Send congestion frame if requested */
05728       p->subs[idx].needcongestion = 0;
05729       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05730       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
05731       ast_mutex_unlock(&p->lock);
05732       return &p->subs[idx].f;
05733    }
05734 
05735    if (p->subs[idx].needcallerid) {
05736       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
05737                      S_OR(p->lastcid_name, NULL),
05738                      S_OR(p->lastcid_num, NULL)
05739                      );
05740       p->subs[idx].needcallerid = 0;
05741    }
05742    
05743    if (p->subs[idx].needanswer) {
05744       /* Send answer frame if requested */
05745       p->subs[idx].needanswer = 0;
05746       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05747       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05748       ast_mutex_unlock(&p->lock);
05749       return &p->subs[idx].f;
05750    }  
05751    
05752    if (p->subs[idx].needflash) {
05753       /* Send answer frame if requested */
05754       p->subs[idx].needflash = 0;
05755       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05756       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
05757       ast_mutex_unlock(&p->lock);
05758       return &p->subs[idx].f;
05759    }  
05760    
05761    if (p->subs[idx].needhold) {
05762       /* Send answer frame if requested */
05763       p->subs[idx].needhold = 0;
05764       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05765       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
05766       ast_mutex_unlock(&p->lock);
05767       ast_debug(1, "Sending hold on '%s'\n", ast->name);
05768       return &p->subs[idx].f;
05769    }  
05770    
05771    if (p->subs[idx].needunhold) {
05772       /* Send answer frame if requested */
05773       p->subs[idx].needunhold = 0;
05774       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05775       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
05776       ast_mutex_unlock(&p->lock);
05777       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
05778       return &p->subs[idx].f;
05779    }  
05780    
05781    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
05782       if (!p->subs[idx].linear) {
05783          p->subs[idx].linear = 1;
05784          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05785          if (res) 
05786             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
05787       }
05788    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
05789          (ast->rawreadformat == AST_FORMAT_ALAW)) {
05790       if (p->subs[idx].linear) {
05791          p->subs[idx].linear = 0;
05792          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
05793          if (res) 
05794             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
05795       }
05796    } else {
05797       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
05798       ast_mutex_unlock(&p->lock);
05799       return NULL;
05800    }
05801    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
05802    CHECK_BLOCKING(ast);
05803    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05804    ast_clear_flag(ast, AST_FLAG_BLOCKING);
05805    /* Check for hangup */
05806    if (res < 0) {
05807       f = NULL;
05808       if (res == -1)  {
05809          if (errno == EAGAIN) {
05810             /* Return "NULL" frame if there is nobody there */
05811             ast_mutex_unlock(&p->lock);
05812             return &p->subs[idx].f;
05813          } else if (errno == ELAST) {
05814             f = __dahdi_exception(ast);
05815          } else
05816             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
05817       }
05818       ast_mutex_unlock(&p->lock);
05819       return f;
05820    }
05821    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
05822       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
05823       f = __dahdi_exception(ast);
05824       ast_mutex_unlock(&p->lock);
05825       return f;
05826    }
05827    if (p->tdd) { /* if in TDD mode, see if we receive that */
05828       int c;
05829 
05830       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
05831       if (c < 0) {
05832          ast_debug(1,"tdd_feed failed\n");
05833          ast_mutex_unlock(&p->lock);
05834          return NULL;
05835       }
05836       if (c) { /* if a char to return */
05837          p->subs[idx].f.subclass = 0;
05838          p->subs[idx].f.frametype = AST_FRAME_TEXT;
05839          p->subs[idx].f.mallocd = 0;
05840          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05841          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
05842          p->subs[idx].f.datalen = 1;
05843          *((char *) p->subs[idx].f.data.ptr) = c;
05844          ast_mutex_unlock(&p->lock);
05845          return &p->subs[idx].f;
05846       }
05847    }
05848    /* Ensure the CW timer decrements only on a single subchannel */
05849    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
05850       p->callwaitingrepeat--;
05851    }
05852    if (p->cidcwexpire)
05853       p->cidcwexpire--;
05854    /* Repeat callwaiting */
05855    if (p->callwaitingrepeat == 1) {
05856       p->callwaitrings++;
05857       dahdi_callwait(ast);
05858    }
05859    /* Expire CID/CW */
05860    if (p->cidcwexpire == 1) {
05861       ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
05862       restore_conference(p);
05863    }
05864    if (p->subs[idx].linear) {
05865       p->subs[idx].f.datalen = READ_SIZE * 2;
05866    } else 
05867       p->subs[idx].f.datalen = READ_SIZE;
05868 
05869    /* Handle CallerID Transmission */
05870    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
05871       send_callerid(p);
05872    }
05873 
05874    p->subs[idx].f.frametype = AST_FRAME_VOICE;
05875    p->subs[idx].f.subclass = ast->rawreadformat;
05876    p->subs[idx].f.samples = READ_SIZE;
05877    p->subs[idx].f.mallocd = 0;
05878    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
05879    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
05880 #if 0
05881    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
05882 #endif   
05883    if (p->dialing || /* Transmitting something */
05884       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
05885       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
05886       ) {
05887       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
05888          don't send anything */
05889       p->subs[idx].f.frametype = AST_FRAME_NULL;
05890       p->subs[idx].f.subclass = 0;
05891       p->subs[idx].f.samples = 0;
05892       p->subs[idx].f.mallocd = 0;
05893       p->subs[idx].f.offset = 0;
05894       p->subs[idx].f.data.ptr = NULL;
05895       p->subs[idx].f.datalen= 0;
05896    }
05897    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect  || p->callprogress) && !idx) {
05898       /* Perform busy detection. etc on the dahdi line */
05899       int mute;
05900 
05901       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
05902 
05903       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
05904       mute = ast_dsp_was_muted(p->dsp);
05905       if (p->muting != mute) {
05906          p->muting = mute;
05907          dahdi_confmute(p, mute);
05908       }
05909 
05910       if (f) {
05911          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
05912             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
05913                /* Treat this as a "hangup" instead of a "busy" on the assumption that
05914                   a busy  */
05915                f = NULL;
05916             }
05917          } else if (f->frametype == AST_FRAME_DTMF) {
05918 #ifdef HAVE_PRI
05919             if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && 
05920                 ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
05921                  (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
05922                /* Don't accept in-band DTMF when in overlap dial mode */
05923                f->frametype = AST_FRAME_NULL;
05924                f->subclass = 0;
05925             }
05926 #endif            
05927             /* DSP clears us of being pulse */
05928             p->pulsedial = 0;
05929          }
05930       }
05931    } else 
05932       f = &p->subs[idx].f; 
05933 
05934    if (f && (f->frametype == AST_FRAME_DTMF))
05935       dahdi_handle_dtmfup(ast, idx, &f);
05936 
05937    /* If we have a fake_event, trigger exception to handle it */
05938    if (p->fake_event)
05939       ast_set_flag(ast, AST_FLAG_EXCEPTION);
05940 
05941    ast_mutex_unlock(&p->lock);
05942    return f;
05943 }

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

Definition at line 9441 of file chan_dahdi.c.

References alloc_sub(), AST_CAUSE_BUSY, AST_CAUSE_CONGESTION, AST_CDR_CALLWAIT, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RESERVED, ast_strdupa, AST_TRANS_CAP_DIGITAL, ast_verbose, available(), dahdi_pvt::bearer, 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_NOTICE, ast_channel::name, dahdi_pvt::next, NUM_SPANS, 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, strsep(), SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.

Referenced by pri_dchannel().

09442 {
09443    ast_group_t groupmatch = 0;
09444    int channelmatch = -1;
09445    int roundrobin = 0;
09446    int callwait = 0;
09447    int busy = 0;
09448    struct dahdi_pvt *p;
09449    struct ast_channel *tmp = NULL;
09450    char *dest=NULL;
09451    int x;
09452    char *s;
09453    char opt=0;
09454    int res=0, y=0;
09455    int backwards = 0;
09456 #ifdef HAVE_PRI
09457    int crv;
09458    int bearer = -1;
09459    int trunkgroup;
09460    struct dahdi_pri *pri=NULL;
09461 #endif   
09462    struct dahdi_pvt *exitpvt, *start, *end;
09463    ast_mutex_t *lock;
09464    int channelmatched = 0;
09465    int groupmatched = 0;
09466    
09467    /*
09468     * data is ---v
09469     * Dial(DAHDI/pseudo[/extension])
09470     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09471     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09472     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09473     *
09474     * g - channel group allocation search forward
09475     * G - channel group allocation search backward
09476     * r - channel group allocation round robin search forward
09477     * R - channel group allocation round robin search backward
09478     *
09479     * c - Wait for DTMF digit to confirm answer
09480     * r<cadance#> - Set distintive ring cadance number
09481     * d - Force bearer capability for ISDN/SS7 call to digital.
09482     */
09483 
09484    /* Assume we're locking the iflock */
09485    lock = &iflock;
09486    start = iflist;
09487    end = ifend;
09488    if (data) {
09489       dest = ast_strdupa((char *)data);
09490    } else {
09491       ast_log(LOG_WARNING, "Channel requested with no data\n");
09492       return NULL;
09493    }
09494    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09495       /* Retrieve the group number */
09496       char *stringp;
09497 
09498       stringp = dest + 1;
09499       s = strsep(&stringp, "/");
09500       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09501          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09502          return NULL;
09503       }
09504       groupmatch = ((ast_group_t) 1 << x);
09505       if (toupper(dest[0]) == 'G') {
09506          if (dest[0] == 'G') {
09507             backwards = 1;
09508             p = ifend;
09509          } else
09510             p = iflist;
09511       } else {
09512          if (dest[0] == 'R') {
09513             backwards = 1;
09514             p = round_robin[x]?round_robin[x]->prev:ifend;
09515             if (!p)
09516                p = ifend;
09517          } else {
09518             p = round_robin[x]?round_robin[x]->next:iflist;
09519             if (!p)
09520                p = iflist;
09521          }
09522          roundrobin = 1;
09523       }
09524    } else {
09525       char *stringp;
09526 
09527       stringp = dest;
09528       s = strsep(&stringp, "/");
09529       p = iflist;
09530       if (!strcasecmp(s, "pseudo")) {
09531          /* Special case for pseudo */
09532          x = CHAN_PSEUDO;
09533          channelmatch = x;
09534       } 
09535 #ifdef HAVE_PRI
09536       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
09537          if ((trunkgroup < 1) || (crv < 1)) {
09538             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09539             return NULL;
09540          }
09541          res--;
09542          for (x = 0; x < NUM_SPANS; x++) {
09543             if (pris[x].trunkgroup == trunkgroup) {
09544                pri = pris + x;
09545                lock = &pri->lock;
09546                start = pri->crvs;
09547                end = pri->crvend;
09548                break;
09549             }
09550          }
09551          if (!pri) {
09552             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09553             return NULL;
09554          }
09555          channelmatch = crv;
09556          p = pris[x].crvs;
09557       }
09558 #endif   
09559       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09560          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09561          return NULL;
09562       } else {
09563          channelmatch = x;
09564       }
09565    }
09566    /* Search for an unowned channel */
09567    ast_mutex_lock(lock);
09568    exitpvt = p;
09569    while (p && !tmp) {
09570       if (roundrobin)
09571          round_robin[x] = p;
09572 #if 0
09573       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09574 #endif
09575 
09576       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09577          ast_debug(1, "Using channel %d\n", p->channel);
09578          if (p->inalarm) 
09579             goto next;
09580 
09581          callwait = (p->owner != NULL);
09582 #ifdef HAVE_PRI
09583          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09584             if (p->sig != SIG_FXSKS) {
09585                /* Gotta find an actual channel to use for this
09586                   CRV if this isn't a callwait */
09587                bearer = pri_find_empty_chan(pri, 0);
09588                if (bearer < 0) {
09589                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09590                   p = NULL;
09591                   break;
09592                }
09593                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09594             } else {
09595                if (alloc_sub(p, 0)) {
09596                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09597                   p = NULL;
09598                   break;
09599                } else
09600                   ast_debug(1, "Allocated placeholder pseudo channel\n");
09601 
09602                p->pri = pri;
09603             }
09604          }
09605 #endif         
09606          if (p->channel == CHAN_PSEUDO) {
09607             p = chandup(p);
09608             if (!p) {
09609                break;
09610             }
09611          }
09612          if (p->owner) {
09613             if (alloc_sub(p, SUB_CALLWAIT)) {
09614                p = NULL;
09615                break;
09616             }
09617          }
09618          p->outgoing = 1;
09619          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09620 #ifdef HAVE_PRI
09621          if (p->bearer) {
09622             /* Log owner to bearer channel, too */
09623             p->bearer->owner = tmp;
09624          }
09625 #endif         
09626          /* Make special notes */
09627          if (res > 1) {
09628             if (opt == 'c') {
09629                /* Confirm answer */
09630                p->confirmanswer = 1;
09631             } else if (opt == 'r') {
09632                /* Distinctive ring */
09633                if (res < 3)
09634                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09635                else
09636                   p->distinctivering = y;
09637             } else if (opt == 'd') {
09638                /* If this is an ISDN call, make it digital */
09639                p->digital = 1;
09640                if (tmp)
09641                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09642             } else {
09643                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09644             }
09645          }
09646          /* Note if the call is a call waiting call */
09647          if (tmp && callwait)
09648             tmp->cdrflags |= AST_CDR_CALLWAIT;
09649          break;
09650       }
09651 next:
09652       if (backwards) {
09653          p = p->prev;
09654          if (!p)
09655             p = end;
09656       } else {
09657          p = p->next;
09658          if (!p)
09659             p = start;
09660       }
09661       /* stop when you roll to the one that we started from */
09662       if (p == exitpvt)
09663          break;
09664    }
09665    ast_mutex_unlock(lock);
09666    restart_monitor();
09667    if (callwait)
09668       *cause = AST_CAUSE_BUSY;
09669    else if (!tmp) {
09670       if (channelmatched) {
09671          if (busy)
09672             *cause = AST_CAUSE_BUSY;
09673       } else if (groupmatched) {
09674          *cause = AST_CAUSE_CONGESTION;
09675       }
09676    }
09677       
09678    return tmp;
09679 }

static int dahdi_restart ( void   )  [static]

Definition at line 12480 of file chan_dahdi.c.

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

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

12481 {
12482 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12483    int i, j;
12484 #endif
12485    int cancel_code;
12486    struct dahdi_pvt *p;
12487 
12488    ast_mutex_lock(&restart_lock);
12489 
12490    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12491    dahdi_softhangup_all();
12492    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12493 
12494 #if defined(HAVE_PRI)
12495    for (i = 0; i < NUM_SPANS; i++) {
12496       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12497          cancel_code = pthread_cancel(pris[i].master);
12498          pthread_kill(pris[i].master, SIGURG);
12499          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12500          pthread_join(pris[i].master, NULL);
12501          ast_debug(4, "Joined thread of span %d\n", i);
12502       }
12503    }
12504 #endif
12505 
12506 #if defined(HAVE_SS7)
12507    for (i = 0; i < NUM_SPANS; i++) {
12508       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12509          cancel_code = pthread_cancel(linksets[i].master);
12510          pthread_kill(linksets[i].master, SIGURG);
12511          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12512          pthread_join(linksets[i].master, NULL);
12513          ast_debug(4, "Joined thread of span %d\n", i);
12514       }
12515     }
12516 #endif
12517 
12518    ast_mutex_lock(&monlock);
12519    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12520       cancel_code = pthread_cancel(monitor_thread);
12521       pthread_kill(monitor_thread, SIGURG);
12522       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12523       pthread_join(monitor_thread, NULL);
12524       ast_debug(4, "Joined monitor thread\n");
12525    }
12526    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12527 
12528    ast_mutex_lock(&mwi_thread_lock);
12529    while (mwi_thread_count > 0) {
12530       ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12531       ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12532    }
12533    ast_mutex_unlock(&mwi_thread_lock);
12534    ast_mutex_lock(&ss_thread_lock);
12535    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12536       int x = DAHDI_FLASH;
12537       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12538 
12539       for (p = iflist; p; p = p->next) {
12540          if (p->owner)
12541             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 */      
12542          }
12543          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12544       }
12545 
12546    /* ensure any created channels before monitor threads were stopped are hungup */
12547    dahdi_softhangup_all();
12548    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12549    destroy_all_channels();
12550    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12551 
12552    ast_mutex_unlock(&monlock);
12553 
12554 #ifdef HAVE_PRI
12555    for (i = 0; i < NUM_SPANS; i++) {
12556       for (j = 0; j < NUM_DCHANS; j++)
12557          dahdi_close_pri_fd(&(pris[i]), j);
12558    }
12559 
12560    memset(pris, 0, sizeof(pris));
12561    for (i = 0; i < NUM_SPANS; i++) {
12562       ast_mutex_init(&pris[i].lock);
12563       pris[i].offset = -1;
12564       pris[i].master = AST_PTHREADT_NULL;
12565       for (j = 0; j < NUM_DCHANS; j++)
12566          pris[i].fds[j] = -1;
12567       }
12568    pri_set_error(dahdi_pri_error);
12569    pri_set_message(dahdi_pri_message);
12570 #endif
12571 #ifdef HAVE_SS7
12572    for (i = 0; i < NUM_SPANS; i++) {
12573       for (j = 0; j < NUM_DCHANS; j++)
12574          dahdi_close_ss7_fd(&(linksets[i]), j);
12575    }
12576 
12577    memset(linksets, 0, sizeof(linksets));
12578    for (i = 0; i < NUM_SPANS; i++) {
12579       ast_mutex_init(&linksets[i].lock);
12580       linksets[i].master = AST_PTHREADT_NULL;
12581       for (j = 0; j < NUM_DCHANS; j++)
12582          linksets[i].fds[j] = -1;
12583    }
12584    ss7_set_error(dahdi_ss7_error);
12585    ss7_set_message(dahdi_ss7_message);
12586 #endif
12587 
12588    if (setup_dahdi(2) != 0) {
12589       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12590       ast_mutex_unlock(&ss_thread_lock);
12591       return 1;
12592    }
12593    ast_mutex_unlock(&ss_thread_lock);
12594    ast_mutex_unlock(&restart_lock);
12595    return 0;
12596 }

static char* dahdi_restart_cmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12598 of file chan_dahdi.c.

References ast_cli_args::argc, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_restart(), and ast_cli_entry::usage.

12599 {
12600    switch (cmd) {
12601    case CLI_INIT:
12602       e->command = "dahdi restart";
12603       e->usage = 
12604          "Usage: dahdi restart\n"
12605          "  Restarts the DAHDI channels: destroys them all and then\n"
12606          "  re-reads them from chan_dahdi.conf.\n"
12607          "  Note that this will STOP any running CALL on DAHDI channels.\n"
12608          "";
12609       return NULL;
12610    case CLI_GENERATE:
12611       return NULL;
12612    }
12613    if (a->argc != 2)
12614       return CLI_SHOWUSAGE;
12615 
12616    if (dahdi_restart() != 0)
12617       return CLI_FAILURE;
12618    return CLI_SUCCESS;
12619 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 4475 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), and dahdi_handle_event().

04476 {
04477    int x;
04478    int res;
04479    /* Make sure our transmit state is on hook */
04480    x = 0;
04481    x = DAHDI_ONHOOK;
04482    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04483    do {
04484       x = DAHDI_RING;
04485       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04486       if (res) {
04487          switch (errno) {
04488          case EBUSY:
04489          case EINTR:
04490             /* Wait just in case */
04491             usleep(10000);
04492             continue;
04493          case EINPROGRESS:
04494             res = 0;
04495             break;
04496          default:
04497             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04498             res = 0;
04499          }
04500       }
04501    } while (res);
04502    return res;
04503 }

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

Definition at line 3272 of file chan_dahdi.c.

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

Referenced by load_module().

03273 {
03274    /* Data will be our digit string */
03275    struct dahdi_pvt *p;
03276    char *digits = (char *) data;
03277 
03278    if (ast_strlen_zero(digits)) {
03279       ast_debug(1, "No digit string sent to application!\n");
03280       return -1;
03281    }
03282 
03283    p = (struct dahdi_pvt *)chan->tech_pvt;
03284 
03285    if (!p) {
03286       ast_debug(1, "Unable to find technology private\n");
03287       return -1;
03288    }
03289 
03290    ast_mutex_lock(&p->lock);
03291 
03292    if (!p->pri || !p->call) {
03293       ast_debug(1, "Unable to find pri or call on channel!\n");
03294       ast_mutex_unlock(&p->lock);
03295       return -1;
03296    }
03297 
03298    if (!pri_grab(p, p->pri)) {
03299       pri_keypad_facility(p->pri->pri, p->call, digits);
03300       pri_rel(p->pri);
03301    } else {
03302       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03303       ast_mutex_unlock(&p->lock);
03304       return -1;
03305    }
03306 
03307    ast_mutex_unlock(&p->lock);
03308 
03309    return 0;
03310 }

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

Definition at line 15347 of file chan_dahdi.c.

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

15348 {
15349 #define  END_SILENCE_LEN 400
15350 #define  HEADER_MS 50
15351 #define  TRAILER_MS 5
15352 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15353 #define  ASCII_BYTES_PER_CHAR 80
15354 
15355    unsigned char *buf,*mybuf;
15356    struct dahdi_pvt *p = c->tech_pvt;
15357    struct pollfd fds[1];
15358    int size,res,fd,len,x;
15359    int bytes=0;
15360    /* Initial carrier (imaginary) */
15361    float cr = 1.0;
15362    float ci = 0.0;
15363    float scont = 0.0;
15364    int idx;
15365 
15366    idx = dahdi_get_index(c, p, 0);
15367    if (idx < 0) {
15368       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
15369       return -1;
15370    }
15371    if (!text[0]) return(0); /* if nothing to send, dont */
15372    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
15373    if (p->mate) 
15374       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15375    else
15376       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15377    if (!buf)
15378       return -1;
15379    mybuf = buf;
15380    if (p->mate) {
15381       int codec = AST_LAW(p);
15382       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
15383          PUT_CLID_MARKMS;
15384       }
15385       /* Put actual message */
15386       for (x = 0; text[x]; x++) {
15387          PUT_CLID(text[x]);
15388       }
15389       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
15390          PUT_CLID_MARKMS;
15391       }
15392       len = bytes;
15393       buf = mybuf;
15394    } else {
15395       len = tdd_generate(p->tdd, buf, text);
15396       if (len < 1) {
15397          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15398          ast_free(mybuf);
15399          return -1;
15400       }
15401    }
15402    memset(buf + len, 0x7f, END_SILENCE_LEN);
15403    len += END_SILENCE_LEN;
15404    fd = p->subs[idx].dfd;
15405    while (len) {
15406       if (ast_check_hangup(c)) {
15407          ast_free(mybuf);
15408          return -1;
15409       }
15410       size = len;
15411       if (size > READ_SIZE)
15412          size = READ_SIZE;
15413       fds[0].fd = fd;
15414       fds[0].events = POLLOUT | POLLPRI;
15415       fds[0].revents = 0;
15416       res = poll(fds, 1, -1);
15417       if (!res) {
15418          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15419          continue;
15420       }
15421         /* if got exception */
15422       if (fds[0].revents & POLLPRI) {
15423          ast_free(mybuf);
15424          return -1;
15425       }
15426       if (!(fds[0].revents & POLLOUT)) {
15427          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15428          continue;
15429       }
15430       res = write(fd, buf, size);
15431       if (res != size) {
15432          if (res == -1) {
15433             ast_free(mybuf);
15434             return -1;
15435          }
15436          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15437          break;
15438       }
15439       len -= size;
15440       buf += size;
15441    }
15442    ast_free(mybuf);
15443    return(0);
15444 }

static char* dahdi_set_dnd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 13246 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_false(), ast_mutex_lock(), ast_mutex_unlock(), ast_true(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_dnd(), ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, and ast_cli_entry::usage.

13247 {
13248    int channel;
13249    int on;
13250    struct dahdi_pvt *dahdi_chan = NULL;
13251 
13252    switch (cmd) {
13253    case CLI_INIT:
13254       e->command = "dahdi set dnd";
13255       e->usage = 
13256          "Usage: dahdi set dnd <chan#> <on|off>\n"
13257          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13258          "  Changes take effect immediately.\n"
13259          "  <chan num> is the channel number\n"
13260          "  <on|off> Enable or disable DND mode?\n"
13261          ;
13262       return NULL;
13263    case CLI_GENERATE:
13264       return NULL;   
13265    }
13266 
13267    if (a->argc != 5)
13268       return CLI_SHOWUSAGE;
13269 
13270    if ((channel = atoi(a->argv[3])) <= 0) {
13271       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13272       return CLI_SHOWUSAGE;
13273    }
13274    
13275    if (ast_true(a->argv[4]))
13276       on = 1;
13277    else if (ast_false(a->argv[4]))
13278       on = 0;
13279    else {
13280       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13281       return CLI_SHOWUSAGE;
13282    }
13283 
13284    ast_mutex_lock(&iflock);
13285    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13286       if (dahdi_chan->channel != channel)
13287          continue;
13288 
13289       /* Found the channel. Actually set it */
13290       dahdi_dnd(dahdi_chan, on);
13291       break;
13292    }
13293    ast_mutex_unlock(&iflock);
13294 
13295    if (!dahdi_chan) {
13296       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13297       return CLI_FAILURE;
13298    }
13299 
13300    return CLI_SUCCESS;
13301 }

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

Definition at line 2227 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(), mwi_send_thread(), and ss_thread().

02228 {
02229    int x, res;
02230 
02231    x = hs;
02232    res = ioctl(fd, DAHDI_HOOK, &x);
02233 
02234    if (res < 0) {
02235       if (errno == EINPROGRESS)
02236          return 0;
02237       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02238       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02239    }
02240 
02241    return res;
02242 }

static char* dahdi_set_hwgain ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 13103 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, dahdi_subchannel::dfd, errno, ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, dahdi_pvt::subs, and ast_cli_entry::usage.

13104 {
13105    int channel;
13106    int gain;
13107    int tx;
13108    struct dahdi_hwgain hwgain;
13109    struct dahdi_pvt *tmp = NULL;
13110 
13111    switch (cmd) {
13112    case CLI_INIT:
13113       e->command = "dahdi set hwgain";
13114       e->usage = 
13115          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13116          "  Sets the hardware gain on a a given channel, overriding the\n"
13117          "   value provided at module loadtime, whether the channel is in\n"
13118          "   use or not.  Changes take effect immediately.\n"
13119          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13120          "   <chan num> is the channel number relative to the device\n"
13121          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13122       return NULL;
13123    case CLI_GENERATE:
13124       return NULL;   
13125    }
13126 
13127    if (a->argc != 6)
13128       return CLI_SHOWUSAGE;
13129    
13130    if (!strcasecmp("rx", a->argv[3]))
13131       tx = 0; /* rx */
13132    else if (!strcasecmp("tx", a->argv[3]))
13133       tx = 1; /* tx */
13134    else
13135       return CLI_SHOWUSAGE;
13136 
13137    channel = atoi(a->argv[4]);
13138    gain = atof(a->argv[5])*10.0;
13139 
13140    ast_mutex_lock(&iflock);
13141 
13142    for (tmp = iflist; tmp; tmp = tmp->next) {
13143 
13144       if (tmp->channel != channel)
13145          continue;
13146 
13147       if (tmp->subs[SUB_REAL].dfd == -1)
13148          break;
13149 
13150       hwgain.newgain = gain;
13151       hwgain.tx = tx;
13152       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13153          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13154          ast_mutex_unlock(&iflock);
13155          return CLI_FAILURE;
13156       }
13157       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13158          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13159       break;
13160    }
13161 
13162    ast_mutex_unlock(&iflock);
13163 
13164    if (tmp)
13165       return CLI_SUCCESS;
13166 
13167    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13168    return CLI_FAILURE;
13169 
13170 }

static char* dahdi_set_swgain ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 13172 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_subchannel::dfd, ast_cli_args::fd, iflist, iflock, dahdi_pvt::law, lock, dahdi_pvt::next, set_actual_rxgain(), set_actual_txgain(), dahdi_pvt::subs, and ast_cli_entry::usage.

13173 {
13174    int channel;
13175    float gain;
13176    int tx;
13177    int res;
13178    ast_mutex_t *lock;
13179    struct dahdi_pvt *tmp = NULL;
13180 
13181    switch (cmd) {
13182    case CLI_INIT:
13183       e->command = "dahdi set swgain";
13184       e->usage = 
13185          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13186          "  Sets the software gain on a a given channel, overriding the\n"
13187          "   value provided at module loadtime, whether the channel is in\n"
13188          "   use or not.  Changes take effect immediately.\n"
13189          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13190          "   <chan num> is the channel number relative to the device\n"
13191          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13192       return NULL;
13193    case CLI_GENERATE:
13194       return NULL;   
13195    }
13196 
13197    lock = &iflock;
13198 
13199    if (a->argc != 6)
13200       return CLI_SHOWUSAGE;
13201    
13202    if (!strcasecmp("rx", a->argv[3]))
13203       tx = 0; /* rx */
13204    else if (!strcasecmp("tx", a->argv[3]))
13205       tx = 1; /* tx */
13206    else
13207       return CLI_SHOWUSAGE;
13208 
13209    channel = atoi(a->argv[4]);
13210    gain = atof(a->argv[5]);
13211 
13212    ast_mutex_lock(lock);
13213    for (tmp = iflist; tmp; tmp = tmp->next) {
13214 
13215       if (tmp->channel != channel)
13216          continue;
13217 
13218       if (tmp->subs[SUB_REAL].dfd == -1)
13219          break;
13220 
13221       if (tx)
13222          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13223       else
13224          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13225 
13226       if (res) {
13227          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13228          ast_mutex_unlock(lock);
13229          return CLI_FAILURE;
13230       }
13231 
13232       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13233          tx ? "tx" : "rx", gain, channel);
13234       break;
13235    }
13236    ast_mutex_unlock(lock);
13237 
13238    if (tmp)
13239       return CLI_SUCCESS;
13240 
13241    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13242    return CLI_FAILURE;
13243 
13244 }

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

Definition at line 9682 of file chan_dahdi.c.

09683 {
09684    return ioctl(dfd, DAHDI_SETLAW, &law);
09685 }

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

Definition at line 1531 of file chan_dahdi.c.

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

01532 {
01533    int res;
01534    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01535    if (res)
01536       return res;
01537    return 0;
01538 }

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

Definition at line 3849 of file chan_dahdi.c.

References ast_check_hangup(), ast_debug, ast_dsp_set_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(), buf, chan, dahdi_pvt::channel, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_subchannel::dfd, dahdi_pvt::didtdd, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MUTECONF, DSP_DIGITMODE_MUTEMAX, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::law, len(), LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech_pvt, and dahdi_pvt::txgain.

03850 {
03851    char *cp;
03852    signed char *scp;
03853    int x;
03854    int idx;
03855    struct dahdi_pvt *p = chan->tech_pvt, *pp;
03856    struct oprmode *oprmode;
03857    
03858 
03859    /* all supported options require data */
03860    if (!data || (datalen < 1)) {
03861       errno = EINVAL;
03862       return -1;
03863    }
03864 
03865    switch (option) {
03866    case AST_OPTION_TXGAIN:
03867       scp = (signed char *) data;
03868       idx = dahdi_get_index(chan, p, 0);
03869       if (idx < 0) {
03870          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
03871          return -1;
03872       }
03873       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
03874       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
03875    case AST_OPTION_RXGAIN:
03876       scp = (signed char *) data;
03877       idx = dahdi_get_index(chan, p, 0);
03878       if (idx < 0) {
03879          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
03880          return -1;
03881       }
03882       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
03883       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
03884    case AST_OPTION_TONE_VERIFY:
03885       if (!p->dsp)
03886          break;
03887       cp = (char *) data;
03888       switch (*cp) {
03889       case 1:
03890          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
03891          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
03892          break;
03893       case 2:
03894          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
03895          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
03896          break;
03897       default:
03898          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
03899          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
03900          break;
03901       }
03902       break;
03903    case AST_OPTION_TDD:
03904       /* turn on or off TDD */
03905       cp = (char *) data;
03906       p->mate = 0;
03907       if (!*cp) { /* turn it off */
03908          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
03909          if (p->tdd)
03910             tdd_free(p->tdd);
03911          p->tdd = 0;
03912          break;
03913       }
03914       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
03915          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
03916       dahdi_disable_ec(p);
03917       /* otherwise, turn it on */
03918       if (!p->didtdd) { /* if havent done it yet */
03919          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
03920          unsigned char *buf;
03921          int size, res, fd, len;
03922          struct pollfd fds[1];
03923 
03924          buf = mybuf;
03925          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
03926          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
03927          len = 40000;
03928          idx = dahdi_get_index(chan, p, 0);
03929          if (idx < 0) {
03930             ast_log(LOG_WARNING, "No index in TDD?\n");
03931             return -1;
03932          }
03933          fd = p->subs[idx].dfd;
03934          while (len) {
03935             if (ast_check_hangup(chan))
03936                return -1;
03937             size = len;
03938             if (size > READ_SIZE)
03939                size = READ_SIZE;
03940             fds[0].fd = fd;
03941             fds[0].events = POLLPRI | POLLOUT;
03942             fds[0].revents = 0;
03943             res = poll(fds, 1, -1);
03944             if (!res) {
03945                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
03946                continue;
03947             }
03948             /* if got exception */
03949             if (fds[0].revents & POLLPRI)
03950                return -1;
03951             if (!(fds[0].revents & POLLOUT)) {
03952                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
03953                continue;
03954             }
03955             res = write(fd, buf, size);
03956             if (res != size) {
03957                if (res == -1) return -1;
03958                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
03959                break;
03960             }
03961             len -= size;
03962             buf += size;
03963          }
03964          p->didtdd = 1; /* set to have done it now */    
03965       }
03966       if (*cp == 2) { /* Mate mode */
03967          if (p->tdd)
03968             tdd_free(p->tdd);
03969          p->tdd = 0;
03970          p->mate = 1;
03971          break;
03972       }     
03973       if (!p->tdd) { /* if we dont have one yet */
03974          p->tdd = tdd_new(); /* allocate one */
03975       }     
03976       break;
03977    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
03978       if (!p->dsp)
03979          break;
03980       cp = (char *) data;
03981       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
03982          *cp ? "ON" : "OFF", (int) *cp, chan->name);
03983       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
03984       break;
03985    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
03986       cp = (char *) data;
03987       if (!*cp) {    
03988          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
03989          x = 0;
03990          dahdi_disable_ec(p);
03991       } else {    
03992          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
03993          x = 1;
03994       }
03995       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
03996          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
03997       break;
03998    case AST_OPTION_OPRMODE:  /* Operator services mode */
03999       oprmode = (struct oprmode *) data;
04000       pp = oprmode->peer->tech_pvt;
04001       p->oprmode = pp->oprmode = 0;
04002       /* setup peers */
04003       p->oprpeer = pp;
04004       pp->oprpeer = p;
04005       /* setup modes, if any */
04006       if (oprmode->mode) 
04007       {
04008          pp->oprmode = oprmode->mode;
04009          p->oprmode = -oprmode->mode;
04010       }
04011       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
04012          oprmode->mode, chan->name,oprmode->peer->name);
04013       break;
04014    case AST_OPTION_ECHOCAN:
04015       cp = (char *) data;
04016       if (*cp) {
04017          ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
04018          dahdi_enable_ec(p);
04019       } else {
04020          ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
04021          dahdi_disable_ec(p);
04022       }
04023       break;
04024    }
04025    errno = 0;
04026 
04027    return 0;
04028 }

static char* dahdi_show_channel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12755 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, 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, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::confno, dahdi_pvt::context, dahdi_pvt::destroy, dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::dnd, dahdi_pvt::dsp, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echocanon, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, ast_cli_args::fd, dahdi_pvt::head, iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, ISTRUNK, dahdi_pvt::law, dahdi_subchannel::linear, lock, dahdi_pvt::logicalspan, dahdi_pvt::mailbox, dahdi_pvt::master, ast_channel::name, ast_variable::name, ast_variable::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::pri, dahdi_pri::pri, pris, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::resetting, S_OR, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, SUB_CALLWAIT, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, ast_cli_entry::usage, ast_variable::value, and dahdi_pvt::vars.

12756 {
12757    int channel;
12758    struct dahdi_pvt *tmp = NULL;
12759    struct dahdi_confinfo ci;
12760    struct dahdi_params ps;
12761    int x;
12762    ast_mutex_t *lock;
12763    struct dahdi_pvt *start;
12764 #ifdef HAVE_PRI
12765    char *c;
12766    int trunkgroup;
12767    struct dahdi_pri *pri=NULL;
12768 #endif
12769    switch (cmd) {
12770    case CLI_INIT:
12771       e->command = "dahdi show channel";
12772       e->usage = 
12773          "Usage: dahdi show channel <chan num>\n"
12774          "  Detailed information about a given channel\n";
12775       return NULL;
12776    case CLI_GENERATE:
12777       return NULL;   
12778    }
12779 
12780    lock = &iflock;
12781    start = iflist;
12782 
12783    if (a->argc != 4)
12784       return CLI_SHOWUSAGE;
12785 #ifdef HAVE_PRI
12786    if ((c = strchr(a->argv[3], ':'))) {
12787       if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2)
12788          return CLI_SHOWUSAGE;
12789       if ((trunkgroup < 1) || (channel < 1))
12790          return CLI_SHOWUSAGE;
12791       for (x = 0; x < NUM_SPANS; x++) {
12792          if (pris[x].trunkgroup == trunkgroup) {
12793             pri = pris + x;
12794             break;
12795          }
12796       }
12797       if (pri) {
12798          start = pri->crvs;
12799          lock = &pri->lock;
12800       } else {
12801          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12802          return CLI_FAILURE;
12803       }
12804    } else
12805 #endif
12806       channel = atoi(a->argv[3]);
12807 
12808    ast_mutex_lock(lock);
12809    tmp = start;
12810    while (tmp) {
12811       if (tmp->channel == channel) {
12812 #ifdef HAVE_PRI
12813          if (pri) 
12814             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12815          else
12816 #endif         
12817          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12818          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12819          ast_cli(a->fd, "Span: %d\n", tmp->span);
12820          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12821          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12822          ast_cli(a->fd, "Context: %s\n", tmp->context);
12823          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12824          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12825          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12826          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12827          if (tmp->vars) {
12828             struct ast_variable *v;
12829             ast_cli(a->fd, "Variables:\n");
12830             for (v = tmp->vars ; v ; v = v->next)
12831                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
12832          }
12833          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12834          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12835          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12836          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12837          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12838          ast_cli(a->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)" : "");
12839          ast_cli(a->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)" : "");
12840          ast_cli(a->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)" : "");
12841          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12842          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12843          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12844          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12845          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12846          if (tmp->busydetect) {
12847 #if defined(BUSYDETECT_TONEONLY)
12848             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12849 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12850             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12851 #endif
12852 #ifdef BUSYDETECT_DEBUG
12853             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
12854 #endif
12855             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
12856             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
12857          }
12858          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12859          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12860          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12861          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12862          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12863          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12864          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12865          ast_cli(a->fd, "Echo Cancellation:\n");
12866 
12867          if (tmp->echocancel.head.tap_length) {
12868             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12869             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12870                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12871             }
12872             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12873          } else {
12874             ast_cli(a->fd, "\tnone\n");
12875          }
12876          if (tmp->master)
12877             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12878          for (x = 0; x < MAX_SLAVES; x++) {
12879             if (tmp->slaves[x])
12880                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12881          }
12882 #ifdef HAVE_SS7
12883          if (tmp->ss7) {
12884             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12885          }
12886 #endif
12887 #ifdef HAVE_PRI
12888          if (tmp->pri) {
12889             ast_cli(a->fd, "PRI Flags: ");
12890             if (tmp->resetting)
12891                ast_cli(a->fd, "Resetting ");
12892             if (tmp->call)
12893                ast_cli(a->fd, "Call ");
12894             if (tmp->bearer)
12895                ast_cli(a->fd, "Bearer ");
12896             ast_cli(a->fd, "\n");
12897             if (tmp->logicalspan) 
12898                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12899             else
12900                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12901          }
12902             
12903 #endif
12904          memset(&ci, 0, sizeof(ci));
12905          ps.channo = tmp->channel;
12906          if (tmp->subs[SUB_REAL].dfd > -1) {
12907             memset(&ci, 0, sizeof(ci));
12908             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12909                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12910             }
12911             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12912                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12913             }
12914             memset(&ps, 0, sizeof(ps));
12915             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12916                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12917             } else {
12918                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12919             }
12920          }
12921          if (ISTRUNK(tmp)) {
12922             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
12923             if (!ast_strlen_zero(progzone))
12924                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
12925             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
12926             if(tmp->busydetect) {
12927                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
12928                if(tmp->busytonelength > 0) {
12929                   ast_cli(a->fd, "Busy Pattern:\n");
12930                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12931                   if (tmp->busyquietlength > 0) 
12932                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12933                   else 
12934                      ast_cli(a->fd, " -- Detect Tone Only\n");
12935                   if(tmp->busyfuzziness > 0)
12936                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12937                }
12938             }
12939          }
12940          ast_mutex_unlock(lock);
12941          return CLI_SUCCESS;
12942       }
12943       tmp = tmp->next;
12944    }
12945    
12946    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12947    ast_mutex_unlock(lock);
12948    return CLI_FAILURE;
12949 }

static char* dahdi_show_channels ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12631 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::channel, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, dahdi_pvt::context, dahdi_pvt::exten, ast_cli_args::fd, FORMAT, FORMAT2, dahdi_pvt::group, iflist, iflock, dahdi_pvt::language, dahdi_pvt::locallyblocked, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, NUM_SPANS, dahdi_pri::pri, pris, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.

12632 {
12633 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12634 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12635    unsigned int targetnum = 0;
12636    int filtertype = 0;
12637    struct dahdi_pvt *tmp = NULL;
12638    char tmps[20] = "";
12639    char statestr[20] = "";
12640    char blockstr[20] = "";
12641    ast_mutex_t *lock;
12642    struct dahdi_pvt *start;
12643 #ifdef HAVE_PRI
12644    int trunkgroup;
12645    struct dahdi_pri *pri = NULL;
12646    int x;
12647 #endif
12648    switch (cmd) {
12649    case CLI_INIT:
12650       e->command = "dahdi show channels [trunkgroup|group|context]";
12651       e->usage = 
12652          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12653          "  Shows a list of available channels with optional filtering\n"
12654          "  <group> must be a number between 0 and 63\n";
12655       return NULL;
12656    case CLI_GENERATE:
12657       return NULL;   
12658    }
12659 
12660    lock = &iflock;
12661    start = iflist;
12662 
12663    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12664 
12665    if (!((a->argc == 3) || (a->argc == 5)))
12666       return CLI_SHOWUSAGE;
12667 
12668    if (a->argc == 5) {
12669 #ifdef HAVE_PRI
12670       if (!strcasecmp(a->argv[3], "trunkgroup")) {
12671          /* this option requires no special handling, so leave filtertype to zero */
12672          if ((trunkgroup = atoi(a->argv[4])) < 1)
12673             return CLI_SHOWUSAGE;
12674          for (x = 0; x < NUM_SPANS; x++) {
12675             if (pris[x].trunkgroup == trunkgroup) {
12676                pri = pris + x;
12677                break;
12678             }
12679          }
12680          if (pri) {
12681             start = pri->crvs;
12682             lock = &pri->lock;
12683          } else {
12684             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12685             return CLI_FAILURE;
12686          }
12687       } else
12688 #endif   
12689       if (!strcasecmp(a->argv[3], "group")) {
12690          targetnum = atoi(a->argv[4]);
12691          if ((targetnum < 0) || (targetnum > 63))
12692             return CLI_SHOWUSAGE;
12693          targetnum = 1 << targetnum;
12694          filtertype = 1;
12695       } else if (!strcasecmp(a->argv[3], "context")) {
12696          filtertype = 2;
12697       }
12698    }
12699 
12700    ast_mutex_lock(lock);
12701 #ifdef HAVE_PRI
12702    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12703 #else
12704    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12705 #endif   
12706    
12707    tmp = start;
12708    while (tmp) {
12709       if (filtertype) {
12710          switch(filtertype) {
12711          case 1: /* dahdi show channels group <group> */
12712             if (tmp->group != targetnum) {
12713                tmp = tmp->next;
12714                continue;
12715             }
12716             break;
12717          case 2: /* dahdi show channels context <context> */
12718             if (strcasecmp(tmp->context, a->argv[4])) {
12719                tmp = tmp->next;
12720                continue;
12721             }
12722             break;
12723          default:
12724             ;
12725          }
12726       }
12727       if (tmp->channel > 0) {
12728          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12729       } else
12730          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12731 
12732       if (tmp->locallyblocked)
12733          blockstr[0] = 'L';
12734       else
12735          blockstr[0] = ' ';
12736 
12737       if (tmp->remotelyblocked)
12738          blockstr[1] = 'R';
12739       else
12740          blockstr[1] = ' ';
12741 
12742       blockstr[2] = '\0';
12743 
12744       snprintf(statestr, sizeof(statestr), "%s", "In Service");
12745 
12746       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12747       tmp = tmp->next;
12748    }
12749    ast_mutex_unlock(lock);
12750    return CLI_SUCCESS;
12751 #undef FORMAT
12752 #undef FORMAT2
12753 }

static char* dahdi_show_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12988 of file chan_dahdi.c.

References ast_cli(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, ast_cli_entry::command, errno, ast_cli_args::fd, FORMAT, FORMAT2, and ast_cli_entry::usage.

12989 {
12990    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12991    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12992    int span;
12993    int res;
12994    char alarmstr[50];
12995 
12996    int ctl;
12997    struct dahdi_spaninfo s;
12998 
12999    switch (cmd) {
13000    case CLI_INIT:
13001       e->command = "dahdi show status";
13002       e->usage = 
13003          "Usage: dahdi show status\n"
13004          "       Shows a list of DAHDI cards with status\n";
13005       return NULL;
13006    case CLI_GENERATE:
13007       return NULL;   
13008    }
13009    ctl = open("/dev/dahdi/ctl", O_RDWR);
13010    if (ctl < 0) {
13011       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13012       return CLI_FAILURE;
13013    }
13014    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13015 
13016    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13017       s.spanno = span;
13018       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13019       if (res) {
13020          continue;
13021       }
13022       alarmstr[0] = '\0';
13023       if (s.alarms > 0) {
13024          if (s.alarms & DAHDI_ALARM_BLUE)
13025             strcat(alarmstr, "BLU/");
13026          if (s.alarms & DAHDI_ALARM_YELLOW)
13027             strcat(alarmstr, "YEL/");
13028          if (s.alarms & DAHDI_ALARM_RED)
13029             strcat(alarmstr, "RED/");
13030          if (s.alarms & DAHDI_ALARM_LOOPBACK)
13031             strcat(alarmstr, "LB/");
13032          if (s.alarms & DAHDI_ALARM_RECOVER)
13033             strcat(alarmstr, "REC/");
13034          if (s.alarms & DAHDI_ALARM_NOTOPEN)
13035             strcat(alarmstr, "NOP/");
13036          if (!strlen(alarmstr))
13037             strcat(alarmstr, "UUU/");
13038          if (strlen(alarmstr)) {
13039             /* Strip trailing / */
13040             alarmstr[strlen(alarmstr) - 1] = '\0';
13041          }
13042       } else {
13043          if (s.numchans)
13044             strcpy(alarmstr, "OK");
13045          else
13046             strcpy(alarmstr, "UNCONFIGURED");
13047       }
13048 
13049       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13050             , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13051               s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13052               s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13053               "CAS"
13054             , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13055               s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13056               s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13057               "Unk"
13058             , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13059               s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13060             , lbostr[s.lbo]
13061          );
13062    }
13063    close(ctl);
13064 
13065    return CLI_SUCCESS;
13066 #undef FORMAT
13067 #undef FORMAT2
13068 }

static char* dahdi_show_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 13070 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, errno, ast_cli_args::fd, and ast_cli_entry::usage.

13071 {
13072    int pseudo_fd = -1;
13073    struct dahdi_versioninfo vi;
13074 
13075    switch (cmd) {
13076    case CLI_INIT:
13077       e->command = "dahdi show version";
13078       e->usage = 
13079          "Usage: dahdi show version\n"
13080          "       Shows the DAHDI version in use\n";
13081       return NULL;
13082    case CLI_GENERATE:
13083       return NULL;
13084    }
13085    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13086       ast_cli(a->fd, "Failed to open control file to get version.\n");
13087       return CLI_SUCCESS;
13088    }
13089 
13090    strcpy(vi.version, "Unknown");
13091    strcpy(vi.echo_canceller, "Unknown");
13092 
13093    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13094       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13095    else
13096       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13097 
13098    close(pseudo_fd);
13099 
13100    return CLI_SUCCESS;
13101 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 1774 of file chan_dahdi.c.

References buf, SIG_BRI, SIG_BRI_PTMP, 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, and SIG_SS7.

01775 {
01776    static char buf[256];
01777    switch (sig) {
01778    case SIG_EM:
01779       return "E & M Immediate";
01780    case SIG_EMWINK:
01781       return "E & M Wink";
01782    case SIG_EM_E1:
01783       return "E & M E1";
01784    case SIG_FEATD:
01785       return "Feature Group D (DTMF)";
01786    case SIG_FEATDMF:
01787       return "Feature Group D (MF)";
01788    case SIG_FEATDMF_TA:
01789       return "Feature Groud D (MF) Tandem Access";
01790    case SIG_FEATB:
01791       return "Feature Group B (MF)";
01792    case SIG_E911:
01793       return "E911 (MF)";
01794    case SIG_FGC_CAMA:
01795       return "FGC/CAMA (Dialpulse)";
01796    case SIG_FGC_CAMAMF:
01797       return "FGC/CAMA (MF)";
01798    case SIG_FXSLS:
01799       return "FXS Loopstart";
01800    case SIG_FXSGS:
01801       return "FXS Groundstart";
01802    case SIG_FXSKS:
01803       return "FXS Kewlstart";
01804    case SIG_FXOLS:
01805       return "FXO Loopstart";
01806    case SIG_FXOGS:
01807       return "FXO Groundstart";
01808    case SIG_FXOKS:
01809       return "FXO Kewlstart";
01810    case SIG_PRI:
01811       return "ISDN PRI";
01812    case SIG_BRI:
01813       return "ISDN BRI Point to Point";
01814    case SIG_BRI_PTMP:
01815       return "ISDN BRI Point to MultiPoint";
01816    case SIG_SS7:
01817       return "SS7";
01818    case SIG_SF:
01819       return "SF (Tone) Immediate";
01820    case SIG_SFWINK:
01821       return "SF (Tone) Wink";
01822    case SIG_SF_FEATD:
01823       return "SF (Tone) with Feature Group D (DTMF)";
01824    case SIG_SF_FEATDMF:
01825       return "SF (Tone) with Feature Group D (MF)";
01826    case SIG_SF_FEATB:
01827       return "SF (Tone) with Feature Group B (MF)";
01828    case SIG_GR303FXOKS:
01829       return "GR-303 with FXOKS";
01830    case SIG_GR303FXSKS:
01831       return "GR-303 with FXSKS";
01832    case 0:
01833       return "Pseudo";
01834    default:
01835       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01836       return buf;
01837    }
01838 }

static void dahdi_softhangup_all ( void   )  [static]

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

12452 {
12453    struct dahdi_pvt *p;
12454 retry:
12455    ast_mutex_lock(&iflock);
12456     for (p = iflist; p; p = p->next) {
12457       ast_mutex_lock(&p->lock);
12458         if (p->owner && !p->restartpending) {
12459          if (ast_channel_trylock(p->owner)) {
12460             if (option_debug > 2)
12461                ast_verbose("Avoiding deadlock\n");
12462             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
12463             ast_mutex_unlock(&p->lock);
12464             ast_mutex_unlock(&iflock);
12465             goto retry;
12466          }
12467          if (option_debug > 2)
12468             ast_verbose("Softhanging up on %s\n", p->owner->name);
12469          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12470          p->restartpending = 1;
12471          num_restart_pending++;
12472          ast_channel_unlock(p->owner);
12473       }
12474       ast_mutex_unlock(&p->lock);
12475     }
12476    ast_mutex_unlock(&iflock);
12477 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2056 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_pvt::echocanon, dahdi_pvt::echotraining, errno, LOG_WARNING, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_answer(), and dahdi_handle_event().

02057 {
02058    int x;
02059    int res;
02060    
02061    if (p && p->echocanon && p->echotraining) {
02062       x = p->echotraining;
02063       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02064       if (res)
02065          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02066       else
02067          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02068    } else {
02069       ast_debug(1, "No echo training requested\n");
02070    }
02071 }

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

Definition at line 4049 of file chan_dahdi.c.

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

Referenced by dahdi_bridge(), and dahdi_fixup().

04050 {
04051    /* Unlink a specific slave or all slaves/masters from a given master */
04052    int x;
04053    int hasslaves;
04054    if (!master)
04055       return;
04056    if (needlock) {
04057       ast_mutex_lock(&master->lock);
04058       if (slave) {
04059          while (ast_mutex_trylock(&slave->lock)) {
04060             DEADLOCK_AVOIDANCE(&master->lock);
04061          }
04062       }
04063    }
04064    hasslaves = 0;
04065    for (x = 0; x < MAX_SLAVES; x++) {
04066       if (master->slaves[x]) {
04067          if (!slave || (master->slaves[x] == slave)) {
04068             /* Take slave out of the conference */
04069             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04070             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04071             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04072             master->slaves[x]->master = NULL;
04073             master->slaves[x] = NULL;
04074          } else
04075             hasslaves = 1;
04076       }
04077       if (!hasslaves)
04078          master->inconference = 0;
04079    }
04080    if (!slave) {
04081       if (master->master) {
04082          /* Take master out of the conference */
04083          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04084          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04085          hasslaves = 0;
04086          for (x = 0; x < MAX_SLAVES; x++) {
04087             if (master->master->slaves[x] == master)
04088                master->master->slaves[x] = NULL;
04089             else if (master->master->slaves[x])
04090                hasslaves = 1;
04091          }
04092          if (!hasslaves)
04093             master->master->inconference = 0;
04094       }
04095       master->master = NULL;
04096    }
04097    update_conf(master);
04098    if (needlock) {
04099       if (slave)
04100          ast_mutex_unlock(&slave->lock);
04101       ast_mutex_unlock(&master->lock);
04102    }
04103 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 312 of file chan_dahdi.c.

Referenced by flash_exec(), and ss_thread().

00313 {
00314    int i, j = 0;
00315    i = DAHDI_IOMUX_SIGEVENT;
00316    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00317       return -1;
00318    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00319       return -1;
00320    return j;
00321 }

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

Definition at line 6490 of file chan_dahdi.c.

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

Referenced by ss_thread().

06491 {
06492    int j;
06493    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06494    for (;;)
06495    {
06496          /* set bits of interest */
06497       j = DAHDI_IOMUX_SIGEVENT;
06498           /* wait for some happening */
06499       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06500          /* exit loop if we have it */
06501       if (j & DAHDI_IOMUX_SIGEVENT) break;
06502    }
06503      /* get the event info */
06504    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06505    return 0;
06506 }

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

Definition at line 5967 of file chan_dahdi.c.

References ast_debug, 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, my_dahdi_write(), ast_channel::name, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, ast_frame::ptr, PVT_TO_CHANNEL, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

05968 {
05969    struct dahdi_pvt *p = ast->tech_pvt;
05970    int res;
05971    int idx;
05972    idx = dahdi_get_index(ast, p, 0);
05973    if (idx < 0) {
05974       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
05975       return -1;
05976    }
05977 
05978 #if 0
05979 #ifdef HAVE_PRI
05980    ast_mutex_lock(&p->lock);
05981    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
05982       if (p->pri->pri) {      
05983          if (!pri_grab(p, p->pri)) {
05984                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
05985                pri_rel(p->pri);
05986          } else
05987                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
05988       }
05989       p->proceeding=1;
05990    }
05991    ast_mutex_unlock(&p->lock);
05992 #endif
05993 #endif
05994    /* Write a frame of (presumably voice) data */
05995    if (frame->frametype != AST_FRAME_VOICE) {
05996       if (frame->frametype != AST_FRAME_IMAGE)
05997          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
05998       return 0;
05999    }
06000    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06001        (frame->subclass != AST_FORMAT_ULAW) &&
06002        (frame->subclass != AST_FORMAT_ALAW)) {
06003       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06004       return -1;
06005    }
06006    if (p->dialing) {
06007       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06008       return 0;
06009    }
06010    if (!p->owner) {
06011       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06012       return 0;
06013    }
06014    if (p->cidspill) {
06015       ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06016       return 0;
06017    }
06018    /* Return if it's not valid data */
06019    if (!frame->data.ptr || !frame->datalen)
06020       return 0;
06021 
06022    if (frame->subclass == AST_FORMAT_SLINEAR) {
06023       if (!p->subs[idx].linear) {
06024          p->subs[idx].linear = 1;
06025          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06026          if (res)
06027             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06028       }
06029       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06030    } else {
06031       /* x-law already */
06032       if (p->subs[idx].linear) {
06033          p->subs[idx].linear = 0;
06034          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06035          if (res)
06036             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06037       }
06038       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06039    }
06040    if (res < 0) {
06041       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06042       return -1;
06043    } 
06044    return 0;
06045 }

static void destroy_all_channels ( void   )  [static]

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

03234 {
03235    int x;
03236    struct dahdi_pvt *p, *pl;
03237 
03238    while (num_restart_pending) {
03239       usleep(1);
03240    }
03241 
03242    ast_mutex_lock(&iflock);
03243    /* Destroy all the interfaces and free their memory */
03244    p = iflist;
03245    while (p) {
03246       /* Free any callerid */
03247       if (p->cidspill)
03248          ast_free(p->cidspill);
03249       pl = p;
03250       p = p->next;
03251       x = pl->channel;
03252       /* Free associated memory */
03253       if (pl)
03254          destroy_dahdi_pvt(&pl);
03255       if (option_verbose > 2) 
03256          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03257    }
03258    iflist = NULL;
03259    ifcount = 0;
03260    ast_mutex_unlock(&iflock);
03261 }

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

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

03184 {
03185    int owned = 0;
03186    int i = 0;
03187 
03188    if (!now) {
03189       if (cur->owner) {
03190          owned = 1;
03191       }
03192 
03193       for (i = 0; i < 3; i++) {
03194          if (cur->subs[i].owner) {
03195             owned = 1;
03196          }
03197       }
03198       if (!owned) {
03199          if (prev) {
03200             prev->next = cur->next;
03201             if (prev->next)
03202                prev->next->prev = prev;
03203             else
03204                ifend = prev;
03205          } else {
03206             iflist = cur->next;
03207             if (iflist)
03208                iflist->prev = NULL;
03209             else
03210                ifend = NULL;
03211          }
03212          destroy_dahdi_pvt(&cur);
03213       }
03214    } else {
03215       if (prev) {
03216          prev->next = cur->next;
03217          if (prev->next)
03218             prev->next->prev = prev;
03219          else
03220             ifend = prev;
03221       } else {
03222          iflist = cur->next;
03223          if (iflist)
03224             iflist->prev = NULL;
03225          else
03226             ifend = NULL;
03227       }
03228       destroy_dahdi_pvt(&cur);
03229    }
03230    return 0;
03231 }

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

Definition at line 3161 of file chan_dahdi.c.

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

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

03162 {
03163    struct dahdi_pvt *p = *pvt;
03164    /* Remove channel from the list */
03165    if (p->prev)
03166       p->prev->next = p->next;
03167    if (p->next)
03168       p->next->prev = p->prev;
03169    if (p->use_smdi)
03170       ast_smdi_interface_unref(p->smdi_iface);
03171    if (p->mwi_event_sub)
03172       ast_event_unsubscribe(p->mwi_event_sub);
03173    if (p->vars)
03174       ast_variables_destroy(p->vars);
03175    ast_mutex_destroy(&p->lock);
03176    dahdi_close_sub(p, SUB_REAL);
03177    if (p->owner)
03178       p->owner->tech_pvt = NULL;
03179    free(p);
03180    *pvt = NULL;
03181 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 1765 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

01766 {
01767    if (dialplan == -1 || dialplan == -2) {
01768       return("Dynamically set dialplan in ISDN");
01769    }
01770    return (pri_plan2str(dialplan));
01771 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1595 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

01596 {
01597    if (isdigit(digit))
01598       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01599    else if (digit >= 'A' && digit <= 'D')
01600       return DAHDI_TONE_DTMF_A + (digit - 'A');
01601    else if (digit >= 'a' && digit <= 'd')
01602       return DAHDI_TONE_DTMF_A + (digit - 'a');
01603    else if (digit == '*')
01604       return DAHDI_TONE_DTMF_s;
01605    else if (digit == '#')
01606       return DAHDI_TONE_DTMF_p;
01607    else
01608       return -1;
01609 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4128 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

04129 {
04130    int val;
04131 
04132    p->ignoredtmf = 1;
04133 
04134    val = 0;
04135    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04136 
04137    if (!p->hardwaredtmf && p->dsp) {
04138       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04139       ast_dsp_set_features(p->dsp, p->dsp_features);
04140    }
04141 }

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

Definition at line 10635 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_verb, ast_waitfor(), chan, dahdi_pvt::channel, ast_channel::context, ast_channel::exten, f, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, ast_channel::name, dahdi_pvt::pri, ast_channel::priority, and ast_channel::tech_pvt.

Referenced by pri_dchannel().

10636 {
10637    struct ast_channel *chan = vchan;
10638    struct dahdi_pvt *pvt = chan->tech_pvt;
10639    struct ast_frame *f;
10640    char ex[80];
10641    /* Wait up to 30 seconds for an answer */
10642    int newms, ms = 30000;
10643    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10644    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10645    if (ast_call(chan, ex, 0)) {
10646       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10647       ast_hangup(chan);
10648       return NULL;
10649    }
10650    while ((newms = ast_waitfor(chan, ms)) > 0) {
10651       f = ast_read(chan);
10652       if (!f) {
10653          /* Got hangup */
10654          break;
10655       }
10656       if (f->frametype == AST_FRAME_CONTROL) {
10657          switch (f->subclass) {
10658          case AST_CONTROL_ANSWER:
10659             /* Launch the PBX */
10660             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10661             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10662             chan->priority = 1;
10663             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10664             ast_pbx_run(chan);
10665             /* It's already hungup, return immediately */
10666             return NULL;
10667          case AST_CONTROL_BUSY:
10668             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10669             break;
10670          case AST_CONTROL_CONGESTION:
10671             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10672             break;
10673          };
10674       }
10675       ast_frfree(f);
10676       ms = newms;
10677    }
10678    /* Hangup the channel since nothing happend */
10679    ast_hangup(chan);
10680    return NULL;
10681 }

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

Definition at line 8306 of file chan_dahdi.c.

References ast_calloc, ast_debug, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), buf, dahdi_pvt::cidspill, iflist, iflock, last, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

08307 {
08308    int count, res, res2, spoint, pollres=0;
08309    struct dahdi_pvt *i;
08310    struct dahdi_pvt *last = NULL;
08311    time_t thispass = 0, lastpass = 0;
08312    int found;
08313    char buf[1024];
08314    struct pollfd *pfds=NULL;
08315    int lastalloc = -1;
08316    /* This thread monitors all the frame relay interfaces which are not yet in use
08317       (and thus do not have a separate thread) indefinitely */
08318    /* From here on out, we die whenever asked */
08319 #if 0
08320    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08321       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08322       return NULL;
08323    }
08324    ast_debug(1, "Monitor starting...\n");
08325 #endif
08326    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08327 
08328    for (;;) {
08329       /* Lock the interface list */
08330       ast_mutex_lock(&iflock);
08331       if (!pfds || (lastalloc != ifcount)) {
08332          if (pfds) {
08333             ast_free(pfds);
08334             pfds = NULL;
08335          }
08336          if (ifcount) {
08337             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08338                ast_mutex_unlock(&iflock);
08339                return NULL;
08340             }
08341          }
08342          lastalloc = ifcount;
08343       }
08344       /* Build the stuff we're going to poll on, that is the socket of every
08345          dahdi_pvt that does not have an associated owner channel */
08346       count = 0;
08347       i = iflist;
08348       while (i) {
08349          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08350             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
08351                /* This needs to be watched, as it lacks an owner */
08352                pfds[count].fd = i->subs[SUB_REAL].dfd;
08353                pfds[count].events = POLLPRI;
08354                pfds[count].revents = 0;
08355                /* If we are monitoring for VMWI or sending CID, we need to
08356                   read from the channel as well */
08357                if (i->cidspill || i->mwimonitor_fsk)
08358                   pfds[count].events |= POLLIN;
08359                count++;
08360             }
08361          }
08362          i = i->next;
08363       }
08364       /* Okay, now that we know what to do, release the interface lock */
08365       ast_mutex_unlock(&iflock);
08366       
08367       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08368       pthread_testcancel();
08369       /* Wait at least a second for something to happen */
08370       res = poll(pfds, count, 1000);
08371       pthread_testcancel();
08372       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08373 
08374       /* Okay, poll has finished.  Let's see what happened.  */
08375       if (res < 0) {
08376          if ((errno != EAGAIN) && (errno != EINTR))
08377             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08378          continue;
08379       }
08380       /* Alright, lock the interface list again, and let's look and see what has
08381          happened */
08382       ast_mutex_lock(&iflock);
08383       found = 0;
08384       spoint = 0;
08385       lastpass = thispass;
08386       thispass = time(NULL);
08387       i = iflist;
08388       while (i) {
08389          if (thispass != lastpass) {
08390             if (!found && ((i == last) || ((i == iflist) && !last))) {
08391                last = i;
08392                if (last) {
08393                   if (!last->mwisendactive &&    last->sig & __DAHDI_SIG_FXO) {
08394                      res = has_voicemail(last);
08395                      if (last->msgstate != res) {
08396 
08397                         /* This channel has a new voicemail state,
08398                         * initiate a thread to send an MWI message
08399                         */
08400                         pthread_attr_t attr;
08401                         pthread_t threadid;
08402                         struct mwi_thread_data *mtd;
08403                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08404                         if (res2) {
08405                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
08406                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08407                         }
08408                         pthread_attr_init(&attr);
08409                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08410                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08411                            last->msgstate = res;
08412                            mtd->pvt = last;
08413                            last->mwisendactive = 1;
08414                            if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
08415                               ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
08416                               ast_free(mtd);
08417                               last->mwisendactive = 0;
08418                            }
08419                         }
08420                         found ++;
08421                      }
08422                   }
08423                   last = last->next;
08424                }
08425             }
08426          }
08427          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08428             if (i->radio && !i->owner)
08429             {
08430                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08431                if (res)
08432                {
08433                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08434                   /* Don't hold iflock while handling init events */
08435                   ast_mutex_unlock(&iflock);
08436                   handle_init_event(i, res);
08437                   ast_mutex_lock(&iflock);   
08438                }
08439                i = i->next;
08440                continue;
08441             }              
08442             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08443             if (pollres & POLLIN) {
08444                if (i->owner || i->subs[SUB_REAL].owner) {
08445 #ifdef HAVE_PRI
08446                   if (!i->pri)
08447 #endif                  
08448                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08449                   i = i->next;
08450                   continue;
08451                }
08452                if (!i->cidspill && !i->mwimonitor_fsk) {
08453                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08454                   i = i->next;
08455                   continue;
08456                }
08457                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08458                if (res > 0) {
08459                   if (i->mwimonitor_fsk) {
08460                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08461                         pthread_attr_t attr;
08462                         pthread_t threadid;
08463                         struct mwi_thread_data *mtd;
08464 
08465                         pthread_attr_init(&attr);
08466                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08467 
08468                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08469                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08470                            mtd->pvt = i;
08471                            memcpy(mtd->buf, buf, res);
08472                            mtd->len = res;
08473                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08474                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08475                               ast_free(mtd);
08476                            }
08477                            i->mwimonitoractive = 1;
08478                         }
08479                      }
08480                   }
08481                } else {
08482                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08483                }
08484             }
08485             if (pollres & POLLPRI) {
08486                if (i->owner || i->subs[SUB_REAL].owner) {
08487 #ifdef HAVE_PRI
08488                   if (!i->pri)
08489 #endif                  
08490                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08491                   i = i->next;
08492                   continue;
08493                }
08494                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08495                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08496                /* Don't hold iflock while handling init events */
08497                ast_mutex_unlock(&iflock);
08498                handle_init_event(i, res);
08499                ast_mutex_lock(&iflock);   
08500             }
08501          }
08502          i=i->next;
08503       }
08504       ast_mutex_unlock(&iflock);
08505    }
08506    /* Never reached */
08507    return NULL;
08508    
08509 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4143 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

04144 {
04145    int val;
04146 
04147    if (p->channel == CHAN_PSEUDO)
04148       return;
04149 
04150    p->ignoredtmf = 0;
04151 
04152    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04153    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04154 
04155    if (!p->hardwaredtmf && p->dsp) {
04156       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04157       ast_dsp_set_features(p->dsp, p->dsp_features);
04158    }
04159 }

static char* event2str ( int  event  )  [static]

Definition at line 1755 of file chan_dahdi.c.

References ARRAY_LEN, and buf.

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

01756 {
01757    static char buf[256];
01758    if ((event < (ARRAY_LEN(events))) && (event > -1))
01759       return events[event];
01760    sprintf(buf, "Event %d", event); /* safe */
01761    return buf;
01762 }

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

Definition at line 2125 of file chan_dahdi.c.

References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_rxgain().

02126 {
02127    int j;
02128    int k;
02129    float linear_gain = pow(10.0, gain / 20.0);
02130 
02131    switch (law) {
02132    case DAHDI_LAW_ALAW:
02133       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02134          if (gain) {
02135             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02136             if (k > 32767) k = 32767;
02137             if (k < -32767) k = -32767;
02138             g->rxgain[j] = AST_LIN2A(k);
02139          } else {
02140             g->rxgain[j] = j;
02141          }
02142       }
02143       break;
02144    case DAHDI_LAW_MULAW:
02145       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02146          if (gain) {
02147             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02148             if (k > 32767) k = 32767;
02149             if (k < -32767) k = -32767;
02150             g->rxgain[j] = AST_LIN2MU(k);
02151          } else {
02152             g->rxgain[j] = j;
02153          }
02154       }
02155       break;
02156    }
02157 }

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

Definition at line 2091 of file chan_dahdi.c.

References ARRAY_LEN, AST_ALAW, AST_LIN2A, AST_LIN2MU, and AST_MULAW.

Referenced by set_actual_txgain().

02092 {
02093    int j;
02094    int k;
02095    float linear_gain = pow(10.0, gain / 20.0);
02096 
02097    switch (law) {
02098    case DAHDI_LAW_ALAW:
02099       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02100          if (gain) {
02101             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02102             if (k > 32767) k = 32767;
02103             if (k < -32767) k = -32767;
02104             g->txgain[j] = AST_LIN2A(k);
02105          } else {
02106             g->txgain[j] = j;
02107          }
02108       }
02109       break;
02110    case DAHDI_LAW_MULAW:
02111       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02112          if (gain) {
02113             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02114             if (k > 32767) k = 32767;
02115             if (k < -32767) k = -32767;
02116             g->txgain[j] = AST_LIN2MU(k);
02117          } else {
02118             g->txgain[j] = j;
02119          }
02120       }
02121       break;
02122    }
02123 }

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

Definition at line 13335 of file chan_dahdi.c.

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

Referenced by action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_transfer(), and action_transferhangup().

13336 {
13337    struct dahdi_pvt *p = iflist;
13338    while (p) {
13339       if (p->channel == channel) {
13340          break;
13341       }
13342       p = p->next;
13343    }
13344    return p;
13345 }

static int get_alarms ( struct dahdi_pvt p  )  [static]

Checks channel for alarms

Parameters:
p a channel to check for alarms.
Returns:
the alarms on the span to which the channel belongs, or alarms on the channel if no span alarms.

Definition at line 4587 of file chan_dahdi.c.

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

Referenced by action_dahdishowchannels(), dahdi_handle_event(), handle_init_event(), and mwi_thread().

04588 {
04589    int res;
04590    struct dahdi_spaninfo zi;
04591    struct dahdi_params params;
04592 
04593    memset(&zi, 0, sizeof(zi));
04594    zi.spanno = p->span;
04595 
04596    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04597       if (zi.alarms != DAHDI_ALARM_NONE)
04598          return zi.alarms;
04599    } else {
04600       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04601       return 0;
04602    }
04603 
04604    /* No alarms on the span. Check for channel alarms. */
04605    memset(&params, 0, sizeof(params));
04606    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04607       return params.chan_alarms;
04608 
04609    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04610 
04611    return DAHDI_ALARM_NONE;
04612 }

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

Definition at line 4680 of file chan_dahdi.c.

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

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

04681 {
04682    const char *alarm_str = alarm2str(alms);
04683 
04684    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04685    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04686             "Alarm: %s\r\n"
04687             "Channel: %d\r\n",
04688             alarm_str, p->channel);
04689 }

static char* handle_dahdi_show_cadences ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12951 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, COLOR_BLACK, COLOR_GREEN, COLOR_MAGENTA, ast_cli_entry::command, ast_cli_args::fd, term_color(), and ast_cli_entry::usage.

12952 {
12953    int i, j;
12954    switch (cmd) {
12955    case CLI_INIT:
12956       e->command = "dahdi show cadences";
12957       e->usage = 
12958          "Usage: dahdi show cadences\n"
12959          "       Shows all cadences currently defined\n";
12960       return NULL;
12961    case CLI_GENERATE:
12962       return NULL;   
12963    }
12964    for (i = 0; i < num_cadence; i++) {
12965       char output[1024];
12966       char tmp[16], tmp2[64];
12967       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12968       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12969 
12970       for (j = 0; j < 16; j++) {
12971          if (cadences[i].ringcadence[j] == 0)
12972             break;
12973          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12974          if (cidrings[i] * 2 - 1 == j)
12975             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12976          else
12977             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12978          if (j != 0)
12979             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12980          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12981       }
12982       ast_cli(a->fd,"%s\n",output);
12983    }
12984    return CLI_SUCCESS;
12985 }

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

Definition at line 8075 of file chan_dahdi.c.

References ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, ast_verb, chan, dahdi_pvt::channel, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), errno, EVENT_FLAG_SYSTEM, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, 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, SIG_SS7, ss_thread(), SUB_REAL, and dahdi_pvt::subs.

Referenced by mwi_send_thread().

08076 {
08077    int res;
08078    int thread_spawned = 0;
08079    pthread_t threadid;
08080    struct ast_channel *chan;
08081 
08082    /* Handle an event on a given channel for the monitor thread. */
08083 
08084    switch (event) {
08085    case DAHDI_EVENT_NONE:
08086    case DAHDI_EVENT_BITSCHANGED:
08087       break;
08088    case DAHDI_EVENT_WINKFLASH:
08089    case DAHDI_EVENT_RINGOFFHOOK:
08090       if (i->inalarm) break;
08091       if (i->radio) break;
08092       /* Got a ring/answer.  What kind of channel are we? */
08093       switch (i->sig) {
08094       case SIG_FXOLS:
08095       case SIG_FXOGS:
08096       case SIG_FXOKS:
08097          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08098          if (res && (errno == EBUSY))
08099             break;
08100          if (i->cidspill) {
08101             /* Cancel VMWI spill */
08102             ast_free(i->cidspill);
08103             i->cidspill = NULL;
08104          }
08105          if (i->immediate) {
08106             dahdi_enable_ec(i);
08107             /* The channel is immediately up.  Start right away */
08108             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
08109             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
08110             if (!chan) {
08111                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
08112                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08113                if (res < 0)
08114                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08115             }
08116          } else {
08117             /* Check for callerid, digits, etc */
08118             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
08119             if (chan) {
08120                if (has_voicemail(i))
08121                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
08122                else
08123                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
08124                if (res < 0) 
08125                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
08126                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08127                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08128                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08129                   if (res < 0)
08130                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08131                   ast_hangup(chan);
08132                } else {
08133                   thread_spawned = 1;
08134                }
08135             } else
08136                ast_log(LOG_WARNING, "Unable to create channel\n");
08137          }
08138          break;
08139       case SIG_FXSLS:
08140       case SIG_FXSGS:
08141       case SIG_FXSKS:
08142             i->ringt = i->ringt_base;
08143             /* Fall through */
08144       case SIG_EMWINK:
08145       case SIG_FEATD:
08146       case SIG_FEATDMF:
08147       case SIG_FEATDMF_TA:
08148       case SIG_E911:
08149       case SIG_FGC_CAMA:
08150       case SIG_FGC_CAMAMF:
08151       case SIG_FEATB:
08152       case SIG_EM:
08153       case SIG_EM_E1:
08154       case SIG_SFWINK:
08155       case SIG_SF_FEATD:
08156       case SIG_SF_FEATDMF:
08157       case SIG_SF_FEATB:
08158       case SIG_SF:
08159          /* Check for callerid, digits, etc */
08160          if (i->cid_start == CID_START_POLARITY_IN) {
08161             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08162          } else {
08163             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
08164          }
08165 
08166          if (!chan) {
08167             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08168          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08169             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08170             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08171             if (res < 0) {
08172                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08173             }
08174             ast_hangup(chan);
08175          } else  {
08176             thread_spawned = 1;
08177          }
08178          break;
08179       default:
08180          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08181          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08182          if (res < 0)
08183                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
08184          return -1;
08185       }
08186       break;
08187    case DAHDI_EVENT_NOALARM:
08188       i->inalarm = 0;
08189       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
08190       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08191          "Channel: %d\r\n", i->channel);
08192       break;
08193    case DAHDI_EVENT_ALARM:
08194       i->inalarm = 1;
08195       res = get_alarms(i);
08196       handle_alarms(i, res);
08197       /* fall thru intentionally */
08198    case DAHDI_EVENT_ONHOOK:
08199       if (i->radio)
08200          break;
08201       /* Back on hook.  Hang up. */
08202       switch (i->sig) {
08203       case SIG_FXOLS:
08204       case SIG_FXOGS:
08205       case SIG_FEATD:
08206       case SIG_FEATDMF:
08207       case SIG_FEATDMF_TA:
08208       case SIG_E911:
08209       case SIG_FGC_CAMA:
08210       case SIG_FGC_CAMAMF:
08211       case SIG_FEATB:
08212       case SIG_EM:
08213       case SIG_EM_E1:
08214       case SIG_EMWINK:
08215       case SIG_SF_FEATD:
08216       case SIG_SF_FEATDMF:
08217       case SIG_SF_FEATB:
08218       case SIG_SF:
08219       case SIG_SFWINK:
08220       case SIG_FXSLS:
08221       case SIG_FXSGS:
08222       case SIG_FXSKS:
08223       case SIG_GR303FXSKS:
08224          dahdi_disable_ec(i);
08225          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08226          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08227          break;
08228       case SIG_GR303FXOKS:
08229       case SIG_FXOKS:
08230          dahdi_disable_ec(i);
08231          /* Diddle the battery for the zhone */
08232 #ifdef ZHONE_HACK
08233          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08234          usleep(1);
08235 #endif         
08236          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08237          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08238          break;
08239       case SIG_PRI:
08240       case SIG_SS7:
08241       case SIG_BRI:
08242       case SIG_BRI_PTMP:
08243          dahdi_disable_ec(i);
08244          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08245          break;
08246       default:
08247          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08248          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08249          return -1;
08250       }
08251       break;
08252    case DAHDI_EVENT_POLARITY:
08253       switch (i->sig) {
08254       case SIG_FXSLS:
08255       case SIG_FXSKS:
08256       case SIG_FXSGS:
08257          /* We have already got a PR before the channel was 
08258             created, but it wasn't handled. We need polarity 
08259             to be REV for remote hangup detection to work. 
08260             At least in Spain */
08261          if (i->hanguponpolarityswitch)
08262             i->polarity = POLARITY_REV;
08263          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08264             i->polarity = POLARITY_REV;
08265             ast_verb(2, "Starting post polarity "
08266                    "CID detection on channel %d\n",
08267                    i->channel);
08268             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08269             if (!chan) {
08270                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
08271             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08272                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08273             } else {
08274                thread_spawned = 1;
08275             }
08276          }
08277          break;
08278       default:
08279          ast_log(LOG_WARNING, "handle_init_event detected "
08280             "polarity reversal on non-FXO (SIG_FXS) "
08281             "interface %d\n", i->channel);
08282       }
08283       break;
08284    case DAHDI_EVENT_REMOVED: /* destroy channel */
08285       ast_log(LOG_NOTICE, 
08286             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08287             i->channel);
08288       dahdi_destroy_channel_bynum(i->channel);
08289       break;
08290    case DAHDI_EVENT_NEONMWI_ACTIVE:
08291       if (i->mwimonitor_neon) {
08292          notify_message(i->mailbox, 1);
08293          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08294       }
08295       break;
08296    case DAHDI_EVENT_NEONMWI_INACTIVE:
08297       if (i->mwimonitor_neon) {
08298          notify_message(i->mailbox, 0);
08299          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08300       }
08301       break;
08302    }
08303    return thread_spawned;
08304 }

static char* handle_pri_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12144 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.

12145 {
12146    int span;
12147    int x;
12148    switch (cmd) {
12149    case CLI_INIT: 
12150       e->command = "pri debug span";
12151       e->usage = 
12152          "Usage: pri debug span <span>\n"
12153          "       Enables debugging on a given PRI span\n";
12154       return NULL;
12155    case CLI_GENERATE:   
12156       return complete_span_4(a->line, a->word, a->pos, a->n);
12157    }
12158    if (a->argc < 4) {
12159       return CLI_SHOWUSAGE;
12160    }
12161    span = atoi(a->argv[3]);
12162    if ((span < 1) || (span > NUM_SPANS)) {
12163       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12164       return CLI_SUCCESS;
12165    }
12166    if (!pris[span-1].pri) {
12167       ast_cli(a->fd, "No PRI running on span %d\n", span);
12168       return CLI_SUCCESS;
12169    }
12170    for (x = 0; x < NUM_DCHANS; x++) {
12171       if (pris[span-1].dchans[x])
12172          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12173                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12174                                                PRI_DEBUG_Q921_STATE);
12175    }
12176    ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12177    return CLI_SUCCESS;
12178 }

static char* handle_pri_no_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12182 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_5(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.

12183 {
12184    int span;
12185    int x;
12186    switch (cmd) {
12187    case CLI_INIT:
12188       e->command = "pri no debug span";
12189       e->usage = 
12190          "Usage: pri no debug span <span>\n"
12191          "       Disables debugging on a given PRI span\n";
12192       return NULL;
12193    case CLI_GENERATE:
12194       return complete_span_5(a->line, a->word, a->pos, a->n);
12195    }
12196    if (a->argc < 5)
12197       return CLI_SHOWUSAGE;
12198 
12199    span = atoi(a->argv[4]);
12200    if ((span < 1) || (span > NUM_SPANS)) {
12201       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12202       return CLI_SUCCESS;
12203    }
12204    if (!pris[span-1].pri) {
12205       ast_cli(a->fd, "No PRI running on span %d\n", span);
12206       return CLI_SUCCESS;
12207    }
12208    for (x = 0; x < NUM_DCHANS; x++) {
12209       if (pris[span-1].dchans[x])
12210          pri_set_debug(pris[span-1].dchans[x], 0);
12211    }
12212    ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12213    return CLI_SUCCESS;
12214 }

static char* handle_pri_really_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12216 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_5(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, ast_cli_args::pos, pris, ast_cli_entry::usage, and ast_cli_args::word.

12217 {
12218    int span;
12219    int x;
12220    switch (cmd) {
12221    case CLI_INIT:
12222       e->command = "pri intensive debug span";
12223       e->usage = 
12224          "Usage: pri intensive debug span <span>\n"
12225          "       Enables debugging down to the Q.921 level\n";
12226       return NULL;
12227    case CLI_GENERATE:
12228       return complete_span_5(a->line, a->word, a->pos, a->n);
12229    }
12230 
12231    if (a->argc < 5)
12232       return CLI_SHOWUSAGE;
12233    span = atoi(a->argv[4]);
12234    if ((span < 1) || (span > NUM_SPANS)) {
12235       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12236       return CLI_SUCCESS;
12237    }
12238    if (!pris[span-1].pri) {
12239       ast_cli(a->fd, "No PRI running on span %d\n", span);
12240       return CLI_SUCCESS;
12241    }
12242    for (x = 0; x < NUM_DCHANS; x++) {
12243       if (pris[span-1].dchans[x])
12244          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12245                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12246                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12247    }
12248    ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12249    return CLI_SUCCESS;
12250 }

static char* handle_pri_set_debug_file ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12108 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), AST_FILE_MODE, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.

12109 {
12110    int myfd;
12111    switch (cmd) {
12112    case CLI_INIT:
12113       e->command = "pri set debug file";
12114       e->usage = "Usage: pri set debug file [output-file]\n"
12115             "       Sends PRI debug output to the specified output file\n";
12116       return NULL;
12117    case CLI_GENERATE:
12118       return NULL;   
12119    }
12120    if (a->argc < 5)
12121       return CLI_SHOWUSAGE;
12122 
12123    if (ast_strlen_zero(a->argv[4]))
12124       return CLI_SHOWUSAGE;
12125 
12126    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12127    if (myfd < 0) {
12128       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12129       return CLI_SUCCESS;
12130    }
12131 
12132    ast_mutex_lock(&pridebugfdlock);
12133 
12134    if (pridebugfd >= 0)
12135       close(pridebugfd);
12136 
12137    pridebugfd = myfd;
12138    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12139    ast_mutex_unlock(&pridebugfdlock);
12140    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12141    return CLI_SUCCESS;
12142 }

static char* handle_pri_show_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12356 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, debug, ast_cli_args::fd, NUM_SPANS, pridebugfdlock, pris, and ast_cli_entry::usage.

12357 {
12358    int x;
12359    int span;
12360    int count=0;
12361    int debug=0;
12362 
12363    switch (cmd) {
12364    case CLI_INIT: 
12365       e->command = "pri show debug";
12366       e->usage = 
12367          "Usage: pri show debug\n"
12368          "  Show the debug state of pri spans\n";
12369       return NULL;
12370    case CLI_GENERATE:
12371       return NULL;   
12372    }
12373 
12374    for (span = 0; span < NUM_SPANS; span++) {
12375            if (pris[span].pri) {
12376          for (x = 0; x < NUM_DCHANS; x++) {
12377             debug = 0;
12378                if (pris[span].dchans[x]) {
12379                   debug = pri_get_debug(pris[span].dchans[x]);
12380                ast_cli(a->fd, "Span %d: Debug: %s\tIntense: %s\n", span+1, (debug&PRI_DEBUG_Q931_STATE)? "Yes" : "No" ,(debug&PRI_DEBUG_Q921_RAW)? "Yes" : "No" );
12381                count++;
12382             }
12383          }
12384       }
12385 
12386    }
12387    ast_mutex_lock(&pridebugfdlock);
12388    if (pridebugfd >= 0) 
12389       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12390    ast_mutex_unlock(&pridebugfdlock);
12391        
12392    if (!count) 
12393       ast_cli(a->fd, "No debug set or no PRI running\n");
12394    return CLI_SUCCESS;
12395 }

static char* handle_pri_show_span ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12306 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, build_status(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_span_4(), DAHDI_OVERLAPDIAL_INCOMING, ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_SPANS, dahdi_pri::overlapdial, ast_cli_args::pos, pri_order(), pris, ast_cli_entry::usage, and ast_cli_args::word.

12307 {
12308    int span;
12309    int x;
12310    char status[256];
12311    switch (cmd) {
12312    case CLI_INIT: 
12313       e->command = "pri show span";
12314       e->usage = 
12315          "Usage: pri show span <span>\n"
12316          "       Displays PRI Information on a given PRI span\n";
12317       return NULL;
12318    case CLI_GENERATE:
12319       return complete_span_4(a->line, a->word, a->pos, a->n);
12320    }
12321 
12322    if (a->argc < 4)
12323       return CLI_SHOWUSAGE;
12324    span = atoi(a->argv[3]);
12325    if ((span < 1) || (span > NUM_SPANS)) {
12326       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12327       return CLI_SUCCESS;
12328    }
12329    if (!pris[span-1].pri) {
12330       ast_cli(a->fd, "No PRI running on span %d\n", span);
12331       return CLI_SUCCESS;
12332    }
12333    for (x = 0; x < NUM_DCHANS; x++) {
12334       if (pris[span-1].dchannels[x]) {
12335 #ifdef PRI_DUMP_INFO_STR
12336          char *info_str = NULL;
12337 #endif
12338          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12339          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12340          ast_cli(a->fd, "Status: %s\n", status);
12341 #ifdef PRI_DUMP_INFO_STR
12342          info_str = pri_dump_info_str(pris[span-1].pri);
12343          if (info_str) {
12344             ast_cli(a->fd, "%s", info_str);
12345             ast_free(info_str);
12346          }
12347 #else
12348          pri_dump_info(pris[span-1].pri);
12349 #endif
12350          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12351       }
12352    }
12353    return CLI_SUCCESS;
12354 }

static char* handle_pri_show_spans ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12273 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli(), build_status(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, NUM_SPANS, pris, and ast_cli_entry::usage.

12274 {
12275    int span;
12276    int x;
12277    char status[256];
12278 
12279    switch (cmd) {
12280    case CLI_INIT:
12281       e->command = "pri show spans";
12282       e->usage = 
12283          "Usage: pri show spans\n"
12284          "       Displays PRI Information\n";
12285       return NULL;
12286    case CLI_GENERATE:
12287       return NULL;   
12288    }
12289 
12290    if (a->argc != 3)
12291       return CLI_SHOWUSAGE;
12292 
12293    for (span = 0; span < NUM_SPANS; span++) {
12294       if (pris[span].pri) {
12295          for (x = 0; x < NUM_DCHANS; x++) {
12296             if (pris[span].dchannels[x]) {
12297                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12298                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12299             }
12300          }
12301       }
12302    }
12303    return CLI_SUCCESS;
12304 }

static char* handle_pri_unset_debug_file ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12087 of file chan_dahdi.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pridebugfdlock, and ast_cli_entry::usage.

12088 {
12089    switch (cmd) {
12090    case CLI_INIT:
12091       e->command = "pri unset debug file";
12092       e->usage = "Usage: pri unset debug file\n"
12093             "       Stop sending debug output to the previously \n"
12094                  "       specified file\n";
12095       return NULL;
12096    case CLI_GENERATE:
12097       return NULL;   
12098    }
12099    /* Assume it is unset */
12100    ast_mutex_lock(&pridebugfdlock);
12101    close(pridebugfd);
12102    pridebugfd = -1;
12103    ast_cli(a->fd, "PRI debug output to file disabled\n");
12104    ast_mutex_unlock(&pridebugfdlock);
12105    return CLI_SUCCESS;
12106 }

static char* handle_pri_version ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 12397 of file chan_dahdi.c.

References ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

12398 {
12399    switch (cmd) {
12400    case CLI_INIT:
12401       e->command = "pri show version";
12402       e->usage = 
12403          "Usage: pri show version\n"
12404          "Show libpri version information\n";
12405       return NULL;
12406    case CLI_GENERATE:
12407       return NULL;
12408    }
12409 
12410    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12411 
12412    return CLI_SUCCESS;
12413 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 2365 of file chan_dahdi.c.

References ast_app_has_voicemail(), ast_event_destroy(), ast_event_get_cached(), ast_event_get_ie_uint(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_strdupa, ast_strlen_zero(), context, dahdi_pvt::mailbox, mailbox, and strsep().

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

02366 {
02367    int new_msgs;
02368    struct ast_event *event;
02369    char *mailbox, *context;
02370 
02371    mailbox = context = ast_strdupa(p->mailbox);
02372    strsep(&context, "@");
02373    if (ast_strlen_zero(context))
02374       context = "default";
02375 
02376    event = ast_event_get_cached(AST_EVENT_MWI,
02377       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02378       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02379       AST_EVENT_IE_END);
02380 
02381    if (event) {
02382       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02383       ast_event_destroy(event);
02384    } else
02385       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02386 
02387    return new_msgs;
02388 }

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

Definition at line 1880 of file chan_dahdi.c.

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

Referenced by conf_del().

01881 {
01882    /* If they're listening to our channel, they're ours */  
01883    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01884       return 1;
01885    /* If they're a talker on our (allocated) conference, they're ours */
01886    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01887       return 1;
01888    return 0;
01889 }

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

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

01911 {
01912    int x;
01913    int useslavenative;
01914    struct dahdi_pvt *slave = NULL;
01915    /* Start out optimistic */
01916    useslavenative = 1;
01917    /* Update conference state in a stateless fashion */
01918    for (x = 0; x < 3; x++) {
01919       /* Any three-way calling makes slave native mode *definitely* out
01920          of the question */
01921       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01922          useslavenative = 0;
01923    }
01924    /* If we don't have any 3-way calls, check to see if we have
01925       precisely one slave */
01926    if (useslavenative) {
01927       for (x = 0; x < MAX_SLAVES; x++) {
01928          if (p->slaves[x]) {
01929             if (slave) {
01930                /* Whoops already have a slave!  No 
01931                   slave native and stop right away */
01932                slave = NULL;
01933                useslavenative = 0;
01934                break;
01935             } else {
01936                /* We have one slave so far */
01937                slave = p->slaves[x];
01938             }
01939          }
01940       }
01941    }
01942    /* If no slave, slave native definitely out */
01943    if (!slave)
01944       useslavenative = 0;
01945    else if (slave->law != p->law) {
01946       useslavenative = 0;
01947       slave = NULL;
01948    }
01949    if (out)
01950       *out = slave;
01951    return useslavenative;
01952 }

static int load_module ( void   )  [static]

Definition at line 15280 of file chan_dahdi.c.

References __unload_module(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_transfer(), action_transferhangup(), ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_cond_init(), ast_log(), ast_manager_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, ast_mutex_init(), AST_PTHREADT_NULL, ast_register_application, ast_string_field_init, ast_string_field_set, dahdi_cli, dahdi_pri_cli, dahdi_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_tech, inuse, lock, LOG_ERROR, name, NUM_SPANS, pris, round_robin, and setup_dahdi().

15281 {
15282    int res;
15283 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15284    int y, i;
15285 #endif
15286 
15287 #ifdef HAVE_PRI
15288    memset(pris, 0, sizeof(pris));
15289    for (y = 0; y < NUM_SPANS; y++) {
15290       ast_mutex_init(&pris[y].lock);
15291       pris[y].offset = -1;
15292       pris[y].master = AST_PTHREADT_NULL;
15293       for (i = 0; i < NUM_DCHANS; i++)
15294          pris[y].fds[i] = -1;
15295    }
15296    pri_set_error(dahdi_pri_error);
15297    pri_set_message(dahdi_pri_message);
15298    ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15299          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15300 #endif
15301 #ifdef HAVE_SS7
15302    memset(linksets, 0, sizeof(linksets));
15303    for (y = 0; y < NUM_SPANS; y++) {
15304       ast_mutex_init(&linksets[y].lock);
15305       linksets[y].master = AST_PTHREADT_NULL;
15306       for (i = 0; i < NUM_DCHANS; i++)
15307          linksets[y].fds[i] = -1;
15308    }
15309    ss7_set_error(dahdi_ss7_error);
15310    ss7_set_message(dahdi_ss7_message);
15311 #endif /* HAVE_SS7 */
15312    res = setup_dahdi(0);
15313    /* Make sure we can register our DAHDI channel type */
15314    if (res)
15315       return AST_MODULE_LOAD_DECLINE;
15316    if (ast_channel_register(&dahdi_tech)) {
15317       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15318       __unload_module();
15319       return AST_MODULE_LOAD_FAILURE;
15320    }
15321 #ifdef HAVE_PRI
15322    ast_string_field_init(&inuse, 16);
15323    ast_string_field_set(&inuse, name, "GR-303InUse");
15324    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15325 #endif   
15326 #ifdef HAVE_SS7
15327    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15328 #endif
15329 
15330    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15331    
15332    memset(round_robin, 0, sizeof(round_robin));
15333    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15334    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15335    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15336    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15337    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15338    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15339    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15340 
15341    ast_cond_init(&mwi_thread_complete, NULL);
15342    ast_cond_init(&ss_thread_complete, NULL);
15343 
15344    return res;
15345 }

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

Definition at line 8695 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_chan_conf::is_sig_auto, 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, 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_pri::sig, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_FXOKS, SIG_FXSKS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SS7, sigtype_to_signalling(), SUB_REAL, dahdi_pri::switchtype, and dahdi_pri::unknownprefix.

Referenced by build_channels().

08696 {
08697    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
08698    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
08699    char fn[80];
08700    struct dahdi_bufferinfo bi;
08701 
08702    int res;
08703    int span = 0;
08704    int here = 0;
08705    int x;
08706    struct dahdi_pvt **wlist;
08707    struct dahdi_pvt **wend;
08708    struct dahdi_params p;
08709 
08710    wlist = &iflist;
08711    wend = &ifend;
08712 
08713 #ifdef HAVE_PRI
08714    if (pri) {
08715       wlist = &pri->crvs;
08716       wend = &pri->crvend;
08717    }
08718 #endif
08719 
08720    tmp2 = *wlist;
08721    prev = NULL;
08722 
08723    while (tmp2) {
08724       if (!tmp2->destroy) {
08725          if (tmp2->channel == channel) {
08726             tmp = tmp2;
08727             here = 1;
08728             break;
08729          }
08730          if (tmp2->channel > channel) {
08731             break;
08732          }
08733       }
08734       prev = tmp2;
08735       tmp2 = tmp2->next;
08736    }
08737 
08738    if (!here && reloading != 1) {
08739       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08740          if (tmp)
08741             free(tmp);
08742          return NULL;
08743       }
08744       ast_mutex_init(&tmp->lock);
08745       ifcount++;
08746       for (x = 0; x < 3; x++)
08747          tmp->subs[x].dfd = -1;
08748       tmp->channel = channel;
08749    }
08750 
08751    if (tmp) {
08752       int chan_sig = conf->chan.sig;
08753       if (!here) {
08754          if ((channel != CHAN_PSEUDO) && !pri) {
08755             int count = 0;
08756             snprintf(fn, sizeof(fn), "%d", channel);
08757             /* Open non-blocking */
08758             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08759             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 */
08760                usleep(1);
08761                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08762                count++;
08763             }
08764             /* Allocate a DAHDI structure */
08765             if (tmp->subs[SUB_REAL].dfd < 0) {
08766                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);
08767                destroy_dahdi_pvt(&tmp);
08768                return NULL;
08769             }
08770             memset(&p, 0, sizeof(p));
08771             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08772             if (res < 0) {
08773                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08774                destroy_dahdi_pvt(&tmp);
08775                return NULL;
08776             }
08777             if (conf->is_sig_auto)
08778                chan_sig = sigtype_to_signalling(p.sigtype);
08779             if (p.sigtype != (chan_sig & 0x3ffff)) {
08780                ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
08781                destroy_dahdi_pvt(&tmp);
08782                return NULL;
08783             }
08784             tmp->law = p.curlaw;
08785             tmp->span = p.spanno;
08786             span = p.spanno - 1;
08787          } else {
08788             if (channel == CHAN_PSEUDO)
08789                chan_sig = 0;
08790             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08791                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08792                return NULL;
08793             }
08794          }
08795 #ifdef HAVE_SS7
08796          if (chan_sig == SIG_SS7) {
08797             struct dahdi_ss7 *ss7;
08798             int clear = 0;
08799             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08800                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08801                destroy_dahdi_pvt(&tmp);
08802                return NULL;
08803             }
08804 
08805             ss7 = ss7_resolve_linkset(cur_linkset);
08806             if (!ss7) {
08807                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08808                destroy_dahdi_pvt(&tmp);
08809                return NULL;
08810             }
08811             if (cur_cicbeginswith < 0) {
08812                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08813                destroy_dahdi_pvt(&tmp);
08814                return NULL;
08815             }
08816 
08817             tmp->cic = cur_cicbeginswith++;
08818 
08819             /* DB: Add CIC's DPC information */
08820             tmp->dpc = cur_defaultdpc;
08821 
08822             tmp->ss7 = ss7;
08823             tmp->ss7call = NULL;
08824             ss7->pvts[ss7->numchans++] = tmp;
08825 
08826             ast_copy_string(linksets[span].internationalprefix, conf->ss7.internationalprefix, sizeof(linksets[span].internationalprefix));
08827             ast_copy_string(linksets[span].nationalprefix, conf->ss7.nationalprefix, sizeof(linksets[span].nationalprefix));
08828             ast_copy_string(linksets[span].subscriberprefix, conf->ss7.subscriberprefix, sizeof(linksets[span].subscriberprefix));
08829             ast_copy_string(linksets[span].unknownprefix, conf->ss7.unknownprefix, sizeof(linksets[span].unknownprefix));
08830 
08831             linksets[span].called_nai = conf->ss7.called_nai;
08832             linksets[span].calling_nai = conf->ss7.calling_nai;
08833          }
08834 #endif
08835 #ifdef HAVE_PRI
08836          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08837             int offset;
08838             int myswitchtype;
08839             int matchesdchan;
08840             int x,y;
08841             offset = 0;
08842             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 
08843                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08844                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08845                destroy_dahdi_pvt(&tmp);
08846                return NULL;
08847             }
08848             if (span >= NUM_SPANS) {
08849                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08850                destroy_dahdi_pvt(&tmp);
08851                return NULL;
08852             } else {
08853                struct dahdi_spaninfo si;
08854                si.spanno = 0;
08855                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08856                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08857                   destroy_dahdi_pvt(&tmp);
08858                   return NULL;
08859                }
08860                /* Store the logical span first based upon the real span */
08861                tmp->logicalspan = pris[span].prilogicalspan;
08862                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08863                if (span < 0) {
08864                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08865                   destroy_dahdi_pvt(&tmp);
08866                   return NULL;
08867                }
08868                if ((chan_sig == SIG_PRI) ||
08869                      (chan_sig == SIG_BRI) ||
08870                      (chan_sig == SIG_BRI_PTMP))
08871                   myswitchtype = conf->pri.switchtype;
08872                else
08873                   myswitchtype = PRI_SWITCH_GR303_TMC;
08874                /* Make sure this isn't a d-channel */
08875                matchesdchan=0;
08876                for (x = 0; x < NUM_SPANS; x++) {
08877                   for (y = 0; y < NUM_DCHANS; y++) {
08878                      if (pris[x].dchannels[y] == tmp->channel) {
08879                         matchesdchan = 1;
08880                         break;
08881                      }
08882                   }
08883                }
08884                offset = p.chanpos;
08885                if (!matchesdchan) {
08886                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08887                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08888                      destroy_dahdi_pvt(&tmp);
08889                      return NULL;
08890                   }
08891                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08892                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08893                      destroy_dahdi_pvt(&tmp);
08894                      return NULL;
08895                   }
08896                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08897                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08898                      destroy_dahdi_pvt(&tmp);
08899                      return NULL;
08900                   }
08901                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08902                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08903                      destroy_dahdi_pvt(&tmp);
08904                      return NULL;
08905                   }
08906                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08907                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08908                      destroy_dahdi_pvt(&tmp);
08909                      return NULL;
08910                   }
08911                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08912                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08913                      destroy_dahdi_pvt(&tmp);
08914                      return NULL;
08915                   }
08916                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08917                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08918                      destroy_dahdi_pvt(&tmp);
08919                      return NULL;
08920                   }
08921                   if (pris[span].numchans >= MAX_CHANNELS) {
08922                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08923                         pris[span].trunkgroup);
08924                      destroy_dahdi_pvt(&tmp);
08925                      return NULL;
08926                   }
08927 
08928                   pris[span].sig = chan_sig;
08929                   pris[span].nodetype = conf->pri.nodetype;
08930                   pris[span].switchtype = myswitchtype;
08931                   pris[span].nsf = conf->pri.nsf;
08932                   pris[span].dialplan = conf->pri.dialplan;
08933                   pris[span].localdialplan = conf->pri.localdialplan;
08934                   pris[span].pvts[pris[span].numchans++] = tmp;
08935                   pris[span].minunused = conf->pri.minunused;
08936                   pris[span].minidle = conf->pri.minidle;
08937                   pris[span].overlapdial = conf->pri.overlapdial;
08938 #ifdef HAVE_PRI_INBANDDISCONNECT
08939                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08940 #endif
08941                   pris[span].facilityenable = conf->pri.facilityenable;
08942                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08943                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08944                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08945                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08946                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08947                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08948                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08949                   pris[span].resetinterval = conf->pri.resetinterval;
08950                   
08951                   tmp->pri = &pris[span];
08952                   tmp->prioffset = offset;
08953                   tmp->call = NULL;
08954                } else {
08955                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08956                   destroy_dahdi_pvt(&tmp);
08957                   return NULL;
08958                }
08959             }
08960          } else {
08961             tmp->prioffset = 0;
08962          }
08963 #endif
08964       } else {
08965          chan_sig = tmp->sig;
08966          if (tmp->subs[SUB_REAL].dfd > -1) {
08967             memset(&p, 0, sizeof(p));
08968             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08969          }
08970       }
08971       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
08972       switch (chan_sig) {
08973       case SIG_FXSKS:
08974       case SIG_FXSLS:
08975       case SIG_EM:
08976       case SIG_EM_E1:
08977       case SIG_EMWINK:
08978       case SIG_FEATD:
08979       case SIG_FEATDMF:
08980       case SIG_FEATDMF_TA:
08981       case SIG_FEATB:
08982       case SIG_E911:
08983       case SIG_SF:
08984       case SIG_SFWINK:
08985       case SIG_FGC_CAMA:
08986       case SIG_FGC_CAMAMF:
08987       case SIG_SF_FEATD:
08988       case SIG_SF_FEATDMF:
08989       case SIG_SF_FEATB:
08990          p.starttime = 250;
08991          break;
08992       }
08993 
08994       if (tmp->radio) {
08995          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
08996          p.channo = channel;
08997          p.rxwinktime = 1;
08998          p.rxflashtime = 1;
08999          p.starttime = 1;
09000          p.debouncetime = 5;
09001       }
09002       if (!tmp->radio) {
09003          p.channo = channel;
09004          /* Override timing settings based on config file */
09005          if (conf->timing.prewinktime >= 0)
09006             p.prewinktime = conf->timing.prewinktime;
09007          if (conf->timing.preflashtime >= 0)
09008             p.preflashtime = conf->timing.preflashtime;
09009          if (conf->timing.winktime >= 0)
09010             p.winktime = conf->timing.winktime;
09011          if (conf->timing.flashtime >= 0)
09012             p.flashtime = conf->timing.flashtime;
09013          if (conf->timing.starttime >= 0)
09014             p.starttime = conf->timing.starttime;
09015          if (conf->timing.rxwinktime >= 0)
09016             p.rxwinktime = conf->timing.rxwinktime;
09017          if (conf->timing.rxflashtime >= 0)
09018             p.rxflashtime = conf->timing.rxflashtime;
09019          if (conf->timing.debouncetime >= 0)
09020             p.debouncetime = conf->timing.debouncetime;
09021       }
09022 
09023       /* dont set parms on a pseudo-channel (or CRV) */
09024       if (tmp->subs[SUB_REAL].dfd >= 0)
09025       {
09026          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
09027          if (res < 0) {
09028             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
09029             destroy_dahdi_pvt(&tmp);
09030             return NULL;
09031          }
09032       }
09033 #if 1
09034       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
09035          memset(&bi, 0, sizeof(bi));
09036          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09037          if (!res) {
09038             bi.txbufpolicy = conf->chan.buf_policy;
09039             bi.rxbufpolicy = conf->chan.buf_policy;
09040             bi.numbufs = conf->chan.buf_no;
09041             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09042             if (res < 0) {
09043                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
09044             }
09045          } else
09046             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
09047       }
09048 #endif
09049       tmp->immediate = conf->chan.immediate;
09050       tmp->transfertobusy = conf->chan.transfertobusy;
09051       if (chan_sig & __DAHDI_SIG_FXS) {
09052          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
09053          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
09054          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
09055       }
09056       tmp->sig = chan_sig;
09057       tmp->outsigmod = conf->chan.outsigmod;
09058       tmp->ringt_base = ringt_base;
09059       tmp->firstradio = 0;
09060       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
09061          tmp->permcallwaiting = conf->chan.callwaiting;
09062       else
09063          tmp->permcallwaiting = 0;
09064       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
09065       tmp->destroy = 0;
09066       tmp->drings = conf->chan.drings;
09067 
09068       /* 10 is a nice default. */
09069       if (tmp->drings.ringnum[0].range == 0)
09070          tmp->drings.ringnum[0].range = 10;
09071       if (tmp->drings.ringnum[1].range == 0)
09072          tmp->drings.ringnum[1].range = 10;
09073       if (tmp->drings.ringnum[2].range == 0)
09074          tmp->drings.ringnum[2].range = 10;
09075 
09076       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
09077       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
09078       tmp->threewaycalling = conf->chan.threewaycalling;
09079       tmp->adsi = conf->chan.adsi;
09080       tmp->use_smdi = conf->chan.use_smdi;
09081       tmp->permhidecallerid = conf->chan.hidecallerid;
09082       tmp->callreturn = conf->chan.callreturn;
09083       tmp->echocancel = conf->chan.echocancel;
09084       tmp->echotraining = conf->chan.echotraining;
09085       tmp->pulse = conf->chan.pulse;
09086       if (tmp->echocancel.head.tap_length) {
09087          tmp->echocanbridged = conf->chan.echocanbridged;
09088       } else {
09089          if (conf->chan.echocanbridged)
09090             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
09091          tmp->echocanbridged = 0;
09092       }
09093       tmp->busydetect = conf->chan.busydetect;
09094       tmp->busycount = conf->chan.busycount;
09095       tmp->busycompare = conf->chan.busycompare;
09096       tmp->busytonelength = conf->chan.busytonelength;
09097       tmp->busyquietlength = conf->chan.busyquietlength;
09098       tmp->busyfuzziness = conf->chan.busyfuzziness;
09099       tmp->silencethreshold = conf->chan.silencethreshold;
09100       tmp->callprogress = conf->chan.callprogress;
09101       tmp->cancallforward = conf->chan.cancallforward;
09102       tmp->dtmfrelax = conf->chan.dtmfrelax;
09103       tmp->callwaiting = tmp->permcallwaiting;
09104       tmp->hidecallerid = tmp->permhidecallerid;
09105       tmp->channel = channel;
09106       tmp->stripmsd = conf->chan.stripmsd;
09107       tmp->use_callerid = conf->chan.use_callerid;
09108       tmp->cid_signalling = conf->chan.cid_signalling;
09109       tmp->cid_start = conf->chan.cid_start;
09110       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
09111       tmp->restrictcid = conf->chan.restrictcid;
09112       tmp->use_callingpres = conf->chan.use_callingpres;
09113       tmp->priindication_oob = conf->chan.priindication_oob;
09114       tmp->priexclusive = conf->chan.priexclusive;
09115       if (tmp->usedistinctiveringdetection) {
09116          if (!tmp->use_callerid) {
09117             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
09118             tmp->use_callerid = 1;
09119          }
09120       }
09121 
09122       if (tmp->cid_signalling == CID_SIG_SMDI) {
09123          if (!tmp->use_smdi) {
09124             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
09125             tmp->use_smdi = 1;
09126          }
09127       }
09128       if (tmp->use_smdi) {
09129          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
09130          if (!(tmp->smdi_iface)) {
09131             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
09132             tmp->use_smdi = 0;
09133          }
09134       }
09135 
09136       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
09137       tmp->amaflags = conf->chan.amaflags;
09138       if (!here) {
09139          tmp->confno = -1;
09140          tmp->propconfno = -1;
09141       }
09142       tmp->canpark = conf->chan.canpark;
09143       tmp->transfer = conf->chan.transfer;
09144       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
09145       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
09146       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
09147       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
09148       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
09149       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
09150       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
09151       tmp->cid_ton = 0;
09152       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
09153       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
09154       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
09155          char *mailbox, *context;
09156          mailbox = context = ast_strdupa(tmp->mailbox);
09157          strsep(&context, "@");
09158          if (ast_strlen_zero(context))
09159             context = "default";
09160          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
09161             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
09162             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
09163             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
09164             AST_EVENT_IE_END);
09165       }
09166       tmp->msgstate = -1;
09167       tmp->group = conf->chan.group;
09168       tmp->callgroup = conf->chan.callgroup;
09169       tmp->pickupgroup= conf->chan.pickupgroup;
09170       if (conf->chan.vars) {
09171          tmp->vars = conf->chan.vars;
09172       }
09173       tmp->cid_rxgain = conf->chan.cid_rxgain;
09174       tmp->rxgain = conf->chan.rxgain;
09175       tmp->txgain = conf->chan.txgain;
09176       tmp->tonezone = conf->chan.tonezone;
09177       tmp->onhooktime = time(NULL);
09178       if (tmp->subs[SUB_REAL].dfd > -1) {
09179          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
09180          if (tmp->dsp)
09181             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
09182          update_conf(tmp);
09183          if (!here) {
09184             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
09185                /* Hang it up to be sure it's good */
09186                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09187          }
09188          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
09189 #ifdef HAVE_PRI
09190          /* the dchannel is down so put the channel in alarm */
09191          if (tmp->pri && !pri_is_up(tmp->pri))
09192             tmp->inalarm = 1;
09193 #endif            
09194          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09195             tmp->inalarm = 1;
09196             handle_alarms(tmp, res);
09197          }
09198       }
09199 
09200       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09201       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09202       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09203       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09204       if (!here) {
09205          tmp->locallyblocked = tmp->remotelyblocked = 0;
09206          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09207             tmp->inservice = 0;
09208          else /* We default to in service on protocols that don't have a reset */
09209             tmp->inservice = 1;
09210       }
09211    }
09212    if (tmp && !here) {
09213       /* nothing on the iflist */
09214       if (!*wlist) {
09215          *wlist = tmp;
09216          tmp->prev = NULL;
09217          tmp->next = NULL;
09218          *wend = tmp;
09219       } else {
09220          /* at least one member on the iflist */
09221          struct dahdi_pvt *working = *wlist;
09222 
09223          /* check if we maybe have to put it on the begining */
09224          if (working->channel > tmp->channel) {
09225             tmp->next = *wlist;
09226             tmp->prev = NULL;
09227             (*wlist)->prev = tmp;
09228             *wlist = tmp;
09229          } else {
09230          /* go through all the members and put the member in the right place */
09231             while (working) {
09232                /* in the middle */
09233                if (working->next) {
09234                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09235                      tmp->next = working->next;
09236                      tmp->prev = working;
09237                      working->next->prev = tmp;
09238                      working->next = tmp;
09239                      break;
09240                   }
09241                } else {
09242                /* the last */
09243                   if (working->channel < tmp->channel) {
09244                      working->next = tmp;
09245                      tmp->next = NULL;
09246                      tmp->prev = working;
09247                      *wend = tmp;
09248                      break;
09249                   }
09250                }
09251                working = working->next;
09252             }
09253          }
09254       }
09255    }
09256    return tmp;
09257 }

static void mwi_event_cb ( const struct ast_event event,
void *  userdata 
) [static]

Definition at line 294 of file chan_dahdi.c.

Referenced by add_peer_mwi_subs(), build_device(), build_gateway(), and build_peer().

00295 {
00296    /* This module does not handle MWI in an event-based manner.  However, it
00297     * subscribes to MWI for each mailbox that is configured so that the core
00298     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00299     * event cache instead of checking the mailbox directly. */
00300 }

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

Definition at line 7901 of file chan_dahdi.c.

References ast_calloc, ast_cond_signal(), ast_free, AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), mwi_thread_data::buf, CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_get_event(), dahdi_set_hook(), errno, handle_init_event(), has_voicemail(), MAX_CALLERID_SIZE, MWI_SEND_CLEANUP, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwi_thread_lock, dahdi_pvt::mwisendactive, mwi_thread_data::pvt, quit, SUB_REAL, dahdi_pvt::subs, and vmwi_generate().

07902 {
07903    struct mwi_thread_data *mtd = data;
07904    struct timeval timeout_basis, suspend, now;
07905    int x, i, res;
07906    int num_read;
07907    enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
07908 
07909    ast_mutex_lock(&mwi_thread_lock);
07910    mwi_thread_count++;
07911    ast_mutex_unlock(&mwi_thread_lock);
07912 
07913    /* Determine how this spill is to be sent */
07914    if(mwisend_rpas) {
07915       mwi_send_state = MWI_SEND_SA;
07916    }
07917 
07918    gettimeofday(&timeout_basis, NULL);
07919    
07920    mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
07921    if (!mtd->pvt->cidspill) {
07922       mtd->pvt->mwisendactive = 0;
07923       ast_free(mtd);
07924       return NULL;
07925    }
07926    x = DAHDI_FLUSH_BOTH;
07927    res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
07928    x = 3000;
07929    ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
07930    mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
07931                             AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
07932    mtd->pvt->cidpos = 0;
07933 
07934    while (MWI_SEND_DONE != mwi_send_state) {
07935       num_read = 0;
07936       gettimeofday(&now, NULL);
07937       if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
07938          ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
07939          goto quit;
07940       }
07941 
07942       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07943       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07944          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07945          goto quit;
07946       }
07947 
07948       if (i & DAHDI_IOMUX_SIGEVENT) {
07949          /* If we get an event, screen out events that we do not act on.
07950          * Otherwise, let handle_init_event determine what is needed
07951          */
07952          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07953          switch (res) {
07954             case DAHDI_EVENT_RINGEROFF:
07955                if(mwi_send_state == MWI_SEND_SA_WAIT) {
07956                   if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
07957                      ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
07958                      goto quit;
07959                   }
07960                   mwi_send_state = MWI_SEND_PAUSE;
07961                   gettimeofday(&suspend, NULL);
07962                }
07963                break;
07964             case DAHDI_EVENT_RINGERON:
07965             case DAHDI_EVENT_HOOKCOMPLETE:
07966                break;
07967             default:
07968                /* Got to the default init event handler */
07969                if (0 < handle_init_event(mtd->pvt, res)) {
07970                   /* I've spawned a thread, get out */
07971                   goto quit;
07972                }
07973                break;
07974          }
07975       } else if (i & DAHDI_IOMUX_READ) {
07976          if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07977             if (errno != ELAST) {
07978                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07979                goto quit;
07980             }
07981             break;
07982          }
07983       }
07984       /* Perform mwi send action */
07985       switch ( mwi_send_state) {
07986          case MWI_SEND_SA:
07987             /* Send the Ring Pulse Signal Alert */
07988             res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
07989             if (res) {
07990                ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
07991                goto quit;
07992             }
07993             dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
07994             mwi_send_state = MWI_SEND_SA_WAIT;
07995             break;
07996             case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
07997                break;
07998                case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
07999                   gettimeofday(&now, NULL);
08000                   if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
08001                      mwi_send_state = MWI_SEND_SPILL;
08002                   }
08003                   break;
08004          case MWI_SEND_SPILL:
08005             /* We read some number of bytes.  Write an equal amount of data */
08006             if(0 < num_read) {
08007                if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
08008                   num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
08009                res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
08010                if (res > 0) {
08011                   mtd->pvt->cidpos += res;
08012                   if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
08013                      ast_free(mtd->pvt->cidspill);
08014                      mtd->pvt->cidspill = NULL;
08015                      mtd->pvt->cidpos = 0;
08016                      mtd->pvt->cidlen = 0;
08017                      mwi_send_state = MWI_SEND_CLEANUP;
08018                   }
08019                } else {
08020                   ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
08021                   goto quit;
08022                }
08023             }
08024             break;
08025          case MWI_SEND_CLEANUP:
08026             /* For now, do nothing */
08027             mwi_send_state = MWI_SEND_DONE;
08028             break;
08029          default:
08030             /* Should not get here, punt*/
08031             goto quit;
08032             break;
08033       }
08034    }
08035 
08036 quit:
08037    if(mtd->pvt->cidspill) {
08038       ast_free(mtd->pvt->cidspill);
08039       mtd->pvt->cidspill = NULL;
08040    }
08041    mtd->pvt->mwisendactive = 0;
08042    ast_free(mtd);
08043 
08044    ast_mutex_lock(&mwi_thread_lock);
08045    mwi_thread_count--;
08046    ast_cond_signal(&mwi_thread_complete);
08047    ast_mutex_unlock(&mwi_thread_lock);
08048 
08049    return NULL;
08050 }

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

Definition at line 7758 of file chan_dahdi.c.

References ast_hangup(), AST_LAW, ast_log(), ast_pthread_create_detached, AST_STATE_RING, mwi_thread_data::buf, bump_gains(), calc_energy(), callerid_feed(), callerid_free(), callerid_new(), chan, dahdi_pvt::channel, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), errno, event2str(), EVENT_FLAG_SYSTEM, callerid_state::flags, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, manager_event, dahdi_pvt::mwimonitoractive, name, mwi_thread_data::pvt, quit, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, ss_thread(), SUB_REAL, and dahdi_pvt::subs.

07759 {
07760    struct mwi_thread_data *mtd = data;
07761    struct callerid_state *cs;
07762    pthread_t threadid;
07763    int samples = 0;
07764    char *name, *number;
07765    int flags;
07766    int i, res;
07767    unsigned int spill_done = 0;
07768    int spill_result = -1;
07769    
07770    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
07771       mtd->pvt->mwimonitoractive = 0;
07772 
07773       return NULL;
07774    }
07775    
07776    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
07777 
07778    bump_gains(mtd->pvt);
07779 
07780    for (;;) {  
07781       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07782       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
07783          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07784          goto quit;
07785       }
07786 
07787       if (i & DAHDI_IOMUX_SIGEVENT) {
07788          struct ast_channel *chan;
07789 
07790          /* If we get an event, screen out events that we do not act on.
07791           * Otherwise, cancel and go to the simple switch to let it deal with it.
07792           */
07793          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
07794 
07795          switch (res) {
07796          case DAHDI_EVENT_NEONMWI_ACTIVE:
07797          case DAHDI_EVENT_NEONMWI_INACTIVE:
07798          case DAHDI_EVENT_NONE:
07799          case DAHDI_EVENT_BITSCHANGED:
07800             break;
07801          case DAHDI_EVENT_NOALARM:
07802             mtd->pvt->inalarm = 0;
07803             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
07804             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07805                "Channel: %d\r\n", mtd->pvt->channel);
07806             break;
07807          case DAHDI_EVENT_ALARM:
07808             mtd->pvt->inalarm = 1;
07809             res = get_alarms(mtd->pvt);
07810             handle_alarms(mtd->pvt, res);
07811             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
07812          default:
07813             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
07814             callerid_free(cs);
07815             
07816             restore_gains(mtd->pvt);
07817             mtd->pvt->ringt = mtd->pvt->ringt_base;
07818 
07819             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
07820                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07821                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
07822                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07823                   if (res < 0)
07824                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
07825                   ast_hangup(chan);
07826                   goto quit;
07827                }
07828                goto quit_no_clean;
07829 
07830             } else {
07831                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
07832             }
07833          }
07834       } else if (i & DAHDI_IOMUX_READ) {
07835          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
07836             if (errno != ELAST) {
07837                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07838                goto quit;
07839             }
07840             break;
07841          }
07842          samples += res;
07843          if (!spill_done) {
07844             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
07845                ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07846                break;
07847             } else if (spill_result) {
07848                spill_done = 1;
07849             }
07850          } else {
07851             /* keep reading data until the energy level drops below the threshold
07852                so we don't get another 'trigger' on the remaining carrier signal
07853             */
07854             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
07855                break;
07856          }
07857          if (samples > (8000 * 4)) /*Termination case - time to give up*/
07858             break;
07859       }
07860    }
07861 
07862    if (spill_result == 1) {
07863       callerid_get(cs, &name, &number, &flags);
07864       if (flags & CID_MSGWAITING) {
07865          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
07866          notify_message(mtd->pvt->mailbox, 1);
07867       } else if (flags & CID_NOMSGWAITING) {
07868          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
07869          notify_message(mtd->pvt->mailbox, 0);
07870       } else {
07871          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
07872       }
07873    }
07874 
07875 
07876 quit:
07877    callerid_free(cs);
07878 
07879    restore_gains(mtd->pvt);
07880 
07881 quit_no_clean:
07882    mtd->pvt->mwimonitoractive = 0;
07883 
07884    ast_free(mtd);
07885 
07886    return NULL;
07887 }

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

Definition at line 5945 of file chan_dahdi.c.

References ast_debug, dahdi_pvt::channel, dahdi_subchannel::dfd, errno, READ_SIZE, and dahdi_pvt::subs.

Referenced by dahdi_write().

05946 {
05947    int sent=0;
05948    int size;
05949    int res;
05950    int fd;
05951    fd = p->subs[idx].dfd;
05952    while (len) {
05953       size = len;
05954       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05955          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05956       res = write(fd, buf, size);
05957       if (res != size) {
05958          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05959          return sent;
05960       }
05961       len -= size;
05962       buf += size;
05963    }
05964    return sent;
05965 }

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

Definition at line 6471 of file chan_dahdi.c.

References ast_waitfordigit(), and chan.

Referenced by ss_thread().

06472 {
06473    char c;
06474 
06475    *str = 0; /* start with empty output buffer */
06476    for (;;)
06477    {
06478       /* Wait for the first digit (up to specified ms). */
06479       c = ast_waitfordigit(chan, ms);
06480       /* if timeout, hangup or error, return as such */
06481       if (c < 1)
06482          return c;
06483       *str++ = c;
06484       *str = 0;
06485       if (strchr(term, c))
06486          return 1;
06487    }
06488 }

static void notify_message ( char *  mailbox_full,
int  thereornot 
) [static]

Send MWI state change.

Returns:
nothing
This function does two things:

1) It generates an internal Asterisk event notifying any other module that cares about MWI that the state of a mailbox has changed.

2) It runs the script specified by the mwimonitornotify option to allow some custom handling of the state change.

Definition at line 2304 of file chan_dahdi.c.

References AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, AST_EVENT_MWI, ast_event_new(), ast_event_queue_and_cache(), ast_safe_system(), ast_strdupa, ast_strlen_zero(), context, mailbox, s, and strsep().

Referenced by handle_init_event().

02305 {
02306    char s[sizeof(mwimonitornotify) + 80];
02307    struct ast_event *event;
02308    char *mailbox, *context;
02309 
02310    /* Strip off @default */
02311    context = mailbox = ast_strdupa(mailbox_full);
02312    strsep(&context, "@");
02313    if (ast_strlen_zero(context))
02314       context = "default";
02315 
02316    if (!(event = ast_event_new(AST_EVENT_MWI,
02317          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02318          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02319          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02320          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02321          AST_EVENT_IE_END))) {
02322       return;
02323    }
02324 
02325    ast_event_queue_and_cache(event);
02326 
02327    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02328       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02329       ast_safe_system(s);
02330    }
02331 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

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

03353 {
03354    int x = -1;
03355 
03356    for (x = 0; x < NUM_DCHANS; x++) {
03357       if ((pri->dchans[x] == pri->pri))
03358          break;
03359    }
03360 
03361    return pri->fds[x];
03362 }

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

Definition at line 3322 of file chan_dahdi.c.

References ast_channel_set_fd(), dahdi_pvt::bearer, dahdi_pvt::call, dahdi_subchannel::dfd, inuse, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::realcall, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_request().

03323 {
03324    bearer->owner = &inuse;
03325    bearer->realcall = crv;
03326    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03327    if (crv->subs[SUB_REAL].owner)
03328       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03329    crv->bearer = bearer;
03330    crv->call = bearer->call;
03331    crv->pri = pri;
03332    return 0;
03333 }

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

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

10765 {
10766    do {
10767       pri->resetpos++;
10768    } while ((pri->resetpos < pri->numchans) &&
10769        (!pri->pvts[pri->resetpos] ||
10770         pri->pvts[pri->resetpos]->call ||
10771         pri->pvts[pri->resetpos]->resetting));
10772    if (pri->resetpos < pri->numchans) {
10773       /* Mark the channel as resetting and restart it */
10774       pri->pvts[pri->resetpos]->resetting = 1;
10775       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10776    } else {
10777       pri->resetting = 0;
10778       time(&pri->lastreset);
10779    }
10780    return 0;
10781 }

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

Definition at line 8647 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08648 {
08649    if (pris[span].mastertrunkgroup) {
08650       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);
08651       return -1;
08652    }
08653    pris[span].mastertrunkgroup = trunkgroup;
08654    pris[span].prilogicalspan = logicalspan;
08655    return 0;
08656 }

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

Definition at line 8584 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08585 {
08586    struct dahdi_spaninfo si;
08587    struct dahdi_params p;
08588    int fd;
08589    int span;
08590    int ospan=0;
08591    int x,y;
08592    for (x = 0; x < NUM_SPANS; x++) {
08593       if (pris[x].trunkgroup == trunkgroup) {
08594          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08595          return -1;
08596       }
08597    }
08598    for (y = 0; y < NUM_DCHANS; y++) {
08599       if (!channels[y]) 
08600          break;
08601       memset(&si, 0, sizeof(si));
08602       memset(&p, 0, sizeof(p));
08603       fd = open("/dev/dahdi/channel", O_RDWR);
08604       if (fd < 0) {
08605          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08606          return -1;
08607       }
08608       x = channels[y];
08609       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08610          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08611          close(fd);
08612          return -1;
08613       }
08614       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08615          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08616          return -1;
08617       }
08618       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08619          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08620          close(fd);
08621          return -1;
08622       }
08623       span = p.spanno - 1;
08624       if (pris[span].trunkgroup) {
08625          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08626          close(fd);
08627          return -1;
08628       }
08629       if (pris[span].pvts[0]) {
08630          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08631          close(fd);
08632          return -1;
08633       }
08634       if (!y) {
08635          pris[span].trunkgroup = trunkgroup;
08636          pris[span].offset = channels[y] - p.chanpos;
08637          ospan = span;
08638       }
08639       pris[ospan].dchannels[y] = channels[y];
08640       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08641       pris[span].span = span + 1;
08642       close(fd);
08643    }
08644    return 0;   
08645 }

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

Definition at line 10858 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_hangup(), dahdi_request(), dahdi_pri::dchannels, dahdi_pri::dchans, do_idle_thread(), dahdi_pri::fds, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::isidlecall, dahdi_pri::lastreset, dahdi_pri::lock, dahdi_pri::minidle, dahdi_pri::minunused, ast_channel::name, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pri::pri, pri_check_restart(), pri_is_up(), dahdi_pri::pvts, dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, and dahdi_pri::switchtype.

10859 {
10860    struct dahdi_pri *pri = vpri;
10861    pri_event *e;
10862    struct pollfd fds[NUM_DCHANS];
10863    int res;
10864    int chanpos = 0;
10865    int x;
10866    int haveidles;
10867    int activeidles;
10868    int nextidle = -1;
10869    struct ast_channel *c;
10870    struct timeval tv, lowest, *next;
10871    struct timeval lastidle = ast_tvnow();
10872    int doidling=0;
10873    char *cc;
10874    char idlen[80];
10875    struct ast_channel *idle;
10876    pthread_t p;
10877    time_t t;
10878    int i, which=-1;
10879    int numdchans;
10880    int cause=0;
10881    struct dahdi_pvt *crv;
10882    pthread_t threadid;
10883    char ani2str[6];
10884    char plancallingnum[256];
10885    char plancallingani[256];
10886    char calledtonstr[10];
10887    
10888    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
10889 
10890    gettimeofday(&lastidle, NULL);
10891    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
10892       /* Need to do idle dialing, check to be sure though */
10893       cc = strchr(pri->idleext, '@');
10894       if (cc) {
10895          *cc = '\0';
10896          cc++;
10897          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
10898 #if 0
10899          /* Extensions may not be loaded yet */
10900          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
10901             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
10902          else
10903 #endif
10904             doidling = 1;
10905       } else
10906          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
10907    }
10908    for (;;) {
10909       for (i = 0; i < NUM_DCHANS; i++) {
10910          if (!pri->dchannels[i])
10911             break;
10912          fds[i].fd = pri->fds[i];
10913          fds[i].events = POLLIN | POLLPRI;
10914          fds[i].revents = 0;
10915       }
10916       numdchans = i;
10917       time(&t);
10918       ast_mutex_lock(&pri->lock);
10919       if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
10920          if (pri->resetting && pri_is_up(pri)) {
10921             if (pri->resetpos < 0)
10922                pri_check_restart(pri);
10923          } else {
10924             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
10925                pri->resetting = 1;
10926                pri->resetpos = -1;
10927             }
10928          }
10929       }
10930       /* Look for any idle channels if appropriate */
10931       if (doidling && pri_is_up(pri)) {
10932          nextidle = -1;
10933          haveidles = 0;
10934          activeidles = 0;
10935          for (x = pri->numchans; x >= 0; x--) {
10936             if (pri->pvts[x] && !pri->pvts[x]->owner && 
10937                 !pri->pvts[x]->call) {
10938                if (haveidles < pri->minunused) {
10939                   haveidles++;
10940                } else if (!pri->pvts[x]->resetting) {
10941                   nextidle = x;
10942                   break;
10943                }
10944             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
10945                activeidles++;
10946          }
10947          if (nextidle > -1) {
10948             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
10949                /* Don't create a new idle call more than once per second */
10950                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
10951                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
10952                if (idle) {
10953                   pri->pvts[nextidle]->isidlecall = 1;
10954                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
10955                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
10956                      dahdi_hangup(idle);
10957                   }
10958                } else
10959                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
10960                lastidle = ast_tvnow();
10961             }
10962          } else if ((haveidles < pri->minunused) &&
10963                (activeidles > pri->minidle)) {
10964             /* Mark something for hangup if there is something 
10965                that can be hungup */
10966             for (x = pri->numchans; x >= 0; x--) {
10967                /* find a candidate channel */
10968                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
10969                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10970                   haveidles++;
10971                   /* Stop if we have enough idle channels or
10972                     can't spare any more active idle ones */
10973                   if ((haveidles >= pri->minunused) ||
10974                       (activeidles <= pri->minidle))
10975                      break;
10976                } 
10977             }
10978          }
10979       }
10980       /* Start with reasonable max */
10981       lowest = ast_tv(60, 0);
10982       for (i = 0; i < NUM_DCHANS; i++) {
10983          /* Find lowest available d-channel */
10984          if (!pri->dchannels[i])
10985             break;
10986          if ((next = pri_schedule_next(pri->dchans[i]))) {
10987             /* We need relative time here */
10988             tv = ast_tvsub(*next, ast_tvnow());
10989             if (tv.tv_sec < 0) {
10990                tv = ast_tv(0,0);
10991             }
10992             if (doidling || pri->resetting) {
10993                if (tv.tv_sec > 1) {
10994                   tv = ast_tv(1, 0);
10995                }
10996             } else {
10997                if (tv.tv_sec > 60) {
10998                   tv = ast_tv(60, 0);
10999                }
11000             }
11001          } else if (doidling || pri->resetting) {
11002             /* Make sure we stop at least once per second if we're
11003                monitoring idle channels */
11004             tv = ast_tv(1,0);
11005          } else {
11006             /* Don't poll for more than 60 seconds */
11007             tv = ast_tv(60, 0);
11008          }
11009          if (!i || ast_tvcmp(tv, lowest) < 0) {
11010             lowest = tv;
11011          }
11012       }
11013       ast_mutex_unlock(&pri->lock);
11014 
11015       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
11016       pthread_testcancel();
11017       e = NULL;
11018       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
11019       pthread_testcancel();
11020       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
11021 
11022       ast_mutex_lock(&pri->lock);
11023       if (!res) {
11024          for (which = 0; which < NUM_DCHANS; which++) {
11025             if (!pri->dchans[which])
11026                break;
11027             /* Just a timeout, run the scheduler */
11028             e = pri_schedule_run(pri->dchans[which]);
11029             if (e)
11030                break;
11031          }
11032       } else if (res > -1) {
11033          for (which = 0; which < NUM_DCHANS; which++) {
11034             if (!pri->dchans[which])
11035                break;
11036             if (fds[which].revents & POLLPRI) {
11037                /* Check for an event */
11038                x = 0;
11039                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
11040                if (x) {
11041                   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);
11042                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
11043                      "PRIEvent: %s\r\n"
11044                      "PRIEventCode: %d\r\n"
11045                      "D-channel: %s\r\n"
11046                      "Span: %d\r\n",
11047                      event2str(x),
11048                      x,
11049                      pri_order(which),
11050                      pri->span
11051                      );
11052                }
11053                /* Keep track of alarm state */  
11054                if (x == DAHDI_EVENT_ALARM) {
11055                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
11056                   pri_find_dchan(pri);
11057                } else if (x == DAHDI_EVENT_NOALARM) {
11058                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
11059                   pri_restart(pri->dchans[which]);
11060                }
11061             
11062                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
11063             } else if (fds[which].revents & POLLIN) {
11064                e = pri_check_event(pri->dchans[which]);
11065             }
11066             if (e)
11067                break;
11068          }
11069       } else if (errno != EINTR)
11070          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
11071 
11072       if (e) {
11073          if (pri->debug)
11074             pri_dump_event(pri->dchans[which], e);
11075 
11076          if (e->e != PRI_EVENT_DCHAN_DOWN) {
11077             if (!(pri->dchanavail[which] & DCHAN_UP)) {
11078                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
11079             }
11080             pri->dchanavail[which] |= DCHAN_UP;
11081          } else {
11082             if (pri->dchanavail[which] & DCHAN_UP) {
11083                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
11084             }
11085             pri->dchanavail[which] &= ~DCHAN_UP;
11086          }
11087 
11088          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
11089             /* Must be an NFAS group that has the secondary dchan active */
11090             pri->pri = pri->dchans[which];
11091 
11092          switch (e->e) {
11093          case PRI_EVENT_DCHAN_UP:
11094             if (!pri->pri) pri_find_dchan(pri);
11095 
11096             /* Note presense of D-channel */
11097             time(&pri->lastreset);
11098 
11099             /* Restart in 5 seconds */
11100             if (pri->resetinterval > -1) {
11101                pri->lastreset -= pri->resetinterval;
11102                pri->lastreset += 5;
11103             }
11104             pri->resetting = 0;
11105             /* Take the channels from inalarm condition */
11106             for (i = 0; i < pri->numchans; i++)
11107                if (pri->pvts[i]) {
11108                   pri->pvts[i]->inalarm = 0;
11109                }
11110             break;
11111          case PRI_EVENT_DCHAN_DOWN:
11112             pri_find_dchan(pri);
11113             if (!pri_is_up(pri)) {
11114                pri->resetting = 0;
11115                /* Hangup active channels and put them in alarm mode */
11116                for (i = 0; i < pri->numchans; i++) {
11117                   struct dahdi_pvt *p = pri->pvts[i];
11118                   if (p) {
11119                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
11120                         /* T309 is not enabled : hangup calls when alarm occurs */
11121                         if (p->call) {
11122                            if (p->pri && p->pri->pri) {
11123                               pri_hangup(p->pri->pri, p->call, -1);
11124                               pri_destroycall(p->pri->pri, p->call);
11125                               p->call = NULL;
11126                            } else
11127                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
11128                         }
11129                         if (p->realcall) {
11130                            pri_hangup_all(p->realcall, pri);
11131                         } else if (p->owner)
11132                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11133                      }
11134                      p->inalarm = 1;
11135                   }
11136                }
11137             }
11138             break;
11139          case PRI_EVENT_RESTART:
11140             if (e->restart.channel > -1) {
11141                chanpos = pri_find_principle(pri, e->restart.channel);
11142                if (chanpos < 0)
11143                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n", 
11144                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11145                else {
11146                   ast_verb(3, "B-channel %d/%d restarted on span %d\n",
11147                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
11148                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11149                   if (pri->pvts[chanpos]->call) {
11150                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
11151                      pri->pvts[chanpos]->call = NULL;
11152                   }
11153                   /* Force soft hangup if appropriate */
11154                   if (pri->pvts[chanpos]->realcall) 
11155                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11156                   else if (pri->pvts[chanpos]->owner)
11157                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11158                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11159                }
11160             } else {
11161                ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
11162                for (x = 0; x < pri->numchans; x++)
11163                   if (pri->pvts[x]) {
11164                      ast_mutex_lock(&pri->pvts[x]->lock);
11165                      if (pri->pvts[x]->call) {
11166                         pri_destroycall(pri->pri, pri->pvts[x]->call);
11167                         pri->pvts[x]->call = NULL;
11168                      }
11169                      if (pri->pvts[chanpos]->realcall) 
11170                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11171                      else if (pri->pvts[x]->owner)
11172                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11173                      ast_mutex_unlock(&pri->pvts[x]->lock);
11174                   }
11175             }
11176             break;
11177          case PRI_EVENT_KEYPAD_DIGIT:
11178             chanpos = pri_find_principle(pri, e->digit.channel);
11179             if (chanpos < 0) {
11180                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
11181                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
11182             } else {
11183                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
11184                if (chanpos > -1) {
11185                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11186                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
11187                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
11188                      /* how to do that */
11189                      int digitlen = strlen(e->digit.digits);
11190                      char digit;
11191                      int i;               
11192                      for (i = 0; i < digitlen; i++) { 
11193                         digit = e->digit.digits[i];
11194                         {
11195                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
11196                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11197                         }
11198                      }
11199                   }
11200                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11201                }
11202             }
11203             break;
11204             
11205          case PRI_EVENT_INFO_RECEIVED:
11206             chanpos = pri_find_principle(pri, e->ring.channel);
11207             if (chanpos < 0) {
11208                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
11209                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11210             } else {
11211                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
11212                if (chanpos > -1) {
11213                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11214                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
11215                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
11216                      /* how to do that */
11217                      int digitlen = strlen(e->ring.callednum);
11218                      char digit;
11219                      int i;               
11220                      for (i = 0; i < digitlen; i++) { 
11221                         digit = e->ring.callednum[i];
11222                         {
11223                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
11224                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11225                         }
11226                      }
11227                   }
11228                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11229                }
11230             }
11231             break;
11232          case PRI_EVENT_RING:
11233             crv = NULL;
11234             if (e->ring.channel == -1)
11235                chanpos = pri_find_empty_chan(pri, 1);
11236             else
11237                chanpos = pri_find_principle(pri, e->ring.channel);
11238             /* if no channel specified find one empty */
11239             if (chanpos < 0) {
11240                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
11241                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11242             } else {
11243                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11244                if (pri->pvts[chanpos]->owner) {
11245                   if (pri->pvts[chanpos]->call == e->ring.call) {
11246                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
11247                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11248                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11249                      break;
11250                   } else {
11251                      /* This is where we handle initial glare */
11252                      ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n", 
11253                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
11254                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11255                      chanpos = -1;
11256                   }
11257                }
11258                if (chanpos > -1)
11259                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11260             }
11261             if ((chanpos < 0) && (e->ring.flexible))
11262                chanpos = pri_find_empty_chan(pri, 1);
11263             if (chanpos > -1) {
11264                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11265                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
11266                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
11267                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
11268                   if (crv)
11269                      ast_mutex_lock(&crv->lock);
11270                   if (!crv || crv->owner) {
11271                      pri->pvts[chanpos]->call = NULL;
11272                      if (crv) {
11273                         if (crv->owner)
11274                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11275                         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);
11276                      } else
11277                         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);
11278                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
11279                      if (crv)
11280                         ast_mutex_unlock(&crv->lock);
11281                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11282                      break;
11283                   }
11284                }
11285                pri->pvts[chanpos]->call = e->ring.call;
11286                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
11287                if (pri->pvts[chanpos]->use_callerid) {
11288                   ast_shrink_phone_number(plancallingnum);
11289                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
11290 #ifdef PRI_ANI
11291                   if (!ast_strlen_zero(e->ring.callingani)) {
11292                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
11293                      ast_shrink_phone_number(plancallingani);
11294                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
11295                   } else {
11296                      pri->pvts[chanpos]->cid_ani[0] = '\0';
11297                   }
11298 #endif
11299                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
11300                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
11301                } else {
11302                   pri->pvts[chanpos]->cid_num[0] = '\0';
11303                   pri->pvts[chanpos]->cid_ani[0] = '\0';
11304                   pri->pvts[chanpos]->cid_name[0] = '\0';
11305                   pri->pvts[chanpos]->cid_ton = 0;
11306                }
11307                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
11308                           e->ring.redirectingnum, e->ring.callingplanrdnis);
11309                /* If immediate=yes go to s|1 */
11310                if (pri->pvts[chanpos]->immediate) {
11311                   ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
11312                   pri->pvts[chanpos]->exten[0] = 's';
11313                   pri->pvts[chanpos]->exten[1] = '\0';
11314                }
11315                /* Get called number */
11316                else if (!ast_strlen_zero(e->ring.callednum)) {
11317                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
11318                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11319                } else if (pri->overlapdial)
11320                   pri->pvts[chanpos]->exten[0] = '\0';
11321                else {
11322                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
11323                   pri->pvts[chanpos]->exten[0] = 's';
11324                   pri->pvts[chanpos]->exten[1] = '\0';
11325                }
11326                /* Set DNID on all incoming calls -- even immediate */
11327                if (!ast_strlen_zero(e->ring.callednum))
11328                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
11329                /* No number yet, but received "sending complete"? */
11330                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
11331                   ast_verb(3, "Going to extension s|1 because of Complete received\n");
11332                   pri->pvts[chanpos]->exten[0] = 's';
11333                   pri->pvts[chanpos]->exten[1] = '\0';
11334                }
11335                /* Make sure extension exists (or in overlap dial mode, can exist) */
11336                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
11337                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11338                   /* Setup law */
11339                   int law;
11340                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
11341                      /* Set to audio mode at this point */
11342                      law = 1;
11343                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11344                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
11345                   }
11346                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
11347                      law = DAHDI_LAW_ALAW;
11348                   else
11349                      law = DAHDI_LAW_MULAW;
11350                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
11351                   if (res < 0) 
11352                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
11353                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
11354                   if (res < 0)
11355                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
11356                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
11357                      /* Just announce proceeding */
11358                      pri->pvts[chanpos]->proceeding = 1;
11359                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
11360                   } else {
11361                      if (pri->switchtype != PRI_SWITCH_GR303_TMC) 
11362                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11363                      else
11364                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
11365                   }
11366                   /* Get the use_callingpres state */
11367                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
11368                
11369                   /* Start PBX */
11370                   if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
11371                      /* Release the PRI lock while we create the channel */
11372                      ast_mutex_unlock(&pri->lock);
11373                      if (crv) {
11374                         /* Set bearer and such */
11375                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
11376                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11377                         pri->pvts[chanpos]->owner = &inuse;
11378                         ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
11379                      } else {
11380                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
11381                      }
11382 
11383                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11384 
11385                      if (!ast_strlen_zero(e->ring.callingsubaddr)) {
11386                         pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
11387                      }
11388                      if (e->ring.ani2 >= 0) {
11389                         snprintf(ani2str, 5, "%.2d", e->ring.ani2);
11390                         pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11391                         pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11392                      }
11393 
11394 #ifdef SUPPORT_USERUSER
11395                      if (!ast_strlen_zero(e->ring.useruserinfo)) {
11396                         pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11397                      }
11398 #endif
11399 
11400                      snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11401                      pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11402                      if (e->ring.redirectingreason >= 0)
11403                         pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11404                   
11405                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11406                      ast_mutex_lock(&pri->lock);
11407                      if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
11408                         ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
11409                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
11410                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11411                      } else {
11412                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
11413                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11414                         if (c)
11415                            ast_hangup(c);
11416                         else {
11417                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11418                            pri->pvts[chanpos]->call = NULL;
11419                         }
11420                      }
11421                   } else  {
11422                      ast_mutex_unlock(&pri->lock);
11423                      /* Release PRI lock while we create the channel */
11424                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
11425                      if (c) {
11426                         char calledtonstr[10];
11427 
11428                         ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11429 
11430                         if (e->ring.ani2 >= 0) {
11431                            snprintf(ani2str, 5, "%d", e->ring.ani2);
11432                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
11433                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
11434                         }
11435 
11436 #ifdef SUPPORT_USERUSER
11437                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
11438                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
11439                         }
11440 #endif
11441 
11442                         if (e->ring.redirectingreason >= 0)
11443                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
11444                      
11445                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
11446                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
11447 
11448                         ast_mutex_lock(&pri->pvts[chanpos]->lock);
11449                         ast_mutex_lock(&pri->lock);
11450 
11451                         ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
11452                               plancallingnum, pri->pvts[chanpos]->exten, 
11453                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11454 
11455                         dahdi_enable_ec(pri->pvts[chanpos]);
11456                      } else {
11457 
11458                         ast_mutex_lock(&pri->lock);
11459 
11460                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", 
11461                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
11462                         pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
11463                         pri->pvts[chanpos]->call = NULL;
11464                      }
11465                   }
11466                } else {
11467                   ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
11468                         pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
11469                            pri->pvts[chanpos]->prioffset, pri->span);
11470                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
11471                   pri->pvts[chanpos]->call = NULL;
11472                   pri->pvts[chanpos]->exten[0] = '\0';
11473                }
11474                if (crv)
11475                   ast_mutex_unlock(&crv->lock);
11476                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11477             } else {
11478                if (e->ring.flexible)
11479                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
11480                else
11481                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
11482             }
11483             break;
11484          case PRI_EVENT_RINGING:
11485             chanpos = pri_find_principle(pri, e->ringing.channel);
11486             if (chanpos < 0) {
11487                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
11488                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11489             } else {
11490                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
11491                if (chanpos < 0) {
11492                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
11493                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
11494                } else {
11495                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11496                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11497                      dahdi_enable_ec(pri->pvts[chanpos]);
11498                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
11499                      pri->pvts[chanpos]->alerting = 1;
11500                   } else
11501                      ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
11502 
11503 #ifdef PRI_PROGRESS_MASK
11504                   if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11505 #else
11506                   if (e->ringing.progress == 8) {
11507 #endif
11508                      /* Now we can do call progress detection */
11509                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11510                         /* RINGING detection isn't required because we got ALERTING signal */
11511                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
11512                         pri->pvts[chanpos]->dsp_features = 0;
11513                      }
11514                   }
11515 
11516 #ifdef SUPPORT_USERUSER
11517                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
11518                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11519                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11520                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
11521                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11522                   }
11523 #endif
11524 
11525                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11526                }
11527             }
11528             break;
11529          case PRI_EVENT_PROGRESS:
11530             /* Get chan value if e->e is not PRI_EVNT_RINGING */
11531             chanpos = pri_find_principle(pri, e->proceeding.channel);
11532             if (chanpos > -1) {
11533 #ifdef PRI_PROGRESS_MASK
11534                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
11535 #else
11536                if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
11537 #endif
11538                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11539 
11540                   if (e->proceeding.cause > -1) {
11541                      ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
11542 
11543                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
11544                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
11545                         if (pri->pvts[chanpos]->owner) {
11546                            ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
11547 
11548                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
11549                            f.subclass = AST_CONTROL_BUSY;
11550                         }
11551                      }
11552                   }
11553                   
11554                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11555                   ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
11556                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11557                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11558 #ifdef PRI_PROGRESS_MASK
11559                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11560 #else
11561                   if (e->proceeding.progress == 8) {
11562 #endif
11563                      /* Now we can do call progress detection */
11564                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11565                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11566                         pri->pvts[chanpos]->dsp_features = 0;
11567                      }
11568                      /* Bring voice path up */
11569                      f.subclass = AST_CONTROL_PROGRESS;
11570                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11571                   }
11572                   pri->pvts[chanpos]->progress = 1;
11573                   pri->pvts[chanpos]->dialing = 0;
11574                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11575                }
11576             }
11577             break;
11578          case PRI_EVENT_PROCEEDING:
11579             chanpos = pri_find_principle(pri, e->proceeding.channel);
11580             if (chanpos > -1) {
11581                if (!pri->pvts[chanpos]->proceeding) {
11582                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11583                   
11584                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11585                   ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
11586                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
11587                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11588 #ifdef PRI_PROGRESS_MASK
11589                   if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
11590 #else
11591                   if (e->proceeding.progress == 8) {
11592 #endif
11593                      /* Now we can do call progress detection */
11594                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11595                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11596                         pri->pvts[chanpos]->dsp_features = 0;
11597                      }
11598                      /* Bring voice path up */
11599                      f.subclass = AST_CONTROL_PROGRESS;
11600                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11601                   }
11602                   pri->pvts[chanpos]->proceeding = 1;
11603                   pri->pvts[chanpos]->dialing = 0;
11604                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11605                }
11606             }
11607             break;
11608          case PRI_EVENT_FACNAME:
11609             chanpos = pri_find_principle(pri, e->facname.channel);
11610             if (chanpos < 0) {
11611                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
11612                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11613             } else {
11614                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
11615                if (chanpos < 0) {
11616                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
11617                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
11618                } else {
11619                   /* Re-use *69 field for PRI */
11620                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11621                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
11622                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
11623                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
11624                   dahdi_enable_ec(pri->pvts[chanpos]);
11625                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11626                }
11627             }
11628             break;            
11629          case PRI_EVENT_ANSWER:
11630             chanpos = pri_find_principle(pri, e->answer.channel);
11631             if (chanpos < 0) {
11632                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
11633                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11634             } else {
11635                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
11636                if (chanpos < 0) {
11637                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
11638                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
11639                } else {
11640                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11641                   /* Now we can do call progress detection */
11642 
11643                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
11644                    * By this time, we need DTMF detection and other features that were previously disabled
11645                    * -- Matt F */
11646                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
11647                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
11648                      pri->pvts[chanpos]->dsp_features = 0;
11649                   }
11650                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
11651                      ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
11652                      x = DAHDI_START;
11653                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
11654                      if (res < 0) {
11655                         if (errno != EINPROGRESS) {
11656                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
11657                         }
11658                      }
11659                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
11660                      pri->pvts[chanpos]->dialing = 1;
11661                      /* Send any "w" waited stuff */
11662                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
11663                      if (res < 0) {
11664                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
11665                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11666                      } else
11667                         ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
11668 
11669                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
11670                   } else if (pri->pvts[chanpos]->confirmanswer) {
11671                      ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
11672                   } else {
11673                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
11674                      /* Enable echo cancellation if it's not on already */
11675                      dahdi_enable_ec(pri->pvts[chanpos]);
11676                   }
11677 
11678 #ifdef SUPPORT_USERUSER
11679                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
11680                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11681                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11682                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
11683                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11684                   }
11685 #endif
11686 
11687                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11688                }
11689             }
11690             break;            
11691          case PRI_EVENT_HANGUP:
11692             chanpos = pri_find_principle(pri, e->hangup.channel);
11693             if (chanpos < 0) {
11694                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
11695                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11696             } else {
11697                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11698                if (chanpos > -1) {
11699                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11700                   if (!pri->pvts[chanpos]->alreadyhungup) {
11701                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
11702                      pri->pvts[chanpos]->alreadyhungup = 1;
11703                      if (pri->pvts[chanpos]->realcall) 
11704                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11705                      else if (pri->pvts[chanpos]->owner) {
11706                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
11707                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11708                         if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11709                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11710                         else {
11711                            switch (e->hangup.cause) {
11712                            case PRI_CAUSE_USER_BUSY:
11713                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11714                               break;
11715                            case PRI_CAUSE_CALL_REJECTED:
11716                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11717                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11718                            case PRI_CAUSE_SWITCH_CONGESTION:
11719                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11720                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11721                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11722                               break;
11723                            default:
11724                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11725                            }
11726                         }
11727                      }
11728                      ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
11729                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
11730                   } else {
11731                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11732                      pri->pvts[chanpos]->call = NULL;
11733                   }
11734                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11735                      ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
11736                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11737                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11738                      pri->pvts[chanpos]->resetting = 1;
11739                   }
11740                   if (e->hangup.aoc_units > -1)
11741                      ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11742                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11743 
11744 #ifdef SUPPORT_USERUSER
11745                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
11746                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11747                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11748                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11749                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11750                   }
11751 #endif
11752 
11753                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11754                } else {
11755                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
11756                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11757                }
11758             } 
11759             break;
11760 #ifndef PRI_EVENT_HANGUP_REQ
11761 #error please update libpri
11762 #endif
11763          case PRI_EVENT_HANGUP_REQ:
11764             chanpos = pri_find_principle(pri, e->hangup.channel);
11765             if (chanpos < 0) {
11766                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
11767                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11768             } else {
11769                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11770                if (chanpos > -1) {
11771                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11772                   if (pri->pvts[chanpos]->realcall) 
11773                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11774                   else if (pri->pvts[chanpos]->owner) {
11775                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
11776                      if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
11777                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11778                      else {
11779                         switch (e->hangup.cause) {
11780                            case PRI_CAUSE_USER_BUSY:
11781                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
11782                               break;
11783                            case PRI_CAUSE_CALL_REJECTED:
11784                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
11785                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
11786                            case PRI_CAUSE_SWITCH_CONGESTION:
11787                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
11788                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
11789                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
11790                               break;
11791                            default:
11792                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11793                         }
11794                      }
11795                      ast_verb(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);
11796                      if (e->hangup.aoc_units > -1)
11797                         ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
11798                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
11799                   } else {
11800                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
11801                      pri->pvts[chanpos]->call = NULL;
11802                   }
11803                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
11804                      ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
11805                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11806                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
11807                      pri->pvts[chanpos]->resetting = 1;
11808                   }
11809 
11810 #ifdef SUPPORT_USERUSER
11811                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11812                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11813                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11814                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11815                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11816                   }
11817 #endif
11818 
11819                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11820                } else {
11821                   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);
11822                }
11823             } 
11824             break;
11825          case PRI_EVENT_HANGUP_ACK:
11826             chanpos = pri_find_principle(pri, e->hangup.channel);
11827             if (chanpos < 0) {
11828                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n", 
11829                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11830             } else {
11831                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
11832                if (chanpos > -1) {
11833                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11834                   pri->pvts[chanpos]->call = NULL;
11835                   pri->pvts[chanpos]->resetting = 0;
11836                   if (pri->pvts[chanpos]->owner) {
11837                      ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
11838                   }
11839 
11840 #ifdef SUPPORT_USERUSER
11841                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
11842                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
11843                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11844                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
11845                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11846                   }
11847 #endif
11848 
11849                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11850                }
11851             }
11852             break;
11853          case PRI_EVENT_CONFIG_ERR:
11854             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
11855             break;
11856          case PRI_EVENT_RESTART_ACK:
11857             chanpos = pri_find_principle(pri, e->restartack.channel);
11858             if (chanpos < 0) {
11859                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
11860                   channel number, so we have to figure it out...  This must be why
11861                   everybody resets exactly a channel at a time. */
11862                for (x = 0; x < pri->numchans; x++) {
11863                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
11864                      chanpos = x;
11865                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
11866                      ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan, 
11867                         pri->pvts[chanpos]->prioffset, pri->span);
11868                      if (pri->pvts[chanpos]->realcall) 
11869                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11870                      else if (pri->pvts[chanpos]->owner) {
11871                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan, 
11872                            pri->pvts[chanpos]->prioffset, pri->span);
11873                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11874                      }
11875                      pri->pvts[chanpos]->resetting = 0;
11876                      ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11877                            pri->pvts[chanpos]->prioffset, pri->span);
11878                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11879                      if (pri->resetting)
11880                         pri_check_restart(pri);
11881                      break;
11882                   }
11883                }
11884                if (chanpos < 0) {
11885                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n", 
11886                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11887                }
11888             } else {
11889                if (pri->pvts[chanpos]) {
11890                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11891                   if (pri->pvts[chanpos]->realcall) 
11892                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
11893                   else if (pri->pvts[chanpos]->owner) {
11894                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
11895                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
11896                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11897                   }
11898                   pri->pvts[chanpos]->resetting = 0;
11899                   pri->pvts[chanpos]->inservice = 1;
11900                   ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
11901                            pri->pvts[chanpos]->prioffset, pri->span);
11902                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11903                   if (pri->resetting)
11904                      pri_check_restart(pri);
11905                }
11906             }
11907             break;
11908          case PRI_EVENT_SETUP_ACK:
11909             chanpos = pri_find_principle(pri, e->setup_ack.channel);
11910             if (chanpos < 0) {
11911                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n", 
11912                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
11913             } else {
11914                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
11915                if (chanpos > -1) {
11916                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
11917                   pri->pvts[chanpos]->setup_ack = 1;
11918                   /* Send any queued digits */
11919                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
11920                      ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
11921                      pri_information(pri->pri, pri->pvts[chanpos]->call, 
11922                         pri->pvts[chanpos]->dialdest[x]);
11923                   }
11924                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11925                } else
11926                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
11927             }
11928             break;
11929          case PRI_EVENT_NOTIFY:
11930             chanpos = pri_find_principle(pri, e->notify.channel);
11931             if (chanpos < 0) {
11932                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
11933                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
11934             } else {
11935                struct ast_frame f = { AST_FRAME_CONTROL, };
11936                ast_mutex_lock(&pri->pvts[chanpos]->lock);
11937                switch (e->notify.info) {
11938                case PRI_NOTIFY_REMOTE_HOLD:
11939                   f.subclass = AST_CONTROL_HOLD;
11940                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11941                   break;
11942                case PRI_NOTIFY_REMOTE_RETRIEVAL:
11943                   f.subclass = AST_CONTROL_UNHOLD;
11944                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
11945                   break;
11946                }
11947                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
11948             }
11949             break;
11950          default:
11951             ast_debug(1, "Event: %d\n", e->e);
11952          }
11953       }  
11954       ast_mutex_unlock(&pri->lock);
11955    }
11956    /* Never reached */
11957    return NULL;
11958 }

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

Definition at line 10511 of file chan_dahdi.c.

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

10512 {
10513    struct dahdi_pvt *p;
10514    p = pri->crvs;
10515    while (p) {
10516       if (p->channel == crv)
10517          return p;
10518       p = p->next;
10519    }
10520    return NULL;
10521 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 3364 of file chan_dahdi.c.

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

03365 {
03366    int oldslot = -1;
03367    struct pri *old;
03368    int newslot = -1;
03369    int x;
03370    old = pri->pri;
03371    for (x = 0; x < NUM_DCHANS; x++) {
03372       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03373          newslot = x;
03374       if (pri->dchans[x] == old) {
03375          oldslot = x;
03376       }
03377    }
03378    if (newslot < 0) {
03379       newslot = 0;
03380       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03381          pri->dchannels[newslot]);
03382    }
03383    if (old && (oldslot != newslot))
03384       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03385          pri->dchannels[oldslot], pri->dchannels[newslot]);
03386    pri->pri = pri->dchans[newslot];
03387    return 0;
03388 }

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

Definition at line 9415 of file chan_dahdi.c.

References ast_debug, dahdi_pvt::inalarm, dahdi_pvt::logicalspan, dahdi_pri::numchans, dahdi_pvt::owner, dahdi_pvt::prioffset, and dahdi_pri::pvts.

Referenced by dahdi_request().

09416 {
09417    int x;
09418    if (backwards)
09419       x = pri->numchans;
09420    else
09421       x = 0;
09422    for (;;) {
09423       if (backwards && (x < 0))
09424          break;
09425       if (!backwards && (x >= pri->numchans))
09426          break;
09427       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09428          ast_debug(1, "Found empty available channel %d/%d\n", 
09429             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09430          return x;
09431       }
09432       if (backwards)
09433          x--;
09434       else
09435          x++;
09436    }
09437    return -1;
09438 }

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

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

10525 {
10526    int x;
10527    int span = PRI_SPAN(channel);
10528    int spanfd;
10529    struct dahdi_params param;
10530    int principle = -1;
10531    int explicit = PRI_EXPLICIT(channel);
10532    channel = PRI_CHANNEL(channel);
10533 
10534    if (!explicit) {
10535       spanfd = pri_active_dchan_fd(pri);
10536       memset(&param, 0, sizeof(param));
10537       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10538          return -1;
10539       span = pris[param.spanno - 1].prilogicalspan;
10540    }
10541 
10542    for (x = 0; x < pri->numchans; x++) {
10543       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10544          principle = x;
10545          break;
10546       }
10547    }
10548    
10549    return principle;
10550 }

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

Definition at line 10552 of file chan_dahdi.c.

References ast_channel_set_fd(), ast_log(), ast_string_field_build, ast_verb, dahdi_pvt::call, name, dahdi_pri::numchans, dahdi_pvt::pri, dahdi_pri::pvts, SUB_REAL, and dahdi_pri::trunkgroup.

10553 {
10554    int x;
10555    struct dahdi_pvt *crv;
10556    if (!c) {
10557       if (principle < 0)
10558          return -1;
10559       return principle;
10560    }
10561    if ((principle > -1) && 
10562       (principle < pri->numchans) && 
10563       (pri->pvts[principle]) && 
10564       (pri->pvts[principle]->call == c))
10565       return principle;
10566    /* First, check for other bearers */
10567    for (x = 0; x < pri->numchans; x++) {
10568       if (!pri->pvts[x])
10569          continue;
10570       if (pri->pvts[x]->call == c) {
10571          /* Found our call */
10572          if (principle != x) {
10573             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10574 
10575             ast_verb(3, "Moving call from channel %d to channel %d\n",
10576                 old->channel, new->channel);
10577             if (new->owner) {
10578                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10579                   old->channel, new->channel, new->channel);
10580                return -1;
10581             }
10582             /* Fix it all up now */
10583             new->owner = old->owner;
10584             old->owner = NULL;
10585             if (new->owner) {
10586                ast_string_field_build(new->owner, name, 
10587                             "DAHDI/%d:%d-%d", pri->trunkgroup,
10588                             new->channel, 1);
10589                new->owner->tech_pvt = new;
10590                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10591                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10592                old->subs[SUB_REAL].owner = NULL;
10593             } else
10594                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);
10595             new->call = old->call;
10596             old->call = NULL;
10597 
10598             /* Copy any DSP that may be present */
10599             new->dsp = old->dsp;
10600             new->dsp_features = old->dsp_features;
10601             old->dsp = NULL;
10602             old->dsp_features = 0;
10603          }
10604          return principle;
10605       }
10606    }
10607    /* Now check for a CRV with no bearer */
10608    crv = pri->crvs;
10609    while (crv) {
10610       if (crv->call == c) {
10611          /* This is our match...  Perform some basic checks */
10612          if (crv->bearer)
10613             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10614          else if (pri->pvts[principle]->owner) 
10615             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10616          else {
10617             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
10618                wakeup the potential sleeper */
10619             dahdi_close_sub(crv, SUB_REAL);
10620             pri->pvts[principle]->call = crv->call;
10621             pri_assign_bearer(crv, pri, pri->pvts[principle]);
10622             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10623                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10624                pri->trunkgroup, crv->channel);
10625             wakeup_sub(crv, SUB_REAL, pri);
10626          }
10627          return principle;
10628       }
10629       crv = crv->next;
10630    }
10631    ast_log(LOG_WARNING, "Call specified, but not found?\n");
10632    return -1;
10633 }

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

Definition at line 1247 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_send_keypad_facility_exec(), and dahdi_write().

01248 {
01249    int res;
01250    /* Grab the lock first */
01251    do {
01252       res = ast_mutex_trylock(&pri->lock);
01253       if (res) {
01254          DEADLOCK_AVOIDANCE(&pvt->lock);
01255       }
01256    } while (res);
01257    /* Then break the poll */
01258    if (pri->master != AST_PTHREADT_NULL)
01259       pthread_kill(pri->master, SIGURG);
01260    return 0;
01261 }

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

Definition at line 10783 of file chan_dahdi.c.

References AST_CAUSE_PRE_EMPTED, ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup_with_cause(), DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

10784 {
10785    int x;
10786    int redo;
10787    ast_mutex_unlock(&pri->lock);
10788    ast_mutex_lock(&p->lock);
10789    do {
10790       redo = 0;
10791       for (x = 0; x < 3; x++) {
10792          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10793             redo++;
10794             DEADLOCK_AVOIDANCE(&p->lock);
10795          }
10796          if (p->subs[x].owner) {
10797             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10798             ast_channel_unlock(p->subs[x].owner);
10799          }
10800       }
10801    } while (redo);
10802    ast_mutex_unlock(&p->lock);
10803    ast_mutex_lock(&pri->lock);
10804    return 0;
10805 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3312 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

03313 {
03314    int x;
03315    for (x = 0; x < NUM_DCHANS; x++) {
03316       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03317          return 1;
03318    }
03319    return 0;
03320 }

static char* pri_order ( int  level  )  [static]

Definition at line 3335 of file chan_dahdi.c.

Referenced by handle_pri_show_span().

03336 {
03337    switch (level) {
03338    case 0:
03339       return "Primary";
03340    case 1:
03341       return "Secondary";
03342    case 2:
03343       return "Tertiary";
03344    case 3:
03345       return "Quaternary";
03346    default:
03347       return "<Unknown>";
03348    }     
03349 }

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

Definition at line 455 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_send_keypad_facility_exec(), and dahdi_write().

00456 {
00457    ast_mutex_unlock(&pri->lock);
00458 }

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

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

08539 {
08540    int x;
08541    int trunkgroup;
08542    /* Get appropriate trunk group if there is one */
08543    trunkgroup = pris[*span].mastertrunkgroup;
08544    if (trunkgroup) {
08545       /* Select a specific trunk group */
08546       for (x = 0; x < NUM_SPANS; x++) {
08547          if (pris[x].trunkgroup == trunkgroup) {
08548             *span = x;
08549             return 0;
08550          }
08551       }
08552       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08553       *span = -1;
08554    } else {
08555       if (pris[*span].trunkgroup) {
08556          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08557          *span = -1;
08558       } else if (pris[*span].mastertrunkgroup) {
08559          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08560          *span = -1;
08561       } else {
08562          if (si->totalchans == 31) {
08563             /* E1 */
08564             pris[*span].dchannels[0] = 16 + offset;
08565          } else if (si->totalchans == 24) {
08566             /* T1 or J1 */
08567             pris[*span].dchannels[0] = 24 + offset;
08568          } else if (si->totalchans == 3) {
08569             /* BRI */
08570             pris[*span].dchannels[0] = 3 + offset;
08571          } else {
08572             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);
08573             *span = -1;
08574             return 0;
08575          }
08576          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08577          pris[*span].offset = offset;
08578          pris[*span].span = *span + 1;
08579       }
08580    }
08581    return 0;
08582 }

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

Definition at line 14234 of file chan_dahdi.c.

References ast_copy_string(), ast_jb_read_conf(), ast_log(), build_channels(), dahdi_chan_conf::chan, global_jbconf, HAVE_PRI, ast_variable::lineno, LOG_DEBUG, MAX_CHANLIST_LEN, ast_variable::name, ast_variable::next, dahdi_pvt::parkinglot, PROC_DAHDI_OPT_NOCHAN, and ast_variable::value.

Referenced by setup_dahdi().

14235 {
14236    struct dahdi_pvt *tmp;
14237    int y;
14238    int found_pseudo = 0;
14239    char dahdichan[MAX_CHANLIST_LEN] = {};
14240 
14241    for (; v; v = v->next) {
14242       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14243          continue;
14244 
14245       /* must have parkinglot in confp before build_channels is called */
14246       if (!strcasecmp(v->name, "parkinglot")) {
14247          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
14248       }
14249 
14250       /* Create the interface list */
14251       if (!strcasecmp(v->name, "channel")
14252 #ifdef HAVE_PRI
14253           || !strcasecmp(v->name, "crv")
14254 #endif         
14255          ) {
14256          int iscrv;
14257          if (options & PROC_DAHDI_OPT_NOCHAN) {
14258             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
14259             continue;
14260          }
14261          iscrv = !strcasecmp(v->name, "crv");
14262          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14263                return -1;
14264          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
14265       } else if (!strcasecmp(v->name, "buffers")) {
14266          int res;
14267          char policy[21] = "";
14268 
14269          res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
14270          if (res != 2) {
14271             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14272             confp->chan.buf_no = numbufs;
14273             continue;
14274          }
14275          if (confp->chan.buf_no < 0)
14276             confp->chan.buf_no = numbufs;
14277          if (!strcasecmp(policy, "full")) {
14278             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14279          } else if (!strcasecmp(policy, "immediate")) {
14280             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14281          } else {
14282             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14283          }
14284       } else if (!strcasecmp(v->name, "dahdichan")) {
14285          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14286       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14287          usedistinctiveringdetection = ast_true(v->value);
14288       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14289          distinctiveringaftercid = ast_true(v->value);
14290       } else if (!strcasecmp(v->name, "dring1context")) {
14291          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14292       } else if (!strcasecmp(v->name, "dring2context")) {
14293          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14294       } else if (!strcasecmp(v->name, "dring3context")) {
14295          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14296       } else if (!strcasecmp(v->name, "dring1range")) {
14297          confp->chan.drings.ringnum[0].range = atoi(v->value);
14298       } else if (!strcasecmp(v->name, "dring2range")) {
14299          confp->chan.drings.ringnum[1].range = atoi(v->value);
14300       } else if (!strcasecmp(v->name, "dring3range")) {
14301          confp->chan.drings.ringnum[2].range = atoi(v->value);
14302       } else if (!strcasecmp(v->name, "dring1")) {
14303          sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
14304       } else if (!strcasecmp(v->name, "dring2")) {
14305          sscanf(v->value,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
14306       } else if (!strcasecmp(v->name, "dring3")) {
14307          sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
14308       } else if (!strcasecmp(v->name, "usecallerid")) {
14309          confp->chan.use_callerid = ast_true(v->value);
14310       } else if (!strcasecmp(v->name, "cidsignalling")) {
14311          if (!strcasecmp(v->value, "bell"))
14312             confp->chan.cid_signalling = CID_SIG_BELL;
14313          else if (!strcasecmp(v->value, "v23"))
14314             confp->chan.cid_signalling = CID_SIG_V23;
14315          else if (!strcasecmp(v->value, "dtmf"))
14316             confp->chan.cid_signalling = CID_SIG_DTMF;
14317          else if (!strcasecmp(v->value, "smdi"))
14318             confp->chan.cid_signalling = CID_SIG_SMDI;
14319          else if (!strcasecmp(v->value, "v23_jp"))
14320             confp->chan.cid_signalling = CID_SIG_V23_JP;
14321          else if (ast_true(v->value))
14322             confp->chan.cid_signalling = CID_SIG_BELL;
14323       } else if (!strcasecmp(v->name, "cidstart")) {
14324          if (!strcasecmp(v->value, "ring"))
14325             confp->chan.cid_start = CID_START_RING;
14326          else if (!strcasecmp(v->value, "polarity_in"))
14327             confp->chan.cid_start = CID_START_POLARITY_IN;
14328          else if (!strcasecmp(v->value, "polarity"))
14329             confp->chan.cid_start = CID_START_POLARITY;
14330          else if (ast_true(v->value))
14331             confp->chan.cid_start = CID_START_RING;
14332       } else if (!strcasecmp(v->name, "threewaycalling")) {
14333          confp->chan.threewaycalling = ast_true(v->value);
14334       } else if (!strcasecmp(v->name, "cancallforward")) {
14335          confp->chan.cancallforward = ast_true(v->value);
14336       } else if (!strcasecmp(v->name, "relaxdtmf")) {
14337          if (ast_true(v->value)) 
14338             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14339          else
14340             confp->chan.dtmfrelax = 0;
14341       } else if (!strcasecmp(v->name, "mailbox")) {
14342          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14343       } else if (!strcasecmp(v->name, "hasvoicemail")) {
14344          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
14345             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
14346          }
14347       } else if (!strcasecmp(v->name, "adsi")) {
14348          confp->chan.adsi = ast_true(v->value);
14349       } else if (!strcasecmp(v->name, "usesmdi")) {
14350          confp->chan.use_smdi = ast_true(v->value);
14351       } else if (!strcasecmp(v->name, "smdiport")) {
14352          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14353       } else if (!strcasecmp(v->name, "transfer")) {
14354          confp->chan.transfer = ast_true(v->value);
14355       } else if (!strcasecmp(v->name, "canpark")) {
14356          confp->chan.canpark = ast_true(v->value);
14357       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14358          confp->chan.echocanbridged = ast_true(v->value);
14359       } else if (!strcasecmp(v->name, "busydetect")) {
14360          confp->chan.busydetect = ast_true(v->value);
14361       } else if (!strcasecmp(v->name, "busycount")) {
14362          confp->chan.busycount = atoi(v->value);
14363       } else if (!strcasecmp(v->name, "silencethreshold")) {
14364          confp->chan.silencethreshold = atoi(v->value);
14365       } else if (!strcasecmp(v->name, "busycompare")) {
14366          confp->chan.busycompare = ast_true(v->value);
14367       } else if (!strcasecmp(v->name, "busypattern")) {
14368          if (sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
14369             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14370          }
14371          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14372          if (count == 1)
14373             confp->chan.busyquietlength = 0;
14374          else if (count < 1)
14375             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
14376       } else if (!strcasecmp(v->name, "busyfuzziness")) {
14377          confp->chan.busyfuzziness = atoi(v->value);
14378       } else if (!strcasecmp(v->name, "callprogress")) {
14379          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14380          if (ast_true(v->value))
14381             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14382       } else if (!strcasecmp(v->name, "faxdetect")) {
14383          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14384          if (!strcasecmp(v->value, "incoming")) {
14385             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14386          } else if (!strcasecmp(v->value, "outgoing")) {
14387             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14388          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14389             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14390       } else if (!strcasecmp(v->name, "echocancel")) {
14391          process_echocancel(confp, v->value, v->lineno);
14392       } else if (!strcasecmp(v->name, "echotraining")) {
14393          if (sscanf(v->value, "%d", &y) == 1) {
14394             if ((y < 10) || (y > 4000)) {
14395                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);             
14396             } else {
14397                confp->chan.echotraining = y;
14398             }
14399          } else if (ast_true(v->value)) {
14400             confp->chan.echotraining = 400;
14401          } else
14402             confp->chan.echotraining = 0;
14403       } else if (!strcasecmp(v->name, "hidecallerid")) {
14404          confp->chan.hidecallerid = ast_true(v->value);
14405       } else if (!strcasecmp(v->name, "hidecalleridname")) {
14406          confp->chan.hidecalleridname = ast_true(v->value);
14407       } else if (!strcasecmp(v->name, "pulsedial")) {
14408          confp->chan.pulse = ast_true(v->value);
14409       } else if (!strcasecmp(v->name, "callreturn")) {
14410          confp->chan.callreturn = ast_true(v->value);
14411       } else if (!strcasecmp(v->name, "callwaiting")) {
14412          confp->chan.callwaiting = ast_true(v->value);
14413       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14414          confp->chan.callwaitingcallerid = ast_true(v->value);
14415       } else if (!strcasecmp(v->name, "context")) {
14416          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14417       } else if (!strcasecmp(v->name, "language")) {
14418          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14419       } else if (!strcasecmp(v->name, "progzone")) {
14420          ast_copy_string(progzone, v->value, sizeof(progzone));
14421       } else if (!strcasecmp(v->name, "mohinterpret") 
14422          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14423          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14424       } else if (!strcasecmp(v->name, "mohsuggest")) {
14425          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14426       } else if (!strcasecmp(v->name, "parkinglot")) {
14427          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
14428       } else if (!strcasecmp(v->name, "stripmsd")) {
14429          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14430          confp->chan.stripmsd = atoi(v->value);
14431       } else if (!strcasecmp(v->name, "jitterbuffers")) {
14432          numbufs = atoi(v->value);
14433       } else if (!strcasecmp(v->name, "group")) {
14434          confp->chan.group = ast_get_group(v->value);
14435       } else if (!strcasecmp(v->name, "callgroup")) {
14436          if (!strcasecmp(v->value, "none"))
14437             confp->chan.callgroup = 0;
14438          else
14439             confp->chan.callgroup = ast_get_group(v->value);
14440       } else if (!strcasecmp(v->name, "pickupgroup")) {
14441          if (!strcasecmp(v->value, "none"))
14442             confp->chan.pickupgroup = 0;
14443          else
14444             confp->chan.pickupgroup = ast_get_group(v->value);
14445       } else if (!strcasecmp(v->name, "setvar")) {
14446          char *varname = ast_strdupa(v->value), *varval = NULL;
14447          struct ast_variable *tmpvar;
14448          if (varname && (varval = strchr(varname, '='))) {
14449             *varval++ = '\0';
14450             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14451                tmpvar->next = confp->chan.vars;
14452                confp->chan.vars = tmpvar;
14453             }
14454          }
14455       } else if (!strcasecmp(v->name, "immediate")) {
14456          confp->chan.immediate = ast_true(v->value);
14457       } else if (!strcasecmp(v->name, "transfertobusy")) {
14458          confp->chan.transfertobusy = ast_true(v->value);
14459       } else if (!strcasecmp(v->name, "mwimonitor")) {
14460          confp->chan.mwimonitor_neon = 0;
14461          confp->chan.mwimonitor_fsk  = 0;
14462          confp->chan.mwimonitor_rpas = 0;
14463          if (strcasestr(v->value, "fsk")) {
14464             confp->chan.mwimonitor_fsk = 1;
14465          }
14466          if (strcasestr(v->value, "rpas")) {
14467             confp->chan.mwimonitor_rpas = 1;
14468          }
14469          if (strcasestr(v->value, "neon")) {
14470             confp->chan.mwimonitor_neon = 1;
14471          }
14472          /* If set to true or yes, assume that simple fsk is desired */
14473          if (ast_true(v->value)) {
14474             confp->chan.mwimonitor_fsk = 1;
14475          } 
14476       } else if (!strcasecmp(v->name, "cid_rxgain")) {
14477          if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
14478             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14479          }
14480       } else if (!strcasecmp(v->name, "rxgain")) {
14481          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
14482             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14483          }
14484       } else if (!strcasecmp(v->name, "txgain")) {
14485          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
14486             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14487          }
14488       } else if (!strcasecmp(v->name, "tonezone")) {
14489          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
14490             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14491          }
14492       } else if (!strcasecmp(v->name, "callerid")) {
14493          if (!strcasecmp(v->value, "asreceived")) {
14494             confp->chan.cid_num[0] = '\0';
14495             confp->chan.cid_name[0] = '\0';
14496          } else {
14497             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14498          } 
14499       } else if (!strcasecmp(v->name, "fullname")) {
14500          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14501       } else if (!strcasecmp(v->name, "cid_number")) {
14502          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14503       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14504          confp->chan.dahditrcallerid = ast_true(v->value);
14505       } else if (!strcasecmp(v->name, "restrictcid")) {
14506          confp->chan.restrictcid = ast_true(v->value);
14507       } else if (!strcasecmp(v->name, "usecallingpres")) {
14508          confp->chan.use_callingpres = ast_true(v->value);
14509       } else if (!strcasecmp(v->name, "accountcode")) {
14510          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14511       } else if (!strcasecmp(v->name, "amaflags")) {
14512          y = ast_cdr_amaflags2int(v->value);
14513          if (y < 0) 
14514             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14515          else
14516             confp->chan.amaflags = y;
14517       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14518          confp->chan.polarityonanswerdelay = atoi(v->value);
14519       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14520          confp->chan.answeronpolarityswitch = ast_true(v->value);
14521       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14522          confp->chan.hanguponpolarityswitch = ast_true(v->value);
14523       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14524          confp->chan.sendcalleridafter = atoi(v->value);
14525       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14526          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14527       } else if (!strcasecmp(v->name, "mwisendtype")) {
14528          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
14529             mwisend_rpas = 1;
14530          } else {
14531             mwisend_rpas = 0;
14532          }
14533       } else if (reload != 1) {
14534           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14535             int orig_radio = confp->chan.radio;
14536             int orig_outsigmod = confp->chan.outsigmod;
14537             int orig_auto = confp->is_sig_auto;
14538 
14539             confp->chan.radio = 0;
14540             confp->chan.outsigmod = -1;
14541             confp->is_sig_auto = 0;
14542             if (!strcasecmp(v->value, "em")) {
14543                confp->chan.sig = SIG_EM;
14544             } else if (!strcasecmp(v->value, "em_e1")) {
14545                confp->chan.sig = SIG_EM_E1;
14546             } else if (!strcasecmp(v->value, "em_w")) {
14547                confp->chan.sig = SIG_EMWINK;
14548             } else if (!strcasecmp(v->value, "fxs_ls")) {
14549                confp->chan.sig = SIG_FXSLS;
14550             } else if (!strcasecmp(v->value, "fxs_gs")) {
14551                confp->chan.sig = SIG_FXSGS;
14552             } else if (!strcasecmp(v->value, "fxs_ks")) {
14553                confp->chan.sig = SIG_FXSKS;
14554             } else if (!strcasecmp(v->value, "fxo_ls")) {
14555                confp->chan.sig = SIG_FXOLS;
14556             } else if (!strcasecmp(v->value, "fxo_gs")) {
14557                confp->chan.sig = SIG_FXOGS;
14558             } else if (!strcasecmp(v->value, "fxo_ks")) {
14559                confp->chan.sig = SIG_FXOKS;
14560             } else if (!strcasecmp(v->value, "fxs_rx")) {
14561                confp->chan.sig = SIG_FXSKS;
14562                confp->chan.radio = 1;
14563             } else if (!strcasecmp(v->value, "fxo_rx")) {
14564                confp->chan.sig = SIG_FXOLS;
14565                confp->chan.radio = 1;
14566             } else if (!strcasecmp(v->value, "fxs_tx")) {
14567                confp->chan.sig = SIG_FXSLS;
14568                confp->chan.radio = 1;
14569             } else if (!strcasecmp(v->value, "fxo_tx")) {
14570                confp->chan.sig = SIG_FXOGS;
14571                confp->chan.radio = 1;
14572             } else if (!strcasecmp(v->value, "em_rx")) {
14573                confp->chan.sig = SIG_EM;
14574                confp->chan.radio = 1;
14575             } else if (!strcasecmp(v->value, "em_tx")) {
14576                confp->chan.sig = SIG_EM;
14577                confp->chan.radio = 1;
14578             } else if (!strcasecmp(v->value, "em_rxtx")) {
14579                confp->chan.sig = SIG_EM;
14580                confp->chan.radio = 2;
14581             } else if (!strcasecmp(v->value, "em_txrx")) {
14582                confp->chan.sig = SIG_EM;
14583                confp->chan.radio = 2;
14584             } else if (!strcasecmp(v->value, "sf")) {
14585                confp->chan.sig = SIG_SF;
14586             } else if (!strcasecmp(v->value, "sf_w")) {
14587                confp->chan.sig = SIG_SFWINK;
14588             } else if (!strcasecmp(v->value, "sf_featd")) {
14589                confp->chan.sig = SIG_FEATD;
14590             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14591                confp->chan.sig = SIG_FEATDMF;
14592             } else if (!strcasecmp(v->value, "sf_featb")) {
14593                confp->chan.sig = SIG_SF_FEATB;
14594             } else if (!strcasecmp(v->value, "sf")) {
14595                confp->chan.sig = SIG_SF;
14596             } else if (!strcasecmp(v->value, "sf_rx")) {
14597                confp->chan.sig = SIG_SF;
14598                confp->chan.radio = 1;
14599             } else if (!strcasecmp(v->value, "sf_tx")) {
14600                confp->chan.sig = SIG_SF;
14601                confp->chan.radio = 1;
14602             } else if (!strcasecmp(v->value, "sf_rxtx")) {
14603                confp->chan.sig = SIG_SF;
14604                confp->chan.radio = 2;
14605             } else if (!strcasecmp(v->value, "sf_txrx")) {
14606                confp->chan.sig = SIG_SF;
14607                confp->chan.radio = 2;
14608             } else if (!strcasecmp(v->value, "featd")) {
14609                confp->chan.sig = SIG_FEATD;
14610             } else if (!strcasecmp(v->value, "featdmf")) {
14611                confp->chan.sig = SIG_FEATDMF;
14612             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14613                confp->chan.sig = SIG_FEATDMF_TA;
14614             } else if (!strcasecmp(v->value, "e911")) {
14615                confp->chan.sig = SIG_E911;
14616             } else if (!strcasecmp(v->value, "fgccama")) {
14617                confp->chan.sig = SIG_FGC_CAMA;
14618             } else if (!strcasecmp(v->value, "fgccamamf")) {
14619                confp->chan.sig = SIG_FGC_CAMAMF;
14620             } else if (!strcasecmp(v->value, "featb")) {
14621                confp->chan.sig = SIG_FEATB;
14622 #ifdef HAVE_PRI
14623             } else if (!strcasecmp(v->value, "pri_net")) {
14624                confp->chan.sig = SIG_PRI;
14625                confp->pri.nodetype = PRI_NETWORK;
14626             } else if (!strcasecmp(v->value, "pri_cpe")) {
14627                confp->chan.sig = SIG_PRI;
14628                confp->pri.nodetype = PRI_CPE;
14629             } else if (!strcasecmp(v->value, "bri_cpe")) {
14630                confp->chan.sig = SIG_BRI;
14631                confp->pri.nodetype = PRI_CPE;
14632             } else if (!strcasecmp(v->value, "bri_net")) {
14633                confp->chan.sig = SIG_BRI;
14634                confp->pri.nodetype = PRI_NETWORK;
14635             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14636                confp->chan.sig = SIG_BRI_PTMP;
14637                confp->pri.nodetype = PRI_CPE;
14638             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14639                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
14640             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14641                confp->chan.sig = SIG_GR303FXOKS;
14642                confp->pri.nodetype = PRI_NETWORK;
14643             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14644                confp->chan.sig = SIG_GR303FXSKS;
14645                confp->pri.nodetype = PRI_CPE;
14646 #endif
14647 #ifdef HAVE_SS7
14648             } else if (!strcasecmp(v->value, "ss7")) {
14649                confp->chan.sig = SIG_SS7;
14650 #endif
14651             } else if (!strcasecmp(v->value, "auto")) {
14652                confp->is_sig_auto = 1;
14653             } else {
14654                confp->chan.outsigmod = orig_outsigmod;
14655                confp->chan.radio = orig_radio;
14656                confp->is_sig_auto = orig_auto;
14657                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14658             }
14659           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14660             if (!strcasecmp(v->value, "em")) {
14661                confp->chan.outsigmod = SIG_EM;
14662             } else if (!strcasecmp(v->value, "em_e1")) {
14663                confp->chan.outsigmod = SIG_EM_E1;
14664             } else if (!strcasecmp(v->value, "em_w")) {
14665                confp->chan.outsigmod = SIG_EMWINK;
14666             } else if (!strcasecmp(v->value, "sf")) {
14667                confp->chan.outsigmod = SIG_SF;
14668             } else if (!strcasecmp(v->value, "sf_w")) {
14669                confp->chan.outsigmod = SIG_SFWINK;
14670             } else if (!strcasecmp(v->value, "sf_featd")) {
14671                confp->chan.outsigmod = SIG_FEATD;
14672             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14673                confp->chan.outsigmod = SIG_FEATDMF;
14674             } else if (!strcasecmp(v->value, "sf_featb")) {
14675                confp->chan.outsigmod = SIG_SF_FEATB;
14676             } else if (!strcasecmp(v->value, "sf")) {
14677                confp->chan.outsigmod = SIG_SF;
14678             } else if (!strcasecmp(v->value, "featd")) {
14679                confp->chan.outsigmod = SIG_FEATD;
14680             } else if (!strcasecmp(v->value, "featdmf")) {
14681                confp->chan.outsigmod = SIG_FEATDMF;
14682             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14683                confp->chan.outsigmod = SIG_FEATDMF_TA;
14684             } else if (!strcasecmp(v->value, "e911")) {
14685                confp->chan.outsigmod = SIG_E911;
14686             } else if (!strcasecmp(v->value, "fgccama")) {
14687                confp->chan.outsigmod = SIG_FGC_CAMA;
14688             } else if (!strcasecmp(v->value, "fgccamamf")) {
14689                confp->chan.outsigmod = SIG_FGC_CAMAMF;
14690             } else if (!strcasecmp(v->value, "featb")) {
14691                confp->chan.outsigmod = SIG_FEATB;
14692             } else {
14693                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14694             }
14695 #ifdef HAVE_PRI
14696          } else if (!strcasecmp(v->name, "pridialplan")) {
14697             if (!strcasecmp(v->value, "national")) {
14698                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14699             } else if (!strcasecmp(v->value, "unknown")) {
14700                confp->pri.dialplan = PRI_UNKNOWN + 1;
14701             } else if (!strcasecmp(v->value, "private")) {
14702                confp->pri.dialplan = PRI_PRIVATE + 1;
14703             } else if (!strcasecmp(v->value, "international")) {
14704                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14705             } else if (!strcasecmp(v->value, "local")) {
14706                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14707             } else if (!strcasecmp(v->value, "dynamic")) {
14708                confp->pri.dialplan = -1;
14709             } else if (!strcasecmp(v->value, "redundant")) {
14710                confp->pri.dialplan = -2;
14711             } else {
14712                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14713             }
14714          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14715             if (!strcasecmp(v->value, "national")) {
14716                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14717             } else if (!strcasecmp(v->value, "unknown")) {
14718                confp->pri.localdialplan = PRI_UNKNOWN + 1;
14719             } else if (!strcasecmp(v->value, "private")) {
14720                confp->pri.localdialplan = PRI_PRIVATE + 1;
14721             } else if (!strcasecmp(v->value, "international")) {
14722                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14723             } else if (!strcasecmp(v->value, "local")) {
14724                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14725             } else if (!strcasecmp(v->value, "dynamic")) {
14726                confp->pri.localdialplan = -1;
14727             } else if (!strcasecmp(v->value, "redundant")) {
14728                confp->pri.localdialplan = -2;
14729             } else {
14730                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14731             }
14732          } else if (!strcasecmp(v->name, "switchtype")) {
14733             if (!strcasecmp(v->value, "national")) 
14734                confp->pri.switchtype = PRI_SWITCH_NI2;
14735             else if (!strcasecmp(v->value, "ni1"))
14736                confp->pri.switchtype = PRI_SWITCH_NI1;
14737             else if (!strcasecmp(v->value, "dms100"))
14738                confp->pri.switchtype = PRI_SWITCH_DMS100;
14739             else if (!strcasecmp(v->value, "4ess"))
14740                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14741             else if (!strcasecmp(v->value, "5ess"))
14742                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14743             else if (!strcasecmp(v->value, "euroisdn"))
14744                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14745             else if (!strcasecmp(v->value, "qsig"))
14746                confp->pri.switchtype = PRI_SWITCH_QSIG;
14747             else {
14748                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14749                return -1;
14750             }
14751          } else if (!strcasecmp(v->name, "nsf")) {
14752             if (!strcasecmp(v->value, "sdn"))
14753                confp->pri.nsf = PRI_NSF_SDN;
14754             else if (!strcasecmp(v->value, "megacom"))
14755                confp->pri.nsf = PRI_NSF_MEGACOM;
14756             else if (!strcasecmp(v->value, "tollfreemegacom"))
14757                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
14758             else if (!strcasecmp(v->value, "accunet"))
14759                confp->pri.nsf = PRI_NSF_ACCUNET;
14760             else if (!strcasecmp(v->value, "none"))
14761                confp->pri.nsf = PRI_NSF_NONE;
14762             else {
14763                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14764                confp->pri.nsf = PRI_NSF_NONE;
14765             }
14766          } else if (!strcasecmp(v->name, "priindication")) {
14767             if (!strcasecmp(v->value, "outofband"))
14768                confp->chan.priindication_oob = 1;
14769             else if (!strcasecmp(v->value, "inband"))
14770                confp->chan.priindication_oob = 0;
14771             else
14772                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14773                   v->value, v->lineno);
14774          } else if (!strcasecmp(v->name, "priexclusive")) {
14775             confp->chan.priexclusive = ast_true(v->value);
14776          } else if (!strcasecmp(v->name, "internationalprefix")) {
14777             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14778          } else if (!strcasecmp(v->name, "nationalprefix")) {
14779             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14780          } else if (!strcasecmp(v->name, "localprefix")) {
14781             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14782          } else if (!strcasecmp(v->name, "privateprefix")) {
14783             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14784          } else if (!strcasecmp(v->name, "unknownprefix")) {
14785             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14786          } else if (!strcasecmp(v->name, "resetinterval")) {
14787             if (!strcasecmp(v->value, "never"))
14788                confp->pri.resetinterval = -1;
14789             else if (atoi(v->value) >= 60)
14790                confp->pri.resetinterval = atoi(v->value);
14791             else
14792                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14793                   v->value, v->lineno);
14794          } else if (!strcasecmp(v->name, "minunused")) {
14795             confp->pri.minunused = atoi(v->value);
14796          } else if (!strcasecmp(v->name, "minidle")) {
14797             confp->pri.minidle = atoi(v->value); 
14798          } else if (!strcasecmp(v->name, "idleext")) {
14799             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14800          } else if (!strcasecmp(v->name, "idledial")) {
14801             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14802          } else if (!strcasecmp(v->name, "overlapdial")) {
14803             if (ast_true(v->value)) {
14804                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14805             } else if (!strcasecmp(v->value, "incoming")) {
14806                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14807             } else if (!strcasecmp(v->value, "outgoing")) {
14808                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14809             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14810                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14811             } else {
14812                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14813             }
14814 #ifdef HAVE_PRI_INBANDDISCONNECT
14815          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14816             confp->pri.inbanddisconnect = ast_true(v->value);
14817 #endif
14818          } else if (!strcasecmp(v->name, "pritimer")) {
14819 #ifdef PRI_GETSET_TIMERS
14820             char tmp[20], *timerc, *c = tmp;
14821             int timer, timeridx;
14822             ast_copy_string(tmp, v->value, sizeof(tmp));
14823             timerc = strsep(&c, ",");
14824             if (timerc) {
14825                timer = atoi(c);
14826                if (!timer)
14827                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno);
14828                else {
14829                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
14830                      pritimers[timeridx] = timer;
14831                   else
14832                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno);
14833                }
14834             } else
14835                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno);
14836 
14837          } else if (!strcasecmp(v->name, "facilityenable")) {
14838             confp->pri.facilityenable = ast_true(v->value);
14839 #endif /* PRI_GETSET_TIMERS */
14840 #endif /* HAVE_PRI */
14841 #ifdef HAVE_SS7
14842          } else if (!strcasecmp(v->name, "ss7type")) {
14843             if (!strcasecmp(v->value, "itu")) {
14844                cur_ss7type = SS7_ITU;
14845             } else if (!strcasecmp(v->value, "ansi")) {
14846                cur_ss7type = SS7_ANSI;
14847             } else
14848                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14849          } else if (!strcasecmp(v->name, "linkset")) {
14850             cur_linkset = atoi(v->value);
14851          } else if (!strcasecmp(v->name, "pointcode")) {
14852             cur_pointcode = parse_pointcode(v->value);
14853          } else if (!strcasecmp(v->name, "adjpointcode")) {
14854             cur_adjpointcode = parse_pointcode(v->value);
14855          } else if (!strcasecmp(v->name, "defaultdpc")) {
14856             cur_defaultdpc = parse_pointcode(v->value);
14857          } else if (!strcasecmp(v->name, "cicbeginswith")) {
14858             cur_cicbeginswith = atoi(v->value);
14859          } else if (!strcasecmp(v->name, "networkindicator")) {
14860             if (!strcasecmp(v->value, "national"))
14861                cur_networkindicator = SS7_NI_NAT;
14862             else if (!strcasecmp(v->value, "national_spare"))
14863                cur_networkindicator = SS7_NI_NAT_SPARE;
14864             else if (!strcasecmp(v->value, "international"))
14865                cur_networkindicator = SS7_NI_INT;
14866             else if (!strcasecmp(v->value, "international_spare"))
14867                cur_networkindicator = SS7_NI_INT_SPARE;
14868             else
14869                cur_networkindicator = -1;
14870          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14871             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14872          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14873             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14874          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14875             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14876          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14877             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14878          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14879             if (!strcasecmp(v->value, "national")) {
14880                confp->ss7.called_nai = SS7_NAI_NATIONAL;
14881             } else if (!strcasecmp(v->value, "international")) {
14882                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14883             } else if (!strcasecmp(v->value, "subscriber")) {
14884                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14885             } else if (!strcasecmp(v->value, "dynamic")) {
14886                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14887             } else {
14888                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14889             }
14890          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14891             if (!strcasecmp(v->value, "national")) {
14892                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14893             } else if (!strcasecmp(v->value, "international")) {
14894                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14895             } else if (!strcasecmp(v->value, "subscriber")) {
14896                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14897             } else if (!strcasecmp(v->value, "dynamic")) {
14898                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14899             } else {
14900                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14901             }
14902          } else if (!strcasecmp(v->name, "sigchan")) {
14903             int sigchan, res;
14904             sigchan = atoi(v->value);
14905             res = linkset_addsigchan(sigchan);
14906             if (res < 0)
14907                return -1;
14908 
14909          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14910             struct dahdi_ss7 *link;
14911             link = ss7_resolve_linkset(cur_linkset);
14912             if (!link) {
14913                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
14914                return -1;
14915             }
14916             if (ast_true(v->value))
14917                link->flags |= LINKSET_FLAG_EXPLICITACM;
14918 
14919 #endif /* HAVE_SS7 */
14920          } else if (!strcasecmp(v->name, "cadence")) {
14921             /* setup to scan our argument */
14922             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14923             int i;
14924             struct dahdi_ring_cadence new_cadence;
14925             int cid_location = -1;
14926             int firstcadencepos = 0;
14927             char original_args[80];
14928             int cadence_is_ok = 1;
14929 
14930             ast_copy_string(original_args, v->value, sizeof(original_args));
14931             /* 16 cadences allowed (8 pairs) */
14932             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]);
14933    
14934             /* Cadence must be even (on/off) */
14935             if (element_count % 2 == 1) {
14936                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14937                cadence_is_ok = 0;
14938             }
14939    
14940             /* Ring cadences cannot be negative */
14941             for (i = 0; i < element_count; i++) {
14942                if (c[i] == 0) {
14943                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14944                   cadence_is_ok = 0;
14945                   break;
14946                } else if (c[i] < 0) {
14947                   if (i % 2 == 1) {
14948                      /* Silence duration, negative possibly okay */
14949                      if (cid_location == -1) {
14950                         cid_location = i;
14951                         c[i] *= -1;
14952                      } else {
14953                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14954                         cadence_is_ok = 0;
14955                         break;
14956                      }
14957                   } else {
14958                      if (firstcadencepos == 0) {
14959                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
14960                                  /* duration will be passed negative to the DAHDI driver */
14961                      } else {
14962                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14963                         cadence_is_ok = 0;
14964                         break;
14965                      }
14966                   }
14967                }
14968             }
14969    
14970             /* Substitute our scanned cadence */
14971             for (i = 0; i < 16; i++) {
14972                new_cadence.ringcadence[i] = c[i];
14973             }
14974    
14975             if (cadence_is_ok) {
14976                /* ---we scanned it without getting annoyed; now some sanity checks--- */
14977                if (element_count < 2) {
14978                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14979                } else {
14980                   if (cid_location == -1) {
14981                      /* user didn't say; default to first pause */
14982                      cid_location = 1;
14983                   } else {
14984                      /* convert element_index to cidrings value */
14985                      cid_location = (cid_location + 1) / 2;
14986                   }
14987                   /* ---we like their cadence; try to install it--- */
14988                   if (!user_has_defined_cadences++)
14989                      /* this is the first user-defined cadence; clear the default user cadences */
14990                      num_cadence = 0;
14991                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
14992                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
14993                   else {
14994                      cadences[num_cadence] = new_cadence;
14995                      cidrings[num_cadence++] = cid_location;
14996                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
14997                   }
14998                }
14999             }
15000          } else if (!strcasecmp(v->name, "ringtimeout")) {
15001             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
15002          } else if (!strcasecmp(v->name, "prewink")) {
15003             confp->timing.prewinktime = atoi(v->value);
15004          } else if (!strcasecmp(v->name, "preflash")) {
15005             confp->timing.preflashtime = atoi(v->value);
15006          } else if (!strcasecmp(v->name, "wink")) {
15007             confp->timing.winktime = atoi(v->value);
15008          } else if (!strcasecmp(v->name, "flash")) {
15009             confp->timing.flashtime = atoi(v->value);
15010          } else if (!strcasecmp(v->name, "start")) {
15011             confp->timing.starttime = atoi(v->value);
15012          } else if (!strcasecmp(v->name, "rxwink")) {
15013             confp->timing.rxwinktime = atoi(v->value);
15014          } else if (!strcasecmp(v->name, "rxflash")) {
15015             confp->timing.rxflashtime = atoi(v->value);
15016          } else if (!strcasecmp(v->name, "debounce")) {
15017             confp->timing.debouncetime = atoi(v->value);
15018          } else if (!strcasecmp(v->name, "toneduration")) {
15019             int toneduration;
15020             int ctlfd;
15021             int res;
15022             struct dahdi_dialparams dps;
15023 
15024             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
15025             if (ctlfd == -1) {
15026                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
15027                return -1;
15028             }
15029 
15030             toneduration = atoi(v->value);
15031             if (toneduration > -1) {
15032                memset(&dps, 0, sizeof(dps));
15033 
15034                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
15035                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
15036                if (res < 0) {
15037                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
15038                   return -1;
15039                }
15040             }
15041             close(ctlfd);
15042          } else if (!strcasecmp(v->name, "defaultcic")) {
15043             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
15044          } else if (!strcasecmp(v->name, "defaultozz")) {
15045             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
15046          } else if (!strcasecmp(v->name, "mwilevel")) {
15047             mwilevel = atoi(v->value);
15048          }
15049       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
15050          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
15051    }
15052    if (dahdichan[0]) { 
15053       /* The user has set 'dahdichan' */
15054       /*< \todo pass proper line number instead of 0 */
15055       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
15056          return -1;
15057       }
15058    }
15059    /*< \todo why check for the pseudo in the per-channel section.
15060     * Any actual use for manual setup of the pseudo channel? */
15061    if (!found_pseudo && reload == 0) {
15062       /* use the default configuration for a channel, so
15063          that any settings from real configured channels
15064          don't "leak" into the pseudo channel config
15065       */
15066       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
15067 
15068       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
15069 
15070       if (tmp) {
15071          ast_verb(3, "Automatically generated pseudo channel\n");
15072       } else {
15073          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
15074       }
15075    }
15076    return 0;
15077 }

static void process_echocancel ( struct dahdi_chan_conf confp,
const char *  data,
unsigned int  line 
) [static]

Definition at line 14178 of file chan_dahdi.c.

References ARRAY_LEN, ast_app_separate_args(), ast_log(), ast_strdupa, ast_strlen_zero(), ast_true(), dahdi_chan_conf::chan, dahdi_pvt::echocancel, dahdi_pvt::head, name, dahdi_pvt::params, and parse().

14179 {
14180    char *parse = ast_strdupa(data);
14181    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14182    unsigned int param_count;
14183    unsigned int x;
14184 
14185    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14186       return;
14187 
14188    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14189 
14190    /* first parameter is tap length, process it here */
14191 
14192    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14193    
14194    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14195       confp->chan.echocancel.head.tap_length = x;
14196    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14197       confp->chan.echocancel.head.tap_length = 128;
14198 
14199    /* now process any remaining parameters */
14200 
14201    for (x = 1; x < param_count; x++) {
14202       struct {
14203          char *name;
14204          char *value;
14205       } param;
14206 
14207       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
14208          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14209          continue;
14210       }
14211 
14212       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14213          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14214          continue;
14215       }
14216 
14217       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14218 
14219       if (param.value) {
14220          if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14221             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14222             continue;
14223          }
14224       }
14225       confp->chan.echocancel.head.param_count++;
14226    }
14227 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 10807 of file chan_dahdi.c.

Referenced by __oh323_new().

10808 {
10809    switch (redirectingreason) {
10810    case 0:
10811       return "UNKNOWN";
10812    case 1:
10813       return "BUSY";
10814    case 2:
10815       return "NO_REPLY";
10816    case 0xF:
10817       return "UNCONDITIONAL";
10818    default:
10819       return "NOREDIRECT";
10820    }
10821 }

static int reload ( void   )  [static]

Definition at line 15447 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

15448 {
15449    int res = 0;
15450 
15451    res = setup_dahdi(1);
15452    if (res) {
15453       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15454       return -1;
15455    }
15456    return 0;
15457 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

01955 {
01956    p->confno = -1;
01957    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01958    if (p->subs[SUB_REAL].dfd > -1) {
01959       struct dahdi_confinfo zi;
01960 
01961       memset(&zi, 0, sizeof(zi));
01962       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01963          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01964    }
01965    return 0;
01966 }

static int restart_monitor ( void   )  [static]

Definition at line 8511 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(), skinny_request(), unistim_reload(), and unistim_request().

08512 {
08513    /* If we're supposed to be stopped -- stay stopped */
08514    if (monitor_thread == AST_PTHREADT_STOP)
08515       return 0;
08516    ast_mutex_lock(&monlock);
08517    if (monitor_thread == pthread_self()) {
08518       ast_mutex_unlock(&monlock);
08519       ast_log(LOG_WARNING, "Cannot kill myself\n");
08520       return -1;
08521    }
08522    if (monitor_thread != AST_PTHREADT_NULL) {
08523       /* Wake up the thread */
08524       pthread_kill(monitor_thread, SIGURG);
08525    } else {
08526       /* Start a new monitor */
08527       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08528          ast_mutex_unlock(&monlock);
08529          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08530          return -1;
08531       }
08532    }
08533    ast_mutex_unlock(&monlock);
08534    return 0;
08535 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2333 of file chan_dahdi.c.

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

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

02334 {
02335    int res;
02336    if (p->saveconf.confmode) {
02337       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02338       p->saveconf.confmode = 0;
02339       if (res) {
02340          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02341          return -1;
02342       }
02343    }
02344    ast_debug(1, "Restored conferencing\n");
02345    return 0;
02346 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 2214 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(), mwi_thread(), and ss_thread().

02215 {
02216    int res;
02217 
02218    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02219    if (res) {
02220       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02221       return -1;
02222    }
02223 
02224    return 0;
02225 }

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2260 of file chan_dahdi.c.

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

Referenced by dahdi_callwait(), and dahdi_handle_event().

02261 {
02262    struct dahdi_confinfo c;
02263    int res;
02264    if (p->saveconf.confmode) {
02265       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02266       return -1;
02267    }
02268    p->saveconf.chan = 0;
02269    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02270    if (res) {
02271       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02272       p->saveconf.confmode = 0;
02273       return -1;
02274    }
02275    memset(&c, 0, sizeof(c));
02276    c.confmode = DAHDI_CONF_NORMAL;
02277    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02278    if (res) {
02279       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02280       return -1;
02281    }
02282    ast_debug(1, "Disabled conferencing\n");
02283    return 0;
02284 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 2390 of file chan_dahdi.c.

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

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

02391 {
02392    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02393    int res;
02394    /* Take out of linear mode if necessary */
02395    if (p->subs[SUB_REAL].linear) {
02396       p->subs[SUB_REAL].linear = 0;
02397       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02398    }
02399    while (p->cidpos < p->cidlen) {
02400       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02401       if (res < 0) {
02402          if (errno == EAGAIN)
02403             return 0;
02404          else {
02405             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02406             return -1;
02407          }
02408       }
02409       if (!res)
02410          return 0;
02411       p->cidpos += res;
02412    }
02413    ast_free(p->cidspill);
02414    p->cidspill = NULL;
02415    if (p->callwaitcas) {
02416       /* Wait for CID/CW to expire */
02417       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02418    } else
02419       restore_conference(p);
02420    return 0;
02421 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

Definition at line 2350 of file chan_dahdi.c.

References ast_callerid_callwaiting_generate(), AST_LAW, ast_malloc, ast_verb, 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, READ_SIZE, and send_callerid().

Referenced by dahdi_handle_dtmfup().

02351 {
02352    p->callwaitcas = 0;
02353    p->cidcwexpire = 0;
02354    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02355       return -1;
02356    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02357    /* Make sure we account for the end */
02358    p->cidlen += READ_SIZE * 4;
02359    p->cidpos = 0;
02360    send_callerid(p);
02361    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02362    return 0;
02363 }

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

Definition at line 2195 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

02196 {
02197    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02198 }

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

Definition at line 2177 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().

02178 {
02179    struct dahdi_gains g;
02180    int res;
02181 
02182    memset(&g, 0, sizeof(g));
02183    g.chan = chan;
02184    res = ioctl(fd, DAHDI_GETGAINS, &g);
02185    if (res) {
02186       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02187       return res;
02188    }
02189 
02190    fill_rxgain(&g, gain, law);
02191 
02192    return ioctl(fd, DAHDI_SETGAINS, &g);
02193 }

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

Definition at line 2159 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

Referenced by dahdi_set_swgain(), dahdi_setoption(), and set_actual_gain().

02160 {
02161    struct dahdi_gains g;
02162    int res;
02163 
02164    memset(&g, 0, sizeof(g));
02165    g.chan = chan;
02166    res = ioctl(fd, DAHDI_GETGAINS, &g);
02167    if (res) {
02168       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02169       return res;
02170    }
02171 
02172    fill_txgain(&g, gain, law);
02173 
02174    return ioctl(fd, DAHDI_SETGAINS, &g);
02175 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 15079 of file chan_dahdi.c.

References ast_category_browse(), ast_clear_flag, ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, dahdi_chan_conf_default(), default_jbconf, global_jbconf, iflock, ast_variable::lineno, LOG_ERROR, ast_variable::name, ast_variable::next, NUM_SPANS, pri_create_spanmap(), pri_create_trunkgroup(), pris, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), pvts, restart_monitor(), start_pri(), and ast_variable::value.

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

15080 {
15081    struct ast_config *cfg, *ucfg;
15082    struct ast_variable *v;
15083    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
15084    struct dahdi_chan_conf conf;
15085    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
15086    const char *cat;
15087    int res;
15088 
15089 #ifdef HAVE_PRI
15090    char *c;
15091    int spanno;
15092    int i;
15093    int logicalspan;
15094    int trunkgroup;
15095    int dchannels[NUM_DCHANS];
15096 #endif
15097 
15098    cfg = ast_config_load(config, config_flags);
15099 
15100    /* Error if we have no config file */
15101    if (!cfg) {
15102       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
15103       return 0;
15104    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
15105       ucfg = ast_config_load("users.conf", config_flags);
15106       if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
15107          return 0;
15108       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15109       cfg = ast_config_load(config, config_flags);
15110    } else {
15111       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
15112       ucfg = ast_config_load("users.conf", config_flags);
15113    }
15114 
15115    /* It's a little silly to lock it, but we mind as well just to be sure */
15116    ast_mutex_lock(&iflock);
15117 #ifdef HAVE_PRI
15118    if (reload != 1) {
15119       /* Process trunkgroups first */
15120       v = ast_variable_browse(cfg, "trunkgroups");
15121       while (v) {
15122          if (!strcasecmp(v->name, "trunkgroup")) {
15123             trunkgroup = atoi(v->value);
15124             if (trunkgroup > 0) {
15125                if ((c = strchr(v->value, ','))) {
15126                   i = 0;
15127                   memset(dchannels, 0, sizeof(dchannels));
15128                   while (c && (i < NUM_DCHANS)) {
15129                      dchannels[i] = atoi(c + 1);
15130                      if (dchannels[i] < 0) {
15131                         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);
15132                      } else
15133                         i++;
15134                      c = strchr(c + 1, ',');
15135                   }
15136                   if (i) {
15137                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
15138                         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);
15139                   } else
15140                         ast_verb(2, "Created trunk group %d with Primary D-channel %d and %d backup%s\n", trunkgroup, dchannels[0], i - 1, (i == 1) ? "" : "s");
15141                   } else
15142                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15143                } else
15144                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
15145             } else
15146                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
15147          } else if (!strcasecmp(v->name, "spanmap")) {
15148             spanno = atoi(v->value);
15149             if (spanno > 0) {
15150                if ((c = strchr(v->value, ','))) {
15151                   trunkgroup = atoi(c + 1);
15152                   if (trunkgroup > 0) {
15153                      if ((c = strchr(c + 1, ','))) 
15154                         logicalspan = atoi(c + 1);
15155                      else
15156                         logicalspan = 0;
15157                      if (logicalspan >= 0) {
15158                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
15159                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15160                      } else
15161                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
15162                      } else
15163                         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);
15164                   } else
15165                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
15166                } else
15167                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
15168             } else
15169                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
15170          } else {
15171             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
15172          }
15173          v = v->next;
15174       }
15175    }
15176 #endif
15177    
15178    /* Copy the default jb config over global_jbconf */
15179    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
15180 
15181    mwimonitornotify[0] = '\0';
15182 
15183    v = ast_variable_browse(cfg, "channels");
15184    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
15185       ast_mutex_unlock(&iflock);
15186       ast_config_destroy(cfg);
15187       if (ucfg) {
15188          ast_config_destroy(ucfg);
15189       }
15190       return res;
15191    }
15192 
15193    /* Now get configuration from all normal sections in chan_dahdi.conf: */
15194    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
15195       /* [channels] and [trunkgroups] are used. Let's also reserve
15196        * [globals] and [general] for future use
15197        */
15198       if (!strcasecmp(cat, "general") || 
15199           !strcasecmp(cat, "trunkgroups") ||
15200           !strcasecmp(cat, "globals") ||
15201           !strcasecmp(cat, "channels")) {
15202          continue;
15203       }
15204 
15205       memcpy(&conf, &base_conf, sizeof(conf));
15206 
15207       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
15208          ast_mutex_unlock(&iflock);
15209          ast_config_destroy(cfg);
15210          if (ucfg) {
15211             ast_config_destroy(cfg);
15212          }
15213          return res;
15214       }
15215    }
15216 
15217    ast_config_destroy(cfg);
15218 
15219    if (ucfg) {
15220       const char *chans;
15221 
15222       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
15223 
15224       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
15225          if (!strcasecmp(cat, "general")) {
15226             continue;
15227          }
15228 
15229          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
15230 
15231          if (ast_strlen_zero(chans)) {
15232             continue;
15233          }
15234 
15235          memcpy(&conf, &base_conf, sizeof(conf));
15236 
15237          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
15238             ast_config_destroy(ucfg);
15239             ast_mutex_unlock(&iflock);
15240             return res;
15241          }
15242       }
15243       ast_config_destroy(ucfg);
15244    }
15245    ast_mutex_unlock(&iflock);
15246 
15247 #ifdef HAVE_PRI
15248    if (reload != 1) {
15249       int x;
15250       for (x = 0; x < NUM_SPANS; x++) {
15251          if (pris[x].pvts[0]) {
15252             if (start_pri(pris + x)) {
15253                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
15254                return -1;
15255             } else
15256                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
15257          }
15258       }
15259    }
15260 #endif
15261 #ifdef HAVE_SS7
15262    if (reload != 1) {
15263       int x;
15264       for (x = 0; x < NUM_SPANS; x++) {
15265          if (linksets[x].ss7) {
15266             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
15267                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
15268                return -1;
15269             } else
15270                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
15271          }
15272       }
15273    }
15274 #endif
15275    /* And start the monitor for the first time */
15276    restart_monitor();
15277    return 0;
15278 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 8690 of file chan_dahdi.c.

Referenced by mkintf().

08691 {
08692         return sigtype;
08693 }

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

Definition at line 6530 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_free, 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_verb, ast_waitfor(), ast_waitfordigit(), ast_waitstream(), buf, 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, 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, CID_START_POLARITY_IN, dahdi_pvt::context, ast_channel::context, ringContextData::contextData, dahdi_dnd(), dahdi_enable_ec(), dahdi_get_event(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_tech, dahdi_wait_event(), dahdi_wink(), dahdi_pvt::defcontext, dahdi_subchannel::dfd, dahdi_pvt::dop, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_DIGITMODE_MF, dahdi_pvt::dtmfrelax, errno, event2str(), ast_channel::exten, dahdi_pvt::exten, exten, f, 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_NOTICE, my_getsigstr(), ast_channel::name, name, NEED_MFDETECT, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, 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, strsep(), 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, and dahdi_pvt::usedistinctiveringdetection.

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

06531 {
06532    struct ast_channel *chan = data;
06533    struct dahdi_pvt *p = chan->tech_pvt;
06534    char exten[AST_MAX_EXTENSION] = "";
06535    char exten2[AST_MAX_EXTENSION] = "";
06536    unsigned char buf[256];
06537    char dtmfcid[300];
06538    char dtmfbuf[300];
06539    struct callerid_state *cs = NULL;
06540    char *name = NULL, *number = NULL;
06541    int distMatches;
06542    int curRingData[3];
06543    int receivedRingT;
06544    int counter1;
06545    int counter;
06546    int samples = 0;
06547    struct ast_smdi_md_message *smdi_msg = NULL;
06548    int flags;
06549    int i;
06550    int timeout;
06551    int getforward = 0;
06552    char *s1, *s2;
06553    int len = 0;
06554    int res;
06555    int idx;
06556 
06557    ast_mutex_lock(&ss_thread_lock);
06558    ss_thread_count++;
06559    ast_mutex_unlock(&ss_thread_lock);
06560    /* in the bizarre case where the channel has become a zombie before we
06561       even get started here, abort safely
06562    */
06563    if (!p) {
06564       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
06565       ast_hangup(chan);
06566       goto quit;
06567    }
06568    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
06569    idx = dahdi_get_index(chan, p, 1);
06570    if (idx < 0) {
06571       ast_log(LOG_WARNING, "Huh?\n");
06572       ast_hangup(chan);
06573       goto quit;
06574    }
06575    if (p->dsp)
06576       ast_dsp_digitreset(p->dsp);
06577    switch (p->sig) {
06578 #ifdef HAVE_PRI
06579    case SIG_PRI:
06580    case SIG_BRI:
06581    case SIG_BRI_PTMP:
06582       /* Now loop looking for an extension */
06583       ast_copy_string(exten, p->exten, sizeof(exten));
06584       len = strlen(exten);
06585       res = 0;
06586       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06587          if (len && !ast_ignore_pattern(chan->context, exten))
06588             tone_zone_play_tone(p->subs[idx].dfd, -1);
06589          else
06590             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06591          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
06592             timeout = matchdigittimeout;
06593          else
06594             timeout = gendigittimeout;
06595          res = ast_waitfordigit(chan, timeout);
06596          if (res < 0) {
06597             ast_debug(1, "waitfordigit returned < 0...\n");
06598             ast_hangup(chan);
06599             goto quit;
06600          } else if (res) {
06601             exten[len++] = res;
06602             exten[len] = '\0';
06603          } else
06604             break;
06605       }
06606       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
06607       if (ast_strlen_zero(exten)) {
06608          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
06609          exten[0] = 's';
06610          exten[1] = '\0';
06611       }
06612       tone_zone_play_tone(p->subs[idx].dfd, -1);
06613       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
06614          /* Start the real PBX */
06615          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06616          if (p->dsp) ast_dsp_digitreset(p->dsp);
06617          dahdi_enable_ec(p);
06618          ast_setstate(chan, AST_STATE_RING);
06619          res = ast_pbx_run(chan);
06620          if (res) {
06621             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
06622          }
06623       } else {
06624          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
06625          chan->hangupcause = AST_CAUSE_UNALLOCATED;
06626          ast_hangup(chan);
06627          p->exten[0] = '\0';
06628          /* Since we send release complete here, we won't get one */
06629          p->call = NULL;
06630       }
06631       goto quit;
06632       break;
06633 #endif
06634    case SIG_FEATD:
06635    case SIG_FEATDMF:
06636    case SIG_FEATDMF_TA:
06637    case SIG_E911:
06638    case SIG_FGC_CAMAMF:
06639    case SIG_FEATB:
06640    case SIG_EMWINK:
06641    case SIG_SF_FEATD:
06642    case SIG_SF_FEATDMF:
06643    case SIG_SF_FEATB:
06644    case SIG_SFWINK:
06645       if (dahdi_wink(p, idx)) 
06646          goto quit;
06647       /* Fall through */
06648    case SIG_EM:
06649    case SIG_EM_E1:
06650    case SIG_SF:
06651    case SIG_FGC_CAMA:
06652       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06653       if (p->dsp)
06654          ast_dsp_digitreset(p->dsp);
06655       /* set digit mode appropriately */
06656       if (p->dsp) {
06657          if (NEED_MFDETECT(p))
06658             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax); 
06659          else 
06660             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06661       }
06662       memset(dtmfbuf, 0, sizeof(dtmfbuf));
06663       /* Wait for the first digit only if immediate=no */
06664       if (!p->immediate)
06665          /* Wait for the first digit (up to 5 seconds). */
06666          res = ast_waitfordigit(chan, 5000);
06667       else
06668          res = 0;
06669       if (res > 0) {
06670          /* save first char */
06671          dtmfbuf[0] = res;
06672          switch (p->sig) {
06673          case SIG_FEATD:
06674          case SIG_SF_FEATD:
06675             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06676             if (res > 0)
06677                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06678             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06679             break;
06680          case SIG_FEATDMF_TA:
06681             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06682             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06683             if (dahdi_wink(p, idx)) goto quit;
06684             dtmfbuf[0] = 0;
06685             /* Wait for the first digit (up to 5 seconds). */
06686             res = ast_waitfordigit(chan, 5000);
06687             if (res <= 0) break;
06688             dtmfbuf[0] = res;
06689             /* fall through intentionally */
06690          case SIG_FEATDMF:
06691          case SIG_E911:
06692          case SIG_FGC_CAMAMF:
06693          case SIG_SF_FEATDMF:
06694             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06695             /* if international caca, do it again to get real ANO */
06696             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
06697             {
06698                if (dahdi_wink(p, idx)) goto quit;
06699                dtmfbuf[0] = 0;
06700                /* Wait for the first digit (up to 5 seconds). */
06701                res = ast_waitfordigit(chan, 5000);
06702                if (res <= 0) break;
06703                dtmfbuf[0] = res;
06704                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06705             }
06706             if (res > 0) {
06707                /* if E911, take off hook */
06708                if (p->sig == SIG_E911)
06709                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06710                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
06711             }
06712             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06713             break;
06714          case SIG_FEATB:
06715          case SIG_SF_FEATB:
06716             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
06717             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06718             break;
06719          case SIG_EMWINK:
06720             /* if we received a '*', we are actually receiving Feature Group D
06721                dial syntax, so use that mode; otherwise, fall through to normal
06722                mode
06723             */
06724             if (res == '*') {
06725                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
06726                if (res > 0)
06727                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
06728                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
06729                break;
06730             }
06731          default:
06732             /* If we got the first digit, get the rest */
06733             len = 1;
06734             dtmfbuf[len] = '\0';
06735             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06736                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
06737                   timeout = matchdigittimeout;
06738                } else {
06739                   timeout = gendigittimeout;
06740                }
06741                res = ast_waitfordigit(chan, timeout);
06742                if (res < 0) {
06743                   ast_debug(1, "waitfordigit returned < 0...\n");
06744                   ast_hangup(chan);
06745                   goto quit;
06746                } else if (res) {
06747                   dtmfbuf[len++] = res;
06748                   dtmfbuf[len] = '\0';
06749                } else {
06750                   break;
06751                }
06752             }
06753             break;
06754          }
06755       }
06756       if (res == -1) {
06757          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
06758          ast_hangup(chan);
06759          goto quit;
06760       } else if (res < 0) {
06761          ast_debug(1, "Got hung up before digits finished\n");
06762          ast_hangup(chan);
06763          goto quit;
06764       }
06765 
06766       if (p->sig == SIG_FGC_CAMA) {
06767          char anibuf[100];
06768 
06769          if (ast_safe_sleep(chan,1000) == -1) {
06770                            ast_hangup(chan);
06771                            goto quit;
06772          }
06773                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06774                         ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
06775                         res = my_getsigstr(chan, anibuf, "#", 10000);
06776                         if ((res > 0) && (strlen(anibuf) > 2)) {
06777             if (anibuf[strlen(anibuf) - 1] == '#')
06778                anibuf[strlen(anibuf) - 1] = 0;
06779             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
06780          }
06781                         ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
06782       }
06783 
06784       ast_copy_string(exten, dtmfbuf, sizeof(exten));
06785       if (ast_strlen_zero(exten))
06786          ast_copy_string(exten, "s", sizeof(exten));
06787       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
06788          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
06789          if (exten[0] == '*') {
06790             char *stringp=NULL;
06791             ast_copy_string(exten2, exten, sizeof(exten2));
06792             /* Parse out extension and callerid */
06793             stringp=exten2 +1;
06794             s1 = strsep(&stringp, "*");
06795             s2 = strsep(&stringp, "*");
06796             if (s2) {
06797                if (!ast_strlen_zero(p->cid_num))
06798                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06799                else
06800                   ast_set_callerid(chan, s1, NULL, s1);
06801                ast_copy_string(exten, s2, sizeof(exten));
06802             } else
06803                ast_copy_string(exten, s1, sizeof(exten));
06804          } else if (p->sig == SIG_FEATD)
06805             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06806       }
06807       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06808          if (exten[0] == '*') {
06809             char *stringp=NULL;
06810             ast_copy_string(exten2, exten, sizeof(exten2));
06811             /* Parse out extension and callerid */
06812             stringp=exten2 +1;
06813             s1 = strsep(&stringp, "#");
06814             s2 = strsep(&stringp, "#");
06815             if (s2) {
06816                if (!ast_strlen_zero(p->cid_num))
06817                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
06818                else
06819                   if (*(s1 + 2))
06820                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
06821                ast_copy_string(exten, s2 + 1, sizeof(exten));
06822             } else
06823                ast_copy_string(exten, s1 + 2, sizeof(exten));
06824          } else
06825             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06826       }
06827       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
06828          if (exten[0] == '*') {
06829             char *stringp=NULL;
06830             ast_copy_string(exten2, exten, sizeof(exten2));
06831             /* Parse out extension and callerid */
06832             stringp=exten2 +1;
06833             s1 = strsep(&stringp, "#");
06834             s2 = strsep(&stringp, "#");
06835             if (s2 && (*(s2 + 1) == '0')) {
06836                if (*(s2 + 2))
06837                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
06838             }
06839             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
06840             else ast_copy_string(exten, "911", sizeof(exten));
06841          } else
06842             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06843       }
06844       if (p->sig == SIG_FEATB) {
06845          if (exten[0] == '*') {
06846             char *stringp=NULL;
06847             ast_copy_string(exten2, exten, sizeof(exten2));
06848             /* Parse out extension and callerid */
06849             stringp=exten2 +1;
06850             s1 = strsep(&stringp, "#");
06851             ast_copy_string(exten, exten2 + 1, sizeof(exten));
06852          } else
06853             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
06854       }
06855       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
06856          dahdi_wink(p, idx);
06857                         /* some switches require a minimum guard time between
06858                            the last FGD wink and something that answers
06859                            immediately. This ensures it */
06860                         if (ast_safe_sleep(chan,100)) goto quit;
06861       }
06862       dahdi_enable_ec(p);
06863       if (NEED_MFDETECT(p)) {
06864          if (p->dsp) {
06865             if (!p->hardwaredtmf)
06866                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax); 
06867             else {
06868                ast_dsp_free(p->dsp);
06869                p->dsp = NULL;
06870             }
06871          }
06872       }
06873 
06874       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
06875          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06876          if (p->dsp) ast_dsp_digitreset(p->dsp);
06877          res = ast_pbx_run(chan);
06878          if (res) {
06879             ast_log(LOG_WARNING, "PBX exited non-zero\n");
06880             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06881          }
06882          goto quit;
06883       } else {
06884          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
06885          sleep(2);
06886          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
06887          if (res < 0)
06888             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
06889          else
06890             sleep(1);
06891          res = ast_streamfile(chan, "ss-noservice", chan->language);
06892          if (res >= 0)
06893             ast_waitstream(chan, "");
06894          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06895          ast_hangup(chan);
06896          goto quit;
06897       }
06898       break;
06899    case SIG_FXOLS:
06900    case SIG_FXOGS:
06901    case SIG_FXOKS:
06902       /* Read the first digit */
06903       timeout = firstdigittimeout;
06904       /* If starting a threeway call, never timeout on the first digit so someone
06905          can use flash-hook as a "hold" feature */
06906       if (p->subs[SUB_THREEWAY].owner) 
06907          timeout = 999999;
06908       while (len < AST_MAX_EXTENSION-1) {
06909          /* Read digit unless it's supposed to be immediate, in which case the
06910             only answer is 's' */
06911          if (p->immediate) 
06912             res = 's';
06913          else
06914             res = ast_waitfordigit(chan, timeout);
06915          timeout = 0;
06916          if (res < 0) {
06917             ast_debug(1, "waitfordigit returned < 0...\n");
06918             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06919             ast_hangup(chan);
06920             goto quit;
06921          } else if (res)  {
06922             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
06923             exten[len++]=res;
06924             exten[len] = '\0';
06925          }
06926          if (!ast_ignore_pattern(chan->context, exten))
06927             tone_zone_play_tone(p->subs[idx].dfd, -1);
06928          else
06929             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06930          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
06931             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
06932                if (getforward) {
06933                   /* Record this as the forwarding extension */
06934                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward)); 
06935                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
06936                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06937                   if (res)
06938                      break;
06939                   usleep(500000);
06940                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06941                   sleep(1);
06942                   memset(exten, 0, sizeof(exten));
06943                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
06944                   len = 0;
06945                   getforward = 0;
06946                } else  {
06947                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
06948                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
06949                   if (!ast_strlen_zero(p->cid_num)) {
06950                      if (!p->hidecallerid)
06951                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num); 
06952                      else
06953                         ast_set_callerid(chan, NULL, NULL, p->cid_num); 
06954                   }
06955                   if (!ast_strlen_zero(p->cid_name)) {
06956                      if (!p->hidecallerid)
06957                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
06958                   }
06959                   ast_setstate(chan, AST_STATE_RING);
06960                   dahdi_enable_ec(p);
06961                   res = ast_pbx_run(chan);
06962                   if (res) {
06963                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
06964                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06965                   }
06966                   goto quit;
06967                }
06968             } else {
06969                /* It's a match, but they just typed a digit, and there is an ambiguous match,
06970                   so just set the timeout to matchdigittimeout and wait some more */
06971                timeout = matchdigittimeout;
06972             }
06973          } else if (res == 0) {
06974             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
06975             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
06976             dahdi_wait_event(p->subs[idx].dfd);
06977             ast_hangup(chan);
06978             goto quit;
06979          } else if (p->callwaiting && !strcmp(exten, "*70")) {
06980             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
06981             /* Disable call waiting if enabled */
06982             p->callwaiting = 0;
06983             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
06984             if (res) {
06985                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
06986                   chan->name, strerror(errno));
06987             }
06988             len = 0;
06989             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
06990             memset(exten, 0, sizeof(exten));
06991             timeout = firstdigittimeout;
06992                
06993          } else if (!strcmp(exten,ast_pickup_ext())) {
06994             /* Scan all channels and see if there are any
06995              * ringing channels that have call groups
06996              * that equal this channels pickup group  
06997              */
06998             if (idx == SUB_REAL) {
06999                /* Switch us from Third call to Call Wait */
07000                if (p->subs[SUB_THREEWAY].owner) {
07001                   /* If you make a threeway call and the *8# a call, it should actually 
07002                      look like a callwait */
07003                   alloc_sub(p, SUB_CALLWAIT);   
07004                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
07005                   unalloc_sub(p, SUB_THREEWAY);
07006                }
07007                dahdi_enable_ec(p);
07008                if (ast_pickup_call(chan)) {
07009                   ast_debug(1, "No call pickup possible...\n");
07010                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07011                   dahdi_wait_event(p->subs[idx].dfd);
07012                }
07013                ast_hangup(chan);
07014                goto quit;
07015             } else {
07016                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
07017                ast_hangup(chan);
07018                goto quit;
07019             }
07020             
07021          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
07022             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
07023             /* Disable Caller*ID if enabled */
07024             p->hidecallerid = 1;
07025             if (chan->cid.cid_num)
07026                ast_free(chan->cid.cid_num);
07027             chan->cid.cid_num = NULL;
07028             if (chan->cid.cid_name)
07029                ast_free(chan->cid.cid_name);
07030             chan->cid.cid_name = NULL;
07031             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07032             if (res) {
07033                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07034                   chan->name, strerror(errno));
07035             }
07036             len = 0;
07037             memset(exten, 0, sizeof(exten));
07038             timeout = firstdigittimeout;
07039          } else if (p->callreturn && !strcmp(exten, "*69")) {
07040             res = 0;
07041             if (!ast_strlen_zero(p->lastcid_num)) {
07042                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
07043             }
07044             if (!res)
07045                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07046             break;
07047          } else if (!strcmp(exten, "*78")) {
07048             dahdi_dnd(p, 1);
07049             /* Do not disturb */
07050             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07051             getforward = 0;
07052             memset(exten, 0, sizeof(exten));
07053             len = 0;
07054          } else if (!strcmp(exten, "*79")) {
07055             dahdi_dnd(p, 0);
07056             /* Do not disturb */
07057             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07058             getforward = 0;
07059             memset(exten, 0, sizeof(exten));
07060             len = 0;
07061          } else if (p->cancallforward && !strcmp(exten, "*72")) {
07062             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07063             getforward = 1;
07064             memset(exten, 0, sizeof(exten));
07065             len = 0;
07066          } else if (p->cancallforward && !strcmp(exten, "*73")) {
07067             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
07068             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07069             memset(p->call_forward, 0, sizeof(p->call_forward));
07070             getforward = 0;
07071             memset(exten, 0, sizeof(exten));
07072             len = 0;
07073          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) && 
07074                   p->subs[SUB_THREEWAY].owner &&
07075                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
07076             /* This is a three way call, the main call being a real channel, 
07077                and we're parking the first call. */
07078             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
07079             ast_verb(3, "Parking call to '%s'\n", chan->name);
07080             break;
07081          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
07082             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
07083             res = ast_db_put("blacklist", p->lastcid_num, "1");
07084             if (!res) {
07085                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07086                memset(exten, 0, sizeof(exten));
07087                len = 0;
07088             }
07089          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
07090             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
07091             /* Enable Caller*ID if enabled */
07092             p->hidecallerid = 0;
07093             if (chan->cid.cid_num)
07094                ast_free(chan->cid.cid_num);
07095             chan->cid.cid_num = NULL;
07096             if (chan->cid.cid_name)
07097                ast_free(chan->cid.cid_name);
07098             chan->cid.cid_name = NULL;
07099             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
07100             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
07101             if (res) {
07102                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n", 
07103                   chan->name, strerror(errno));
07104             }
07105             len = 0;
07106             memset(exten, 0, sizeof(exten));
07107             timeout = firstdigittimeout;
07108          } else if (!strcmp(exten, "*0")) {
07109             struct ast_channel *nbridge = 
07110                p->subs[SUB_THREEWAY].owner;
07111             struct dahdi_pvt *pbridge = NULL;
07112               /* set up the private struct of the bridged one, if any */
07113             if (nbridge && ast_bridged_channel(nbridge)) 
07114                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
07115             if (nbridge && pbridge && 
07116                 (nbridge->tech == &dahdi_tech) && 
07117                 (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
07118                 ISTRUNK(pbridge)) {
07119                int func = DAHDI_FLASH;
07120                /* Clear out the dial buffer */
07121                p->dop.dialstr[0] = '\0';
07122                /* flash hookswitch */
07123                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07124                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n", 
07125                      nbridge->name, strerror(errno));
07126                }
07127                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07128                unalloc_sub(p, SUB_THREEWAY);
07129                p->owner = p->subs[SUB_REAL].owner;
07130                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
07131                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
07132                ast_hangup(chan);
07133                goto quit;
07134             } else {
07135                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07136                dahdi_wait_event(p->subs[idx].dfd);
07137                tone_zone_play_tone(p->subs[idx].dfd, -1);
07138                swap_subs(p, SUB_REAL, SUB_THREEWAY);
07139                unalloc_sub(p, SUB_THREEWAY);
07140                p->owner = p->subs[SUB_REAL].owner;
07141                ast_hangup(chan);
07142                goto quit;
07143             }              
07144          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
07145                      ((exten[0] != '*') || (strlen(exten) > 2))) {
07146             ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
07147             break;
07148          }
07149          if (!timeout)
07150             timeout = gendigittimeout;
07151          if (len && !ast_ignore_pattern(chan->context, exten))
07152             tone_zone_play_tone(p->subs[idx].dfd, -1);
07153       }
07154       break;
07155    case SIG_FXSLS:
07156    case SIG_FXSGS:
07157    case SIG_FXSKS:
07158 #ifdef HAVE_PRI
07159       if (p->pri) {
07160          /* This is a GR-303 trunk actually.  Wait for the first ring... */
07161          struct ast_frame *f;
07162          int res;
07163          time_t start;
07164 
07165          time(&start);
07166          ast_setstate(chan, AST_STATE_RING);
07167          while (time(NULL) < start + 3) {
07168             res = ast_waitfor(chan, 1000);
07169             if (res) {
07170                f = ast_read(chan);
07171                if (!f) {
07172                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
07173                   ast_hangup(chan);
07174                   goto quit;
07175                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
07176                   res = 1;
07177                } else
07178                   res = 0;
07179                ast_frfree(f);
07180                if (res) {
07181                   ast_debug(1, "Got ring!\n");
07182                   res = 0;
07183                   break;
07184                }
07185             }
07186          }
07187       }
07188 #endif
07189       /* check for SMDI messages */
07190       if (p->use_smdi && p->smdi_iface) {
07191          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
07192 
07193          if (smdi_msg != NULL) {
07194             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
07195 
07196             if (smdi_msg->type == 'B')
07197                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
07198             else if (smdi_msg->type == 'N')
07199                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
07200 
07201             ast_debug(1, "Recieved SMDI message on %s\n", chan->name);
07202          } else {
07203             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
07204          }
07205       }
07206 
07207       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
07208             number = smdi_msg->calling_st;
07209 
07210       /* If we want caller id, we're in a prering state due to a polarity reversal
07211        * and we're set to use a polarity reversal to trigger the start of caller id,
07212        * grab the caller id and wait for ringing to start... */
07213       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
07214          /* If set to use DTMF CID signalling, listen for DTMF */
07215          if (p->cid_signalling == CID_SIG_DTMF) {
07216             int k = 0;
07217             cs = NULL;
07218             ast_debug(1, "Receiving DTMF cid on "
07219                "channel %s\n", chan->name);
07220             dahdi_setlinear(p->subs[idx].dfd, 0);
07221             res = 2000;
07222             for (;;) {
07223                struct ast_frame *f;
07224                res = ast_waitfor(chan, res);
07225                if (res <= 0) {
07226                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07227                      "Exiting simple switch\n");
07228                   ast_hangup(chan);
07229                   goto quit;
07230                } 
07231                f = ast_read(chan);
07232                if (!f)
07233                   break;
07234                if (f->frametype == AST_FRAME_DTMF) {
07235                   dtmfbuf[k++] = f->subclass;
07236                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
07237                   res = 2000;
07238                }
07239                ast_frfree(f);
07240                if (chan->_state == AST_STATE_RING ||
07241                    chan->_state == AST_STATE_RINGING) 
07242                   break; /* Got ring */
07243             }
07244             dtmfbuf[k] = '\0';
07245             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07246             /* Got cid and ring. */
07247             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
07248             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07249             ast_debug(1, "CID is '%s', flags %d\n", 
07250                dtmfcid, flags);
07251             /* If first byte is NULL, we have no cid */
07252             if (!ast_strlen_zero(dtmfcid)) 
07253                number = dtmfcid;
07254             else
07255                number = NULL;
07256          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07257          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
07258             cs = callerid_new(p->cid_signalling);
07259             if (cs) {
07260                samples = 0;
07261 #if 1
07262                bump_gains(p);
07263 #endif
07264                /* Take out of linear mode for Caller*ID processing */
07265                dahdi_setlinear(p->subs[idx].dfd, 0);
07266                
07267                /* First we wait and listen for the Caller*ID */
07268                for (;;) {  
07269                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07270                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07271                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07272                      callerid_free(cs);
07273                      ast_hangup(chan);
07274                      goto quit;
07275                   }
07276                   if (i & DAHDI_IOMUX_SIGEVENT) {
07277                      res = dahdi_get_event(p->subs[idx].dfd);
07278                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07279 
07280                      if (p->cid_signalling == CID_SIG_V23_JP) {
07281                         if (res == DAHDI_EVENT_RINGBEGIN) {
07282                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07283                            usleep(1);
07284                         }
07285                      } else {
07286                         res = 0;
07287                         break;
07288                      }
07289                   } else if (i & DAHDI_IOMUX_READ) {
07290                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
07291                      if (res < 0) {
07292                         if (errno != ELAST) {
07293                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07294                            callerid_free(cs);
07295                            ast_hangup(chan);
07296                            goto quit;
07297                         }
07298                         break;
07299                      }
07300                      samples += res;
07301 
07302                      if  (p->cid_signalling == CID_SIG_V23_JP) {
07303                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
07304                      } else {
07305                         res = callerid_feed(cs, buf, res, AST_LAW(p));
07306                      }
07307 
07308                      if (res < 0) {
07309                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
07310                         break;
07311                      } else if (res)
07312                         break;
07313                      else if (samples > (8000 * 10))
07314                         break;
07315                   }
07316                }
07317                if (res == 1) {
07318                   callerid_get(cs, &name, &number, &flags);
07319                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07320                }
07321 
07322                if (p->cid_signalling == CID_SIG_V23_JP) {
07323                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
07324                   usleep(1);
07325                   res = 4000;
07326                } else {
07327 
07328                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */ 
07329                   res = 2000;
07330                }
07331 
07332                for (;;) {
07333                   struct ast_frame *f;
07334                   res = ast_waitfor(chan, res);
07335                   if (res <= 0) {
07336                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
07337                         "Exiting simple switch\n");
07338                      ast_hangup(chan);
07339                      goto quit;
07340                   } 
07341                   if (!(f = ast_read(chan))) {
07342                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
07343                      ast_hangup(chan);
07344                      goto quit;
07345                   }
07346                   ast_frfree(f);
07347                   if (chan->_state == AST_STATE_RING ||
07348                       chan->_state == AST_STATE_RINGING) 
07349                      break; /* Got ring */
07350                }
07351    
07352                /* We must have a ring by now, so, if configured, lets try to listen for
07353                 * distinctive ringing */ 
07354                if (p->usedistinctiveringdetection) {
07355                   len = 0;
07356                   distMatches = 0;
07357                   /* Clear the current ring data array so we dont have old data in it. */
07358                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07359                      curRingData[receivedRingT] = 0;
07360                   receivedRingT = 0;
07361                   counter = 0;
07362                   counter1 = 0;
07363                   /* Check to see if context is what it should be, if not set to be. */
07364                   if (strcmp(p->context,p->defcontext) != 0) {
07365                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07366                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07367                   }
07368       
07369                   for (;;) {  
07370                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07371                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07372                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07373                         callerid_free(cs);
07374                         ast_hangup(chan);
07375                         goto quit;
07376                      }
07377                      if (i & DAHDI_IOMUX_SIGEVENT) {
07378                         res = dahdi_get_event(p->subs[idx].dfd);
07379                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07380                         res = 0;
07381                         /* Let us detect distinctive ring */
07382       
07383                         curRingData[receivedRingT] = p->ringt;
07384       
07385                         if (p->ringt < p->ringt_base/2)
07386                            break;
07387                         /* Increment the ringT counter so we can match it against
07388                            values in chan_dahdi.conf for distinctive ring */
07389                         if (++receivedRingT == ARRAY_LEN(curRingData))
07390                            break;
07391                      } else if (i & DAHDI_IOMUX_READ) {
07392                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
07393                         if (res < 0) {
07394                            if (errno != ELAST) {
07395                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07396                               callerid_free(cs);
07397                               ast_hangup(chan);
07398                               goto quit;
07399                            }
07400                            break;
07401                         }
07402                         if (p->ringt) 
07403                            p->ringt--;
07404                         if (p->ringt == 1) {
07405                            res = -1;
07406                            break;
07407                         }
07408                      }
07409                   }
07410                      /* this only shows up if you have n of the dring patterns filled in */
07411                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07412                   for (counter = 0; counter < 3; counter++) {
07413                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07414                      channel */
07415                      distMatches = 0;
07416                      for (counter1 = 0; counter1 < 3; counter1++) {
07417                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07418                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
07419                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07420                            curRingData[counter1]);
07421                            distMatches++;
07422                         }
07423                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07424                             curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07425                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07426                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07427                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07428                            distMatches++;
07429                         }
07430                      }
07431 
07432                      if (distMatches == 3) {
07433                         /* The ring matches, set the context to whatever is for distinctive ring.. */
07434                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07435                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07436                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07437                         break;
07438                      }
07439                   }
07440                }
07441                /* Restore linear mode (if appropriate) for Caller*ID processing */
07442                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07443 #if 1
07444                restore_gains(p);
07445 #endif            
07446             } else
07447                ast_log(LOG_WARNING, "Unable to get caller ID space\n");       
07448          } else {
07449             ast_log(LOG_WARNING, "Channel %s in prering "
07450                "state, but I have nothing to do. "
07451                "Terminating simple switch, should be "
07452                "restarted by the actual ring.\n", 
07453                chan->name);
07454             ast_hangup(chan);
07455             goto quit;
07456          }
07457       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
07458                         if (p->cid_signalling == CID_SIG_DTMF) {
07459                                 int k = 0;
07460                                 cs = NULL;
07461                                 dahdi_setlinear(p->subs[idx].dfd, 0);
07462                                 res = 2000;
07463                                 for (;;) {
07464                                         struct ast_frame *f;
07465                                         res = ast_waitfor(chan, res);
07466                                         if (res <= 0) {
07467                                                 ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
07468                                                                 "Exiting simple switch\n");
07469                                                 ast_hangup(chan);
07470                                                 return NULL;
07471                                         }
07472                                         f = ast_read(chan);
07473                                         if (f->frametype == AST_FRAME_DTMF) {
07474                                                 dtmfbuf[k++] = f->subclass;
07475                                                 ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
07476                                                 res = 2000;
07477                                         }
07478                                         ast_frfree(f);
07479 
07480                                         if (p->ringt_base == p->ringt)
07481                                                 break;
07482 
07483                                 }
07484                                 dtmfbuf[k] = '\0';
07485                                 dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07486                                 /* Got cid and ring. */
07487                                 callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
07488                                 ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
07489                                                 dtmfcid, flags);
07490                                 /* If first byte is NULL, we have no cid */
07491                                 if (!ast_strlen_zero(dtmfcid))
07492                                         number = dtmfcid;
07493                                 else
07494                                         number = NULL;
07495                                 /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
07496                         } else {
07497          /* FSK Bell202 callerID */
07498          cs = callerid_new(p->cid_signalling);
07499          if (cs) {
07500 #if 1
07501             bump_gains(p);
07502 #endif            
07503             samples = 0;
07504             len = 0;
07505             distMatches = 0;
07506             /* Clear the current ring data array so we dont have old data in it. */
07507             for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
07508                curRingData[receivedRingT] = 0;
07509             receivedRingT = 0;
07510             counter = 0;
07511             counter1 = 0;
07512             /* Check to see if context is what it should be, if not set to be. */
07513             if (strcmp(p->context,p->defcontext) != 0) {
07514                ast_copy_string(p->context, p->defcontext, sizeof(p->context));
07515                ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
07516             }
07517 
07518             /* Take out of linear mode for Caller*ID processing */
07519             dahdi_setlinear(p->subs[idx].dfd, 0);
07520             for (;;) {  
07521                i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07522                if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
07523                   ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07524                   callerid_free(cs);
07525                   ast_hangup(chan);
07526                   goto quit;
07527                }
07528                if (i & DAHDI_IOMUX_SIGEVENT) {
07529                   res = dahdi_get_event(p->subs[idx].dfd);
07530                   ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07531                   /* If we get a PR event, they hung up while processing calerid */
07532                   if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
07533                      ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
07534                      p->polarity = POLARITY_IDLE;
07535                      callerid_free(cs);
07536                      ast_hangup(chan);
07537                      goto quit;
07538                   }
07539                   res = 0;
07540                   /* Let us detect callerid when the telco uses distinctive ring */
07541 
07542                   curRingData[receivedRingT] = p->ringt;
07543 
07544                   if (p->ringt < p->ringt_base/2)
07545                      break;
07546                   /* Increment the ringT counter so we can match it against
07547                      values in chan_dahdi.conf for distinctive ring */
07548                   if (++receivedRingT == ARRAY_LEN(curRingData))
07549                      break;
07550                } else if (i & DAHDI_IOMUX_READ) {
07551                   res = read(p->subs[idx].dfd, buf, sizeof(buf));
07552                   if (res < 0) {
07553                      if (errno != ELAST) {
07554                         ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07555                         callerid_free(cs);
07556                         ast_hangup(chan);
07557                         goto quit;
07558                      }
07559                      break;
07560                   }
07561                   if (p->ringt) 
07562                      p->ringt--;
07563                   if (p->ringt == 1) {
07564                      res = -1;
07565                      break;
07566                   }
07567                   samples += res;
07568                   res = callerid_feed(cs, buf, res, AST_LAW(p));
07569                   if (res < 0) {
07570                      ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
07571                      break;
07572                   } else if (res)
07573                      break;
07574                   else if (samples > (8000 * 10))
07575                      break;
07576                }
07577             }
07578             if (res == 1) {
07579                callerid_get(cs, &name, &number, &flags);
07580                ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
07581             }
07582             if (distinctiveringaftercid == 1) {
07583                /* Clear the current ring data array so we dont have old data in it. */
07584                for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
07585                   curRingData[receivedRingT] = 0;
07586                }
07587                receivedRingT = 0;
07588                ast_verb(3, "Detecting post-CID distinctive ring\n");
07589                for (;;) {
07590                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
07591                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i)))    {
07592                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
07593                      callerid_free(cs);
07594                      ast_hangup(chan);
07595                      goto quit;
07596                   }
07597                   if (i & DAHDI_IOMUX_SIGEVENT) {
07598                      res = dahdi_get_event(p->subs[idx].dfd);
07599                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
07600                      res = 0;
07601                      /* Let us detect callerid when the telco uses distinctive ring */
07602 
07603                      curRingData[receivedRingT] = p->ringt;
07604 
07605                      if (p->ringt < p->ringt_base/2)
07606                         break;
07607                      /* Increment the ringT counter so we can match it against
07608                         values in chan_dahdi.conf for distinctive ring */
07609                      if (++receivedRingT == ARRAY_LEN(curRingData))
07610                         break;
07611                   } else if (i & DAHDI_IOMUX_READ) {
07612                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
07613                      if (res < 0) {
07614                         if (errno != ELAST) {
07615                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
07616                            callerid_free(cs);
07617                            ast_hangup(chan);
07618                            goto quit;
07619                         }
07620                         break;
07621                      }
07622                   if (p->ringt)
07623                      p->ringt--;
07624                      if (p->ringt == 1) {
07625                         res = -1;
07626                         break;
07627                      }
07628                   }
07629                }
07630             }
07631             if (p->usedistinctiveringdetection) {
07632                   /* this only shows up if you have n of the dring patterns filled in */
07633                ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
07634 
07635                for (counter = 0; counter < 3; counter++) {
07636                   /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
07637                   channel */
07638                      /* this only shows up if you have n of the dring patterns filled in */
07639                   ast_verb(3, "Checking %d,%d,%d\n",
07640                         p->drings.ringnum[counter].ring[0],
07641                         p->drings.ringnum[counter].ring[1],
07642                         p->drings.ringnum[counter].ring[2]);
07643                   distMatches = 0;
07644                   for (counter1 = 0; counter1 < 3; counter1++) {
07645                      ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
07646                      if (p->drings.ringnum[counter].ring[counter1] == -1) {
07647                         ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
07648                         curRingData[counter1]);
07649                         distMatches++;
07650                      }
07651                      else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
07652                          curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
07653                         ast_verb(3, "Ring pattern matched in range: %d to %d\n",
07654                         (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
07655                         (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
07656                         distMatches++;
07657                      }
07658                   }
07659                   if (distMatches == 3) {
07660                      /* The ring matches, set the context to whatever is for distinctive ring.. */
07661                      ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
07662                      ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
07663                      ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
07664                      break;
07665                   }
07666                }
07667             }
07668             /* Restore linear mode (if appropriate) for Caller*ID processing */
07669             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07670 #if 1
07671             restore_gains(p);
07672 #endif            
07673             if (res < 0) {
07674                ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
07675             }
07676          } else
07677             ast_log(LOG_WARNING, "Unable to get caller ID space\n");
07678       }
07679       }
07680       else
07681          cs = NULL;
07682 
07683       if (number)
07684          ast_shrink_phone_number(number);
07685       ast_set_callerid(chan, number, name, number);
07686 
07687       if (smdi_msg)
07688          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
07689 
07690       if (cs)
07691          callerid_free(cs);
07692       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
07693       if (flags & CID_MSGWAITING) {
07694          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
07695          notify_message(p->mailbox, 1);
07696          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
07697          if (p->mwimonitor_rpas) {
07698             ast_hangup(chan);
07699             return NULL;
07700          }
07701       } else if (flags & CID_NOMSGWAITING) {
07702          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
07703          notify_message(p->mailbox, 0);
07704          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
07705          if (p->mwimonitor_rpas) {
07706             ast_hangup(chan);
07707             return NULL;
07708          }
07709       }
07710 
07711       ast_setstate(chan, AST_STATE_RING);
07712       chan->rings = 1;
07713       p->ringt = p->ringt_base;
07714       res = ast_pbx_run(chan);
07715       if (res) {
07716          ast_hangup(chan);
07717          ast_log(LOG_WARNING, "PBX exited non-zero\n");
07718       }
07719       goto quit;
07720    default:
07721       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
07722       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07723       if (res < 0)
07724             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07725    }
07726    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07727    if (res < 0)
07728          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
07729    ast_hangup(chan);
07730 quit:
07731    ast_mutex_lock(&ss_thread_lock);
07732    ss_thread_count--;
07733    ast_cond_signal(&ss_thread_complete);
07734    ast_mutex_unlock(&ss_thread_lock);
07735    return NULL;
07736 }

static int start_pri ( struct dahdi_pri pri  )  [static]

Definition at line 11960 of file chan_dahdi.c.

References ast_log(), dahdi_close_pri_fd(), DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_OUTGOING, 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, dahdi_pri::sig, SIG_BRI, SIG_BRI_PTMP, and dahdi_pri::switchtype.

Referenced by setup_dahdi().

11961 {
11962    int res, x;
11963    struct dahdi_params p;
11964    struct dahdi_bufferinfo bi;
11965    struct dahdi_spaninfo si;
11966    int i;
11967    
11968    for (i = 0; i < NUM_DCHANS; i++) {
11969       if (!pri->dchannels[i])
11970          break;
11971       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11972       x = pri->dchannels[i];
11973       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11974          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11975          return -1;
11976       }
11977       memset(&p, 0, sizeof(p));
11978       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11979       if (res) {
11980          dahdi_close_pri_fd(pri, i);
11981          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11982          return -1;
11983       }
11984       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11985          dahdi_close_pri_fd(pri, i);
11986          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
11987          return -1;
11988       }
11989       memset(&si, 0, sizeof(si));
11990       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11991       if (res) {
11992          dahdi_close_pri_fd(pri, i);
11993          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11994       }
11995       if (!si.alarms)
11996          pri->dchanavail[i] |= DCHAN_NOTINALARM;
11997       else
11998          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11999       memset(&bi, 0, sizeof(bi));
12000       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12001       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12002       bi.numbufs = 32;
12003       bi.bufsize = 1024;
12004       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12005          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12006          dahdi_close_pri_fd(pri, i);
12007          return -1;
12008       }
12009       switch (pri->sig) {
12010          case SIG_BRI:
12011             pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12012             break;
12013          case SIG_BRI_PTMP:
12014             pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12015             break;
12016          default:
12017             pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12018       }
12019       /* Force overlap dial if we're doing GR-303! */
12020       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12021          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12022       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12023 #ifdef HAVE_PRI_INBANDDISCONNECT
12024       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12025 #endif
12026       /* Enslave to master if appropriate */
12027       if (i)
12028          pri_enslave(pri->dchans[0], pri->dchans[i]);
12029       if (!pri->dchans[i]) {
12030          dahdi_close_pri_fd(pri, i);
12031          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12032          return -1;
12033       }
12034       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12035       pri_set_nsf(pri->dchans[i], pri->nsf);
12036 #ifdef PRI_GETSET_TIMERS
12037       for (x = 0; x < PRI_MAX_TIMERS; x++) {
12038          if (pritimers[x] != 0)
12039             pri_set_timer(pri->dchans[i], x, pritimers[x]);
12040       }
12041 #endif
12042    }
12043    /* Assume primary is the one we use */
12044    pri->pri = pri->dchans[0];
12045    pri->resetpos = -1;
12046    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12047       for (i = 0; i < NUM_DCHANS; i++) {
12048          if (!pri->dchannels[i])
12049             break;
12050          dahdi_close_pri_fd(pri, i);
12051       }
12052       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12053       return -1;
12054    }
12055    return 0;
12056 }

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

Definition at line 1428 of file chan_dahdi.c.

References ast_channel_set_fd(), ast_debug, dahdi_subchannel::chan, dahdi_subchannel::dfd, dahdi_subchannel::inthreeway, dahdi_subchannel::owner, dahdi_pvt::subs, and wakeup_sub().

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

01429 {
01430    int tchan;
01431    int tinthreeway;
01432    struct ast_channel *towner;
01433 
01434    ast_debug(1, "Swapping %d and %d\n", a, b);
01435 
01436    tchan = p->subs[a].chan;
01437    towner = p->subs[a].owner;
01438    tinthreeway = p->subs[a].inthreeway;
01439 
01440    p->subs[a].chan = p->subs[b].chan;
01441    p->subs[a].owner = p->subs[b].owner;
01442    p->subs[a].inthreeway = p->subs[b].inthreeway;
01443 
01444    p->subs[b].chan = tchan;
01445    p->subs[b].owner = towner;
01446    p->subs[b].inthreeway = tinthreeway;
01447 
01448    if (p->subs[a].owner) 
01449       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01450    if (p->subs[b].owner) 
01451       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01452    wakeup_sub(p, a, NULL);
01453    wakeup_sub(p, b, NULL);
01454 }

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

Definition at line 1578 of file chan_dahdi.c.

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

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

01579 {
01580    if (!x) {
01581       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01582       return -1;
01583    }
01584    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01585    dahdi_close_sub(p, x);
01586    p->subs[x].linear = 0;
01587    p->subs[x].chan = 0;
01588    p->subs[x].owner = NULL;
01589    p->subs[x].inthreeway = 0;
01590    p->polarity = POLARITY_IDLE;
01591    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01592    return 0;
01593 }

static int unload_module ( void   )  [static]

Definition at line 14070 of file chan_dahdi.c.

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

14071 {
14072 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14073    int y;
14074 #endif
14075 #ifdef HAVE_PRI
14076    for (y = 0; y < NUM_SPANS; y++)
14077       ast_mutex_destroy(&pris[y].lock);
14078 #endif
14079 #ifdef HAVE_SS7
14080    for (y = 0; y < NUM_SPANS; y++)
14081       ast_mutex_destroy(&linksets[y].lock);
14082 #endif /* HAVE_SS7 */
14083    return __unload_module();
14084 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

01969 {
01970    int needconf = 0;
01971    int x;
01972    int useslavenative;
01973    struct dahdi_pvt *slave = NULL;
01974 
01975    useslavenative = isslavenative(p, &slave);
01976    /* Start with the obvious, general stuff */
01977    for (x = 0; x < 3; x++) {
01978       /* Look for three way calls */
01979       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01980          conf_add(p, &p->subs[x], x, 0);
01981          needconf++;
01982       } else {
01983          conf_del(p, &p->subs[x], x);
01984       }
01985    }
01986    /* If we have a slave, add him to our conference now. or DAX
01987       if this is slave native */
01988    for (x = 0; x < MAX_SLAVES; x++) {
01989       if (p->slaves[x]) {
01990          if (useslavenative)
01991             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01992          else {
01993             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01994             needconf++;
01995          }
01996       }
01997    }
01998    /* If we're supposed to be in there, do so now */
01999    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02000       if (useslavenative)
02001          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02002       else {
02003          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02004          needconf++;
02005       }
02006    }
02007    /* If we have a master, add ourselves to his conference */
02008    if (p->master) {
02009       if (isslavenative(p->master, NULL)) {
02010          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02011       } else {
02012          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02013       }
02014    }
02015    if (!needconf) {
02016       /* Nobody is left (or should be left) in our conference.
02017          Kill it. */
02018       p->confno = -1;
02019    }
02020    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02021    return 0;
02022 }

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

Definition at line 1335 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), and DEADLOCK_AVOIDANCE.

Referenced by swap_subs().

01339 {
01340 #ifdef HAVE_PRI
01341    if (pri)
01342       ast_mutex_unlock(&pri->lock);
01343 #endif         
01344    for (;;) {
01345       if (p->subs[a].owner) {
01346          if (ast_channel_trylock(p->subs[a].owner)) {
01347             DEADLOCK_AVOIDANCE(&p->lock);
01348          } else {
01349             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01350             ast_channel_unlock(p->subs[a].owner);
01351             break;
01352          }
01353       } else
01354          break;
01355    }
01356 #ifdef HAVE_PRI
01357    if (pri)
01358       ast_mutex_lock(&pri->lock);
01359 #endif         
01360 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 15481 of file chan_dahdi.c.

int alarm

Definition at line 1733 of file chan_dahdi.c.

Referenced by alarm2str().

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

Referenced by alarm2str().

struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}} [static]

Definition at line 1309 of file chan_dahdi.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 15481 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 1290 of file chan_dahdi.c.

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

const char config[] = "chan_dahdi.conf" [static]

Definition at line 168 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 13303 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 12415 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

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

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

Definition at line 3266 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1217 of file chan_dahdi.c.

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 118 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 226 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 227 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 238 of file chan_dahdi.c.

char* events[] [static]

Definition at line 1710 of file chan_dahdi.c.

Referenced by geteventbyname().

int firstdigittimeout = 16000 [static]

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

Definition at line 254 of file chan_dahdi.c.

Referenced by disa_exec(), and mgcp_ss().

int gendigittimeout = 8000 [static]

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

Definition at line 257 of file chan_dahdi.c.

Referenced by mgcp_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 125 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 266 of file chan_dahdi.c.

struct dahdi_pvt * ifend [static]

struct dahdi_pvt * iflist [static]

Referenced by __oh323_destroy(), __unload_module(), action_dahdishowchannels(), chandup(), dahdi_destroy_channel_bynum(), dahdi_hangup(), dahdi_request(), dahdi_restart(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), destroy_channel(), do_monitor(), find_call_locked(), find_channel(), load_module(), mkintf(), oh323_alloc(), phone_request(), and unload_module().

ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Protect the interface list (of dahdi_pvt's).

Definition at line 263 of file chan_dahdi.c.

Referenced by __unload_module(), action_dahdishowchannels(), dahdi_hangup(), dahdi_request(), dahdi_set_dnd(), dahdi_set_hwgain(), dahdi_set_swgain(), dahdi_show_channel(), dahdi_show_channels(), dahdi_softhangup_all(), destroy_all_channels(), do_monitor(), find_call_locked(), load_module(), oh323_alloc(), oh323_destroy(), phone_request(), restart_monitor(), setup_dahdi(), and unload_module().

struct ast_channel inuse [static]

Definition at line 245 of file chan_dahdi.c.

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

const char* lbostr[] [static]

Definition at line 106 of file chan_dahdi.c.

int matchdigittimeout = 3000 [static]

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

Definition at line 260 of file chan_dahdi.c.

Referenced by mgcp_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 278 of file chan_dahdi.c.

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

ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [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 274 of file chan_dahdi.c.

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

ast_cond_t mwi_thread_complete [static]

Definition at line 279 of file chan_dahdi.c.

int mwi_thread_count = 0 [static]

Definition at line 284 of file chan_dahdi.c.

ast_mutex_t mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 281 of file chan_dahdi.c.

Referenced by dahdi_restart(), and mwi_send_thread().

int mwilevel = 512 [static]

Definition at line 242 of file chan_dahdi.c.

char mwimonitornotify[PATH_MAX] = "" [static]

Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled

Definition at line 232 of file chan_dahdi.c.

int mwisend_rpas = 0 [static]

Definition at line 233 of file chan_dahdi.c.

char* name

Definition at line 1734 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1287 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 286 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 240 of file chan_dahdi.c.

char parkinglot[AST_MAX_EXTENSION] = "" [static]

Default parking lot for this channel

Definition at line 229 of file chan_dahdi.c.

Referenced by __find_callno(), ast_iax2_new(), build_gateway(), build_parkinglot(), build_user(), check_access(), check_peer_ok(), create_addr_from_peer(), find_parkinglot(), findparkinglotname(), func_channel_write(), gtalk_load_config(), gtalk_new(), park_exec_full(), park_space_reserve(), parkinglot_addref(), parkinglot_cmp_cb(), parkinglot_hash_cb(), parkinglot_unref(), set_pvt_defaults(), sip_alloc(), and store_config_core().

int pridebugfd = -1 [static]

Definition at line 249 of file chan_dahdi.c.

ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 269 of file chan_dahdi.c.

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

char pridebugfilename[1024] = "" [static]

Definition at line 250 of file chan_dahdi.c.

struct dahdi_pri pris[NUM_SPANS] [static]

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

ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

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

struct dahdi_pvt* round_robin[32]

Definition at line 1244 of file chan_dahdi.c.

Referenced by dahdi_request(), and load_module().

ast_cond_t ss_thread_complete [static]

Definition at line 280 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 285 of file chan_dahdi.c.

ast_mutex_t ss_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 282 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

char* subnames[] [static]

Initial value:

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

Definition at line 486 of file chan_dahdi.c.

const char tdesc[] [static]

Initial value:

 "DAHDI Telephony Driver"

               " w/PRI"

Definition at line 159 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 237 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 1288 of file chan_dahdi.c.


Generated on Fri Jun 19 12:10:12 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7