Thu Jul 9 13:40:55 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 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

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 alarm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static void apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static void build_status (char *s, size_t len, int status, int active)
static int bump_gains (struct dahdi_pvt *p)
static 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 index, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
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 index, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
static struct ast_channeldahdi_new (struct dahdi_pvt *, int, int, int, int, int)
static int dahdi_open (char *fn)
static void dahdi_pri_error (struct pri *pri, char *s)
static void dahdi_pri_message (struct pri *pri, char *s)
static void dahdi_queue_frame (struct dahdi_pvt *p, struct ast_frame *f, 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 index)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static void destroy_all_channels (void)
static int destroy_channel (struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt **pvt)
static char * dialplan2str (int dialplan)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_idle_thread (void *vchan)
static void * do_monitor (void *data)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, int law)
static struct dahdi_pvtfind_channel (int channel)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alarms)
static 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 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_thread (void *data)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int index, int linear)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static 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, struct ast_variable *v, int reload, int skipchannels)
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, .reload = reload, }
struct {
   int   alarm
   char *   name
alarms []
static const struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static 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 int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
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_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(), and process_dahdi().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 223 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 222 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

Definition at line 221 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), dahdi_new(), and process_dahdi().

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

10,000 ms

Definition at line 324 of file chan_dahdi.c.

Referenced by dahdi_callwait().

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

300 ms

Definition at line 323 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 1295 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 1296 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 325 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 505 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 506 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 process_dahdi(), and start_pri().

#define DAHDI_OVERLAPDIAL_INCOMING   2

Definition at line 217 of file chan_dahdi.c.

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

#define DAHDI_OVERLAPDIAL_NONE   0

Definition at line 215 of file chan_dahdi.c.

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_OUTGOING   1

Definition at line 216 of file chan_dahdi.c.

Referenced by dahdi_read(), process_dahdi(), 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 446 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

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

#define HANGUP   1

Definition at line 13103 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 1292 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 320 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 321 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 13942 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 508 of file chan_dahdi.c.

Referenced by isslavenative().

#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

Definition at line 326 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 1270 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(), process_dahdi(), setup_dahdi(), and unload_module().

#define POLARITY_IDLE   0

Definition at line 464 of file chan_dahdi.c.

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

#define POLARITY_REV   1

Definition at line 465 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and handle_init_event().

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

Definition at line 385 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 387 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 386 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

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

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

#define sig2str   dahdi_sig2str

Definition at line 1821 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), process_dahdi(), 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(), mkintf(), and process_dahdi().

#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)

Definition at line 196 of file chan_dahdi.c.

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

#define SIG_PRI   DAHDI_SIG_CLEAR

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

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

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

#define SUB_REAL   0

Active call

Definition at line 459 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(), features_hangup(), features_request(), find_subchannel_by_name(), get_alarms(), handle_init_event(), HandleCallIncoming(), HandleCallOutgoing(), key_call(), key_dial_page(), mkintf(), 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 461 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(), features_hangup(), HandleCallOutgoing(), ss_thread(), TransferCallStep1(), unistim_answer(), and unistim_hangup().

#define tdesc   "DAHDI Telephony w/PRI"

Definition at line 15163 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Definition at line 13102 of file chan_dahdi.c.

Referenced by action_transfer(), and dahdi_fake_event().


Function Documentation

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 15177 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

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

13761 {
13762    struct dahdi_pvt *p;
13763 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13764    int i, j;
13765 #endif
13766 
13767 #ifdef HAVE_PRI
13768    for (i = 0; i < NUM_SPANS; i++) {
13769       if (pris[i].master != AST_PTHREADT_NULL) 
13770          pthread_cancel(pris[i].master);
13771    }
13772    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
13773    ast_unregister_application(dahdi_send_keypad_facility_app);
13774 #endif
13775 #if defined(HAVE_SS7)
13776    for (i = 0; i < NUM_SPANS; i++) {
13777       if (linksets[i].master != AST_PTHREADT_NULL)
13778          pthread_cancel(linksets[i].master);
13779       }
13780    ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
13781 #endif
13782 
13783    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
13784    ast_manager_unregister( "DAHDIDialOffhook" );
13785    ast_manager_unregister( "DAHDIHangup" );
13786    ast_manager_unregister( "DAHDITransfer" );
13787    ast_manager_unregister( "DAHDIDNDoff" );
13788    ast_manager_unregister( "DAHDIDNDon" );
13789    ast_manager_unregister("DAHDIShowChannels");
13790    ast_manager_unregister("DAHDIRestart");
13791    ast_channel_unregister(&dahdi_tech);
13792    ast_mutex_lock(&iflock);
13793    /* Hangup all interfaces if they have an owner */
13794    p = iflist;
13795    while (p) {
13796       if (p->owner)
13797          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
13798       p = p->next;
13799    }
13800    ast_mutex_unlock(&iflock);
13801    ast_mutex_lock(&monlock);
13802    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
13803       pthread_cancel(monitor_thread);
13804       pthread_kill(monitor_thread, SIGURG);
13805       pthread_join(monitor_thread, NULL);
13806    }
13807    monitor_thread = AST_PTHREADT_STOP;
13808    ast_mutex_unlock(&monlock);
13809 
13810    destroy_all_channels();
13811 
13812 #if defined(HAVE_PRI)
13813    for (i = 0; i < NUM_SPANS; i++) {
13814       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
13815          pthread_join(pris[i].master, NULL);
13816       for (j = 0; j < NUM_DCHANS; j++) {
13817          dahdi_close_pri_fd(&(pris[i]), j);
13818       }
13819    }
13820 #endif
13821 
13822 #if defined(HAVE_SS7)
13823    for (i = 0; i < NUM_SPANS; i++) {
13824       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
13825          pthread_join(linksets[i].master, NULL);
13826       for (j = 0; j < NUM_DCHANS; j++) {
13827          dahdi_close_ss7_fd(&(linksets[i]), j);
13828       }
13829    }
13830 #endif
13831 
13832    ast_cond_destroy(&ss_thread_complete);
13833    return 0;
13834 }

static void __unreg_module ( void   )  [static]

Definition at line 15177 of file chan_dahdi.c.

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

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

13210 {
13211    struct dahdi_pvt *p = NULL;
13212    const char *channel = astman_get_header(m, "DAHDIChannel");
13213    const char *number = astman_get_header(m, "Number");
13214    int i;
13215 
13216    if (ast_strlen_zero(channel)) {
13217       astman_send_error(s, m, "No channel specified");
13218       return 0;
13219    }
13220    if (ast_strlen_zero(number)) {
13221       astman_send_error(s, m, "No number specified");
13222       return 0;
13223    }
13224    p = find_channel(atoi(channel));
13225    if (!p) {
13226       astman_send_error(s, m, "No such channel");
13227       return 0;
13228    }
13229    if (!p->owner) {
13230       astman_send_error(s, m, "Channel does not have it's owner");
13231       return 0;
13232    }
13233    for (i = 0; i < strlen(number); i++) {
13234       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13235       dahdi_queue_frame(p, &f, NULL); 
13236    }
13237    astman_send_ack(s, m, "DAHDIDialOffhook");
13238    return 0;
13239 }

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

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

13153 {
13154    struct dahdi_pvt *p = NULL;
13155    const char *channel = astman_get_header(m, "DAHDIChannel");
13156 
13157    if (ast_strlen_zero(channel)) {
13158       astman_send_error(s, m, "No channel specified");
13159       return 0;
13160    }
13161    p = find_channel(atoi(channel));
13162    if (!p) {
13163       astman_send_error(s, m, "No such channel");
13164       return 0;
13165    }
13166    p->dnd = 0;
13167    astman_send_ack(s, m, "DND Disabled");
13168    return 0;
13169 }

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

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

13134 {
13135    struct dahdi_pvt *p = NULL;
13136    const char *channel = astman_get_header(m, "DAHDIChannel");
13137 
13138    if (ast_strlen_zero(channel)) {
13139       astman_send_error(s, m, "No channel specified");
13140       return 0;
13141    }
13142    p = find_channel(atoi(channel));
13143    if (!p) {
13144       astman_send_error(s, m, "No such channel");
13145       return 0;
13146    }
13147    p->dnd = 1;
13148    astman_send_ack(s, m, "DND Enabled");
13149    return 0;
13150 }

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

Definition at line 12408 of file chan_dahdi.c.

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

Referenced by load_module().

12409 {
12410    if (dahdi_restart() != 0) {
12411       astman_send_error(s, m, "Failed rereading DAHDI configuration");
12412       return 1;
12413    }
12414    astman_send_ack(s, m, "DAHDIRestart: Success");
12415    return 0;
12416 }

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

Definition at line 13241 of file chan_dahdi.c.

References ast_channel::accountcode, alarm, 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().

13242 {
13243    struct dahdi_pvt *tmp = NULL;
13244    const char *id = astman_get_header(m, "ActionID");
13245    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13246    char idText[256] = "";
13247    int channels = 0;
13248    int dahdichanquery = -1;
13249    if (!ast_strlen_zero(dahdichannel)) {
13250       dahdichanquery = atoi(dahdichannel);
13251    }
13252 
13253    astman_send_ack(s, m, "DAHDI channel status will follow");
13254    if (!ast_strlen_zero(id))
13255       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13256 
13257    ast_mutex_lock(&iflock);
13258    
13259    tmp = iflist;
13260    while (tmp) {
13261       if (tmp->channel > 0) {
13262          int alarm = get_alarms(tmp);
13263 
13264          /* If a specific channel is queried for, only deliver status for that channel */
13265          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13266             continue;
13267 
13268          channels++;
13269          if (tmp->owner) {
13270             /* Add data if we have a current call */
13271             astman_append(s,
13272                "Event: DAHDIShowChannels\r\n"
13273                "DAHDIChannel: %d\r\n"
13274                "Channel: %s\r\n"
13275                "Uniqueid: %s\r\n"
13276                "AccountCode: %s\r\n"
13277                "Signalling: %s\r\n"
13278                "SignallingCode: %d\r\n"
13279                "Context: %s\r\n"
13280                "DND: %s\r\n"
13281                "Alarm: %s\r\n"
13282                "%s"
13283                "\r\n",
13284                tmp->channel, 
13285                tmp->owner->name,
13286                tmp->owner->uniqueid,
13287                tmp->owner->accountcode,
13288                sig2str(tmp->sig), 
13289                tmp->sig,
13290                tmp->context, 
13291                tmp->dnd ? "Enabled" : "Disabled",
13292                alarm2str(alarm), idText);
13293          } else {
13294             astman_append(s,
13295                "Event: DAHDIShowChannels\r\n"
13296                "DAHDIChannel: %d\r\n"
13297                "Signalling: %s\r\n"
13298                "SignallingCode: %d\r\n"
13299                "Context: %s\r\n"
13300                "DND: %s\r\n"
13301                "Alarm: %s\r\n"
13302                "%s"
13303                "\r\n",
13304                tmp->channel, sig2str(tmp->sig), tmp->sig, 
13305                tmp->context, 
13306                tmp->dnd ? "Enabled" : "Disabled",
13307                alarm2str(alarm), idText);
13308          }
13309       } 
13310 
13311       tmp = tmp->next;
13312    }
13313 
13314    ast_mutex_unlock(&iflock);
13315    
13316    astman_append(s, 
13317       "Event: DAHDIShowChannelsComplete\r\n"
13318       "%s"
13319       "Items: %d\r\n"
13320       "\r\n", 
13321       idText,
13322       channels);
13323    return 0;
13324 }

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

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

13172 {
13173    struct dahdi_pvt *p = NULL;
13174    const char *channel = astman_get_header(m, "DAHDIChannel");
13175 
13176    if (ast_strlen_zero(channel)) {
13177       astman_send_error(s, m, "No channel specified");
13178       return 0;
13179    }
13180    p = find_channel(atoi(channel));
13181    if (!p) {
13182       astman_send_error(s, m, "No such channel");
13183       return 0;
13184    }
13185    dahdi_fake_event(p,TRANSFER);
13186    astman_send_ack(s, m, "DAHDITransfer");
13187    return 0;
13188 }

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

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

13191 {
13192    struct dahdi_pvt *p = NULL;
13193    const char *channel = astman_get_header(m, "DAHDIChannel");
13194 
13195    if (ast_strlen_zero(channel)) {
13196       astman_send_error(s, m, "No channel specified");
13197       return 0;
13198    }
13199    p = find_channel(atoi(channel));
13200    if (!p) {
13201       astman_send_error(s, m, "No such channel");
13202       return 0;
13203    }
13204    dahdi_fake_event(p,HANGUP);
13205    astman_send_ack(s, m, "DAHDIHangup");
13206    return 0;
13207 }

static char* alarm2str ( int  alarm  )  [static]

Definition at line 1726 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

01727 {
01728    int x;
01729    for (x = 0; x < ARRAY_LEN(alarms); x++) {
01730       if (alarms[x].alarm & alarm)
01731          return alarms[x].name;
01732    }
01733    return alarm ? "Unknown Alarm" : "No Alarm";
01734 }

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

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

01523 {
01524    struct dahdi_bufferinfo bi;
01525    int res;
01526    if (p->subs[x].dfd >= 0) {
01527       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
01528       return -1;
01529    }
01530 
01531    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
01532    if (p->subs[x].dfd <= -1) {
01533       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
01534       return -1;
01535    }
01536 
01537    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
01538    if (!res) {
01539       bi.txbufpolicy = p->buf_policy;
01540       bi.rxbufpolicy = p->buf_policy;
01541       bi.numbufs = p->buf_no;
01542       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
01543       if (res < 0) {
01544          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
01545       }
01546    } else 
01547       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
01548 
01549    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
01550       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
01551       dahdi_close_sub(p, x);
01552       p->subs[x].dfd = -1;
01553       return -1;
01554    }
01555    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
01556    return 0;
01557 }

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

10635 {
10636    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10637       snprintf(buf, size, "%s", number);
10638       return;
10639    }
10640    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10641       if (size) {
10642          *buf = '\0';
10643       }
10644       return;
10645    }
10646    switch (plan) {
10647    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10648       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10649       break;
10650    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10651       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10652       break;
10653    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10654       snprintf(buf, size, "%s%s", pri->localprefix, number);
10655       break;
10656    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10657       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10658       break;
10659    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10660       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10661       break;
10662    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10663       snprintf(buf, size, "%s", number);
10664       break;
10665    }
10666 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 4497 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_onhook_message(), handle_request(), handle_soft_key_event_message(), and local_attended_transfer().

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

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

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

09067 {
09068    int res;
09069    struct dahdi_params par;
09070 
09071    /* First, check group matching */
09072    if (groupmatch) {
09073       if ((p->group & groupmatch) != groupmatch)
09074          return 0;
09075       *groupmatched = 1;
09076    }
09077    /* Check to see if we have a channel match */
09078    if (channelmatch != -1) {
09079       if (p->channel != channelmatch)
09080          return 0;
09081       *channelmatched = 1;
09082    }
09083    /* We're at least busy at this point */
09084    if (busy) {
09085       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
09086          *busy = 1;
09087    }
09088    /* If do not disturb, definitely not */
09089    if (p->dnd)
09090       return 0;
09091    /* If guard time, definitely not */
09092    if (p->guardtime && (time(NULL) < p->guardtime)) 
09093       return 0;
09094 
09095    if (p->locallyblocked || p->remotelyblocked)
09096       return 0;
09097       
09098    /* If no owner definitely available */
09099    if (!p->owner) {
09100 #ifdef HAVE_PRI
09101       /* Trust PRI */
09102       if (p->pri) {
09103          if (p->resetting || p->call)
09104             return 0;
09105          else
09106             return 1;
09107       }
09108 #endif
09109 #ifdef HAVE_SS7
09110       /* Trust SS7 */
09111       if (p->ss7) {
09112          if (p->ss7call)
09113             return 0;
09114          else
09115             return 1;
09116       }
09117 #endif
09118       if (!(p->radio || (p->oprmode < 0)))
09119       {
09120          if (!p->sig || (p->sig == SIG_FXSLS))
09121             return 1;
09122          /* Check hook state */
09123          if (p->subs[SUB_REAL].dfd > -1) {
09124             memset(&par, 0, sizeof(par));
09125             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
09126          } else {
09127             /* Assume not off hook on CVRS */
09128             res = 0;
09129             par.rxisoffhook = 0;
09130          }
09131          if (res) {
09132             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
09133          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
09134             /* When "onhook" that means no battery on the line, and thus
09135               it is out of service..., if it's on a TDM card... If it's a channel
09136               bank, there is no telling... */
09137             if (par.rxbits > -1)
09138                return 1;
09139             if (par.rxisoffhook)
09140                return 1;
09141             else
09142                return 0;
09143          } else if (par.rxisoffhook) {
09144             ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
09145             /* Not available when the other end is off hook */
09146 #ifdef DAHDI_CHECK_HOOKSTATE
09147             return 0;
09148 #else
09149             return 1;
09150 #endif
09151          }
09152       }
09153       return 1;
09154    }
09155 
09156    /* If it's not an FXO, forget about call wait */
09157    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS)) 
09158       return 0;
09159 
09160    if (!p->callwaiting) {
09161       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
09162       return 0;
09163    }
09164 
09165    if (p->subs[SUB_CALLWAIT].dfd > -1) {
09166       /* If there is already a call waiting call, then we can't take a second one */
09167       return 0;
09168    }
09169    
09170    if ((p->owner->_state != AST_STATE_UP) &&
09171        ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
09172       /* If the current call is not up, then don't allow the call */
09173       return 0;
09174    }
09175    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
09176       /* Can't take a call wait when the three way calling hasn't been merged yet. */
09177       return 0;
09178    }
09179    /* We're cool */
09180    return 1;
09181 }

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

13853 {
13854    char *c, *chan;
13855    int x, start, finish;
13856    struct dahdi_pvt *tmp;
13857 #ifdef HAVE_PRI
13858    struct dahdi_pri *pri;
13859    int trunkgroup, y;
13860 #endif
13861    
13862    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
13863       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
13864       return -1;
13865    }
13866 
13867    c = ast_strdupa(value);
13868 
13869 #ifdef HAVE_PRI
13870    pri = NULL;
13871    if (iscrv) {
13872       if (sscanf(c, "%d:%n", &trunkgroup, &y) != 1) {
13873          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
13874          return -1;
13875       }
13876       if (trunkgroup < 1) {
13877          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
13878          return -1;
13879       }
13880       c += y;
13881       for (y = 0; y < NUM_SPANS; y++) {
13882          if (pris[y].trunkgroup == trunkgroup) {
13883             pri = pris + y;
13884             break;
13885          }
13886       }
13887       if (!pri) {
13888          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
13889          return -1;
13890       }
13891    }
13892 #endif         
13893 
13894    while ((chan = strsep(&c, ","))) {
13895       if (sscanf(chan, "%d-%d", &start, &finish) == 2) {
13896          /* Range */
13897       } else if (sscanf(chan, "%d", &start)) {
13898          /* Just one */
13899          finish = start;
13900       } else if (!strcasecmp(chan, "pseudo")) {
13901          finish = start = CHAN_PSEUDO;
13902          if (found_pseudo)
13903             *found_pseudo = 1;
13904       } else {
13905          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
13906          return -1;
13907       }
13908       if (finish < start) {
13909          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
13910          x = finish;
13911          finish = start;
13912          start = x;
13913       }
13914 
13915       for (x = start; x <= finish; x++) {
13916 #ifdef HAVE_PRI
13917          tmp = mkintf(x, conf, pri, reload);
13918 #else       
13919          tmp = mkintf(x, conf, NULL, reload);
13920 #endif         
13921 
13922          if (tmp) {
13923 #ifdef HAVE_PRI
13924                if (pri)
13925                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
13926                else
13927 #endif
13928                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
13929          } else {
13930             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
13931                (reload == 1) ? "reconfigure" : "register", value);
13932             return -1;
13933          }
13934       }
13935    }
13936 
13937    return 0;
13938 }

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

Definition at line 12067 of file chan_dahdi.c.

References DCHAN_NOTINALARM, and DCHAN_PROVISIONED.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

12068 {
12069    if (!s || len < 1) {
12070       return;
12071    }
12072    s[0] = '\0';
12073    if (status & DCHAN_PROVISIONED)
12074       strncat(s, "Provisioned, ", len - strlen(s) - 1);
12075    if (!(status & DCHAN_NOTINALARM))
12076       strncat(s, "In Alarm, ", len - strlen(s) - 1);
12077    if (status & DCHAN_UP)
12078       strncat(s, "Up", len - strlen(s) - 1);
12079    else
12080       strncat(s, "Down", len - strlen(s) - 1);
12081    if (active)
12082       strncat(s, ", Active", len - strlen(s) - 1);
12083    else
12084       strncat(s, ", Standby", len - strlen(s) - 1);
12085    s[len - 1] = '\0';
12086 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

02182 {
02183    int res;
02184 
02185    /* Bump receive gain by value stored in cid_rxgain */
02186    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02187    if (res) {
02188       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02189       return -1;
02190    }
02191 
02192    return 0;
02193 }

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

Definition at line 7717 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by mwi_thread().

07718 {
07719    int x;
07720    int sum = 0;
07721 
07722    if (!len)
07723       return 0;
07724 
07725    for (x = 0; x < len; x++)
07726       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07727 
07728    return sum / len;
07729 }

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

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

09184 {
09185    struct dahdi_pvt *p;
09186    struct dahdi_bufferinfo bi;
09187    int res;
09188    
09189    if ((p = ast_malloc(sizeof(*p)))) {
09190       memcpy(p, src, sizeof(struct dahdi_pvt));
09191       ast_mutex_init(&p->lock);
09192       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09193       /* Allocate a dahdi structure */
09194       if (p->subs[SUB_REAL].dfd < 0) {
09195          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09196          destroy_dahdi_pvt(&p);
09197          return NULL;
09198       }
09199       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09200       if (!res) {
09201          bi.txbufpolicy = src->buf_policy;
09202          bi.rxbufpolicy = src->buf_policy;
09203          bi.numbufs = src->buf_no;
09204          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09205          if (res < 0) {
09206             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09207          }
09208       } else
09209          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09210    }
09211    p->destroy = 1;
09212    p->next = iflist;
09213    p->prev = NULL;
09214    iflist = p;
09215    if (iflist->next)
09216       iflist->next->prev = p;
09217    return p;
09218 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

04550 {
04551    struct dahdi_confinfo ci;
04552    /* Fine if we already have a master, etc */
04553    if (p->master || (p->confno > -1))
04554       return 0;
04555    memset(&ci, 0, sizeof(ci));
04556    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
04557       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
04558       return 0;
04559    }
04560    /* If we have no master and don't have a confno, then 
04561       if we're in a conference, it's probably a MeetMe room or
04562       some such, so don't let us 3-way out! */
04563    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
04564       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
04565       return 1;
04566    }
04567    return 0;
04568 }

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

Definition at line 11892 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

11893 {
11894    return complete_span_helper(line,word,pos,state,3);
11895 }

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

Definition at line 11897 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_no_debug(), and handle_pri_really_debug().

11898 {
11899    return complete_span_helper(line,word,pos,state,4);
11900 }

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

Definition at line 11873 of file chan_dahdi.c.

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

Referenced by complete_span_4(), and complete_span_5().

11874 {
11875    int which, span;
11876    char *ret = NULL;
11877 
11878    if (pos != rpos)
11879       return ret;
11880 
11881    for (which = span = 0; span < NUM_SPANS; span++) {
11882       if (pris[span].pri && ++which > state) {
11883          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
11884             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
11885          }
11886          break;
11887       }
11888    }
11889    return ret;
11890 }

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

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

01824 {
01825    /* If the conference already exists, and we're already in it
01826       don't bother doing anything */
01827    struct dahdi_confinfo zi;
01828    
01829    memset(&zi, 0, sizeof(zi));
01830    zi.chan = 0;
01831 
01832    if (slavechannel > 0) {
01833       /* If we have only one slave, do a digital mon */
01834       zi.confmode = DAHDI_CONF_DIGITALMON;
01835       zi.confno = slavechannel;
01836    } else {
01837       if (!index) {
01838          /* Real-side and pseudo-side both participate in conference */
01839          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
01840             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
01841       } else
01842          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
01843       zi.confno = p->confno;
01844    }
01845    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
01846       return 0;
01847    if (c->dfd < 0)
01848       return 0;
01849    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01850       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
01851       return -1;
01852    }
01853    if (slavechannel < 1) {
01854       p->confno = zi.confno;
01855    }
01856    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01857    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01858    return 0;
01859 }

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

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

01873 {
01874    struct dahdi_confinfo zi;
01875    if (/* Can't delete if there's no dfd */
01876       (c->dfd < 0) ||
01877       /* Don't delete from the conference if it's not our conference */
01878       !isourconf(p, c)
01879       /* Don't delete if we don't think it's conferenced at all (implied) */
01880       ) return 0;
01881    memset(&zi, 0, sizeof(zi));
01882    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
01883       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
01884       return -1;
01885    }
01886    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
01887    memcpy(&c->curconf, &zi, sizeof(c->curconf));
01888    return 0;
01889 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

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

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 4145 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, 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().

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

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

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

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

02409 {
02410    struct dahdi_pvt *p = ast->tech_pvt;
02411    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
02412    if (p->cidspill) {
02413       ast_log(LOG_WARNING, "Spill already exists?!?\n");
02414       ast_free(p->cidspill);
02415    }
02416    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
02417       return -1;
02418    save_conference(p);
02419    /* Silence */
02420    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
02421    if (!p->callwaitrings && p->callwaitingcallerid) {
02422       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
02423       p->callwaitcas = 1;
02424       p->cidlen = 2400 + 680 + READ_SIZE * 4;
02425    } else {
02426       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
02427       p->callwaitcas = 0;
02428       p->cidlen = 2400 + READ_SIZE * 4;
02429    }
02430    p->cidpos = 0;
02431    send_callerid(p);
02432    
02433    return 0;
02434 }

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

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

static void dahdi_close ( int  fd  )  [static]

Definition at line 1484 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), and dahdi_close_sub().

01485 {
01486    if (fd > 0)
01487       close(fd);
01488 }

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

Definition at line 1497 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

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

01498 {
01499    dahdi_close(pri->fds[fd_num]);
01500    pri->fds[fd_num] = -1;
01501 }

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

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

01491 {
01492    dahdi_close(chan_pvt->subs[sub_num].dfd);
01493    chan_pvt->subs[sub_num].dfd = -1;
01494 }

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

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

02226 {
02227    int x, y, res;
02228    x = muted;
02229    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02230       y = 1;
02231       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02232       if (res)
02233          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02234    }
02235    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02236    if (res < 0)
02237       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02238    return res;
02239 }

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

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

12223 {
12224    int channel;
12225    int ret;
12226    switch (cmd) {
12227    case CLI_INIT:
12228       e->command = "dahdi destroy channel";
12229       e->usage = 
12230          "Usage: dahdi destroy channel <chan num>\n"
12231          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12232       return NULL;
12233    case CLI_GENERATE:
12234       return NULL;   
12235    }
12236    if (a->argc != 4)
12237       return CLI_SHOWUSAGE;
12238    
12239    channel = atoi(a->argv[3]);
12240    ret = dahdi_destroy_channel_bynum(channel);
12241    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12242 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

07864 {
07865    struct dahdi_pvt *tmp = NULL;
07866    struct dahdi_pvt *prev = NULL;
07867 
07868    tmp = iflist;
07869    while (tmp) {
07870       if (tmp->channel == channel) {
07871          int x = DAHDI_FLASH;
07872          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 */
07873          destroy_channel(prev, tmp, 1);
07874          ast_module_unref(ast_module_info->self);
07875          return RESULT_SUCCESS;
07876       }
07877       prev = tmp;
07878       tmp = tmp->next;
07879    }
07880    return RESULT_FAILURE;
07881 }

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

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

01593 {
01594    struct dahdi_pvt *pvt;
01595    int index;
01596    int dtmf = -1;
01597    
01598    pvt = chan->tech_pvt;
01599 
01600    ast_mutex_lock(&pvt->lock);
01601 
01602    index = dahdi_get_index(chan, pvt, 0);
01603 
01604    if ((index != SUB_REAL) || !pvt->owner)
01605       goto out;
01606 
01607 #ifdef HAVE_PRI
01608    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP)) 
01609          && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
01610       if (pvt->setup_ack) {
01611          if (!pri_grab(pvt, pvt->pri)) {
01612             pri_information(pvt->pri->pri, pvt->call, digit);
01613             pri_rel(pvt->pri);
01614          } else
01615             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
01616       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
01617          int res;
01618          ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
01619          res = strlen(pvt->dialdest);
01620          pvt->dialdest[res++] = digit;
01621          pvt->dialdest[res] = '\0';
01622       }
01623       goto out;
01624    }
01625 #endif
01626    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
01627       goto out;
01628 
01629    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
01630       int res;
01631       struct dahdi_dialoperation zo = {
01632          .op = DAHDI_DIAL_OP_APPEND,
01633       };
01634 
01635       zo.dialstr[0] = 'T';
01636       zo.dialstr[1] = digit;
01637       zo.dialstr[2] = '\0';
01638       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
01639          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
01640       else
01641          pvt->dialing = 1;
01642    } else {
01643       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
01644       pvt->dialing = 1;
01645       pvt->begindigit = digit;
01646    }
01647 
01648 out:
01649    ast_mutex_unlock(&pvt->lock);
01650 
01651    return 0;
01652 }

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

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

01655 {
01656    struct dahdi_pvt *pvt;
01657    int res = 0;
01658    int index;
01659    int x;
01660    
01661    pvt = chan->tech_pvt;
01662 
01663    ast_mutex_lock(&pvt->lock);
01664    
01665    index = dahdi_get_index(chan, pvt, 0);
01666 
01667    if ((index != SUB_REAL) || !pvt->owner || pvt->pulse)
01668       goto out;
01669 
01670 #ifdef HAVE_PRI
01671    /* This means that the digit was already sent via PRI signalling */
01672    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
01673          && !pvt->begindigit)
01674       goto out;
01675 #endif
01676 
01677    if (pvt->begindigit) {
01678       x = -1;
01679       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
01680       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
01681       pvt->dialing = 0;
01682       pvt->begindigit = 0;
01683    }
01684 
01685 out:
01686    ast_mutex_unlock(&pvt->lock);
01687 
01688    return res;
01689 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

02055 {
02056    int res;
02057 
02058    if (p->echocanon) {
02059       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02060 
02061       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02062 
02063       if (res)
02064          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02065       else
02066          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02067    }
02068 
02069    p->echocanon = 0;
02070 }

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

06509 {
06510    /* Do not disturb */
06511    dahdichan->dnd = on;
06512    ast_verb(3, "%s DND on channel %d\n", 
06513          on? "Enabled" : "Disabled",
06514          dahdichan->channel);
06515    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06516          "Channel: DAHDI/%d\r\n"
06517          "Status: %s\r\n", dahdichan->channel,
06518          on? "enabled" : "disabled");
06519 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

02006 {
02007    int x;
02008    int res;
02009    if (!p)
02010       return;
02011    if (p->echocanon) {
02012       ast_debug(1, "Echo cancellation already on\n");
02013       return;
02014    }
02015    if (p->digital) {
02016       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02017       return;
02018    }
02019    if (p->echocancel.head.tap_length) {
02020       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02021          x = 1;
02022          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02023          if (res)
02024             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02025       }
02026       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02027       if (res)  {
02028          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02029       } else {
02030          p->echocanon = 1;
02031          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02032       }
02033    } else
02034       ast_debug(1, "No echo cancellation requested\n");
02035 }

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

Definition at line 5637 of file chan_dahdi.c.

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

05638 {
05639    struct dahdi_pvt *p = ast->tech_pvt;
05640    struct ast_frame *f;
05641    ast_mutex_lock(&p->lock);
05642    f = __dahdi_exception(ast);
05643    ast_mutex_unlock(&p->lock);
05644    return f;
05645 }

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

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

13106 {
13107    if (p) {
13108       switch (mode) {
13109          case TRANSFER:
13110             p->fake_event = DAHDI_EVENT_WINKFLASH;
13111             break;
13112          case HANGUP:
13113             p->fake_event = DAHDI_EVENT_ONHOOK;
13114             break;
13115          default:
13116             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
13117       }
13118    }
13119    return 0;
13120 }

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

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

04442 {
04443    struct dahdi_pvt *p = newchan->tech_pvt;
04444    int x;
04445    ast_mutex_lock(&p->lock);
04446    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
04447    if (p->owner == oldchan) {
04448       p->owner = newchan;
04449    }
04450    for (x = 0; x < 3; x++)
04451       if (p->subs[x].owner == oldchan) {
04452          if (!x)
04453             dahdi_unlink(NULL, p, 0);
04454          p->subs[x].owner = newchan;
04455       }
04456    if (newchan->_state == AST_STATE_RINGING) 
04457       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
04458    update_conf(p);
04459    ast_mutex_unlock(&p->lock);
04460    return 0;
04461 }

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

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

04015 {
04016    struct dahdi_pvt *p = chan->tech_pvt;
04017    
04018    if (!strcasecmp(data, "rxgain")) {
04019       ast_mutex_lock(&p->lock);
04020       snprintf(buf, len, "%f", p->rxgain);
04021       ast_mutex_unlock(&p->lock);   
04022    } else if (!strcasecmp(data, "txgain")) {
04023       ast_mutex_lock(&p->lock);
04024       snprintf(buf, len, "%f", p->txgain);
04025       ast_mutex_unlock(&p->lock);   
04026    } else {
04027       ast_copy_string(buf, "", len);
04028    }
04029    return 0;
04030 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 297 of file chan_dahdi.c.

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

00298 {
00299    int j;
00300    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00301       return -1;
00302    return j;
00303 }

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

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

01299 {
01300    int res;
01301    if (p->subs[SUB_REAL].owner == ast)
01302       res = 0;
01303    else if (p->subs[SUB_CALLWAIT].owner == ast)
01304       res = 1;
01305    else if (p->subs[SUB_THREEWAY].owner == ast)
01306       res = 2;
01307    else {
01308       res = -1;
01309       if (!nullok)
01310          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01311    }
01312    return res;
01313 }

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

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

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

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

Definition at line 4693 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), ast_channel_lock, 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_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_PRERING, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_RINGING, AST_STATE_UP, ast_strdup, ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, attempt_transfer(), dahdi_pvt::bearer, dahdi_pvt::call, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, CANPROGRESSDETECT, chan, dahdi_pvt::channel, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_enable_ec(), dahdi_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, 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, 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().

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 3376 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_digitmode(), ast_dsp_free(), 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, 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().

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

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

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

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

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

Definition at line 4089 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, and master.

Referenced by dahdi_bridge().

04089                                                                           {
04090    int x;
04091    if (!slave || !master) {
04092       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
04093       return;
04094    }
04095    for (x = 0; x < MAX_SLAVES; x++) {
04096       if (!master->slaves[x]) {
04097          master->slaves[x] = slave;
04098          break;
04099       }
04100    }
04101    if (x >= MAX_SLAVES) {
04102       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
04103       master->slaves[MAX_SLAVES - 1] = slave;
04104    }
04105    if (slave->master) 
04106       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
04107    slave->master = master;
04108    
04109    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
04110 }

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

Definition at line 6268 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_device_state_changed_literal(), ast_dsp_digitmode(), ast_dsp_new(), ast_dsp_set_busy_compare(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_features(), ast_dsp_set_threshold(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), AST_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_DTMF_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, ast_variable::name, ast_channel::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, 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().

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1437 of file chan_dahdi.c.

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

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

01438 {
01439    int fd;
01440    int isnum;
01441    int chan = 0;
01442    int bs;
01443    int x;
01444    isnum = 1;
01445    for (x = 0; x < strlen(fn); x++) {
01446       if (!isdigit(fn[x])) {
01447          isnum = 0;
01448          break;
01449       }
01450    }
01451    if (isnum) {
01452       chan = atoi(fn);
01453       if (chan < 1) {
01454          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
01455          return -1;
01456       }
01457       fn = "/dev/dahdi/channel";
01458    }
01459    fd = open(fn, O_RDWR | O_NONBLOCK);
01460    if (fd < 0) {
01461       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
01462       return -1;
01463    }
01464    if (chan) {
01465       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
01466          x = errno;
01467          close(fd);
01468          errno = x;
01469          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
01470          return -1;
01471       }
01472    }
01473    bs = READ_SIZE;
01474    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
01475       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
01476       x = errno;
01477       close(fd);
01478       errno = x;
01479       return -1;
01480    }
01481    return fd;
01482 }

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

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

10537 {
10538    int x, y;
10539    int dchan = -1, span = -1;
10540    int dchancount = 0;
10541 
10542    if (pri) {
10543       for (x = 0; x < NUM_SPANS; x++) {
10544          for (y = 0; y < NUM_DCHANS; y++) {
10545             if (pris[x].dchans[y])
10546                dchancount++;
10547 
10548             if (pris[x].dchans[y] == pri)
10549                dchan = y;
10550          }
10551          if (dchan >= 0) {
10552             span = x;
10553             break;
10554          }
10555          dchancount = 0;
10556       }
10557       if ((dchancount > 1) && (span > -1))
10558          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10559       else
10560          ast_log(LOG_ERROR, "%s", s);
10561    } else
10562       ast_log(LOG_ERROR, "%s", s);
10563 
10564    ast_mutex_lock(&pridebugfdlock);
10565 
10566    if (pridebugfd >= 0) {
10567       if (write(pridebugfd, s, strlen(s)) < 0) {
10568          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10569       }
10570    }
10571 
10572    ast_mutex_unlock(&pridebugfdlock);
10573 }

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

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

10498 {
10499    int x, y;
10500    int dchan = -1, span = -1;
10501    int dchancount = 0;
10502 
10503    if (pri) {
10504       for (x = 0; x < NUM_SPANS; x++) {
10505          for (y = 0; y < NUM_DCHANS; y++) {
10506             if (pris[x].dchans[y])
10507                dchancount++;
10508 
10509             if (pris[x].dchans[y] == pri)
10510                dchan = y;
10511          }
10512          if (dchan >= 0) {
10513             span = x;
10514             break;
10515          }
10516          dchancount = 0;
10517       }
10518       if (dchancount > 1 && (span > -1))
10519          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10520       else
10521          ast_verbose("%s", s);
10522    } else
10523       ast_verbose("%s", s);
10524 
10525    ast_mutex_lock(&pridebugfdlock);
10526 
10527    if (pridebugfd >= 0) {
10528       if (write(pridebugfd, s, strlen(s)) < 0) {
10529          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10530       }
10531    }
10532 
10533    ast_mutex_unlock(&pridebugfdlock);
10534 }

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

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

01344 {
01345 #ifdef HAVE_PRI
01346    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01347 #endif
01348 #ifdef HAVE_SS7
01349    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01350 #endif
01351    /* We must unlock the PRI to avoid the possibility of a deadlock */
01352 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01353    if (data) {
01354       switch (p->sig) {
01355 #ifdef HAVE_PRI
01356       case SIG_BRI:
01357       case SIG_BRI_PTMP:
01358       case SIG_PRI:
01359          ast_mutex_unlock(&pri->lock);
01360          break;
01361 #endif
01362 #ifdef HAVE_SS7
01363       case SIG_SS7:
01364          ast_mutex_unlock(&ss7->lock);
01365          break;
01366 #endif
01367       default:
01368          break;
01369       }
01370    }
01371 #endif      
01372    for (;;) {
01373       if (p->owner) {
01374          if (ast_channel_trylock(p->owner)) {
01375             DEADLOCK_AVOIDANCE(&p->lock);
01376          } else {
01377             ast_queue_frame(p->owner, f);
01378             ast_channel_unlock(p->owner);
01379             break;
01380          }
01381       } else
01382          break;
01383    }
01384 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01385    if (data) {
01386       switch (p->sig) {
01387 #ifdef HAVE_PRI
01388       case SIG_BRI:
01389       case SIG_BRI_PTMP:
01390       case SIG_PRI:
01391          ast_mutex_lock(&pri->lock);
01392          break;
01393 #endif
01394 #ifdef HAVE_SS7
01395       case SIG_SS7:
01396          ast_mutex_lock(&ss7->lock);
01397          break;
01398 #endif
01399       default:
01400          break;
01401       }
01402    }
01403 
01404 #endif      
01405 }

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

Definition at line 5647 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_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_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, 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, 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.

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

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

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

09249 {
09250    ast_group_t groupmatch = 0;
09251    int channelmatch = -1;
09252    int roundrobin = 0;
09253    int callwait = 0;
09254    int busy = 0;
09255    struct dahdi_pvt *p;
09256    struct ast_channel *tmp = NULL;
09257    char *dest=NULL;
09258    int x;
09259    char *s;
09260    char opt=0;
09261    int res=0, y=0;
09262    int backwards = 0;
09263 #ifdef HAVE_PRI
09264    int crv;
09265    int bearer = -1;
09266    int trunkgroup;
09267    struct dahdi_pri *pri=NULL;
09268 #endif   
09269    struct dahdi_pvt *exit, *start, *end;
09270    ast_mutex_t *lock;
09271    int channelmatched = 0;
09272    int groupmatched = 0;
09273    
09274    /*
09275     * data is ---v
09276     * Dial(DAHDI/pseudo[/extension])
09277     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
09278     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
09279     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
09280     *
09281     * g - channel group allocation search forward
09282     * G - channel group allocation search backward
09283     * r - channel group allocation round robin search forward
09284     * R - channel group allocation round robin search backward
09285     *
09286     * c - Wait for DTMF digit to confirm answer
09287     * r<cadance#> - Set distintive ring cadance number
09288     * d - Force bearer capability for ISDN/SS7 call to digital.
09289     */
09290 
09291    /* Assume we're locking the iflock */
09292    lock = &iflock;
09293    start = iflist;
09294    end = ifend;
09295    if (data) {
09296       dest = ast_strdupa((char *)data);
09297    } else {
09298       ast_log(LOG_WARNING, "Channel requested with no data\n");
09299       return NULL;
09300    }
09301    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
09302       /* Retrieve the group number */
09303       char *stringp;
09304 
09305       stringp = dest + 1;
09306       s = strsep(&stringp, "/");
09307       if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09308          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
09309          return NULL;
09310       }
09311       groupmatch = ((ast_group_t) 1 << x);
09312       if (toupper(dest[0]) == 'G') {
09313          if (dest[0] == 'G') {
09314             backwards = 1;
09315             p = ifend;
09316          } else
09317             p = iflist;
09318       } else {
09319          if (dest[0] == 'R') {
09320             backwards = 1;
09321             p = round_robin[x]?round_robin[x]->prev:ifend;
09322             if (!p)
09323                p = ifend;
09324          } else {
09325             p = round_robin[x]?round_robin[x]->next:iflist;
09326             if (!p)
09327                p = iflist;
09328          }
09329          roundrobin = 1;
09330       }
09331    } else {
09332       char *stringp;
09333 
09334       stringp = dest;
09335       s = strsep(&stringp, "/");
09336       p = iflist;
09337       if (!strcasecmp(s, "pseudo")) {
09338          /* Special case for pseudo */
09339          x = CHAN_PSEUDO;
09340          channelmatch = x;
09341       } 
09342 #ifdef HAVE_PRI
09343       else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
09344          if ((trunkgroup < 1) || (crv < 1)) {
09345             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
09346             return NULL;
09347          }
09348          res--;
09349          for (x = 0; x < NUM_SPANS; x++) {
09350             if (pris[x].trunkgroup == trunkgroup) {
09351                pri = pris + x;
09352                lock = &pri->lock;
09353                start = pri->crvs;
09354                end = pri->crvend;
09355                break;
09356             }
09357          }
09358          if (!pri) {
09359             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
09360             return NULL;
09361          }
09362          channelmatch = crv;
09363          p = pris[x].crvs;
09364       }
09365 #endif   
09366       else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
09367          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
09368          return NULL;
09369       } else {
09370          channelmatch = x;
09371       }
09372    }
09373    /* Search for an unowned channel */
09374    ast_mutex_lock(lock);
09375    exit = p;
09376    while (p && !tmp) {
09377       if (roundrobin)
09378          round_robin[x] = p;
09379 #if 0
09380       ast_verbose("name = %s, %d, %d, %d\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
09381 #endif
09382 
09383       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
09384          ast_debug(1, "Using channel %d\n", p->channel);
09385          if (p->inalarm) 
09386             goto next;
09387 
09388          callwait = (p->owner != NULL);
09389 #ifdef HAVE_PRI
09390          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
09391             if (p->sig != SIG_FXSKS) {
09392                /* Gotta find an actual channel to use for this
09393                   CRV if this isn't a callwait */
09394                bearer = pri_find_empty_chan(pri, 0);
09395                if (bearer < 0) {
09396                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
09397                   p = NULL;
09398                   break;
09399                }
09400                pri_assign_bearer(p, pri, pri->pvts[bearer]);
09401             } else {
09402                if (alloc_sub(p, 0)) {
09403                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
09404                   p = NULL;
09405                   break;
09406                } else
09407                   ast_debug(1, "Allocated placeholder pseudo channel\n");
09408 
09409                p->pri = pri;
09410             }
09411          }
09412 #endif         
09413          if (p->channel == CHAN_PSEUDO) {
09414             p = chandup(p);
09415             if (!p) {
09416                break;
09417             }
09418          }
09419          if (p->owner) {
09420             if (alloc_sub(p, SUB_CALLWAIT)) {
09421                p = NULL;
09422                break;
09423             }
09424          }
09425          p->outgoing = 1;
09426          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
09427 #ifdef HAVE_PRI
09428          if (p->bearer) {
09429             /* Log owner to bearer channel, too */
09430             p->bearer->owner = tmp;
09431          }
09432 #endif         
09433          /* Make special notes */
09434          if (res > 1) {
09435             if (opt == 'c') {
09436                /* Confirm answer */
09437                p->confirmanswer = 1;
09438             } else if (opt == 'r') {
09439                /* Distinctive ring */
09440                if (res < 3)
09441                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
09442                else
09443                   p->distinctivering = y;
09444             } else if (opt == 'd') {
09445                /* If this is an ISDN call, make it digital */
09446                p->digital = 1;
09447                if (tmp)
09448                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
09449             } else {
09450                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
09451             }
09452          }
09453          /* Note if the call is a call waiting call */
09454          if (tmp && callwait)
09455             tmp->cdrflags |= AST_CDR_CALLWAIT;
09456          break;
09457       }
09458 next:
09459       if (backwards) {
09460          p = p->prev;
09461          if (!p)
09462             p = end;
09463       } else {
09464          p = p->next;
09465          if (!p)
09466             p = start;
09467       }
09468       /* stop when you roll to the one that we started from */
09469       if (p == exit)
09470          break;
09471    }
09472    ast_mutex_unlock(lock);
09473    restart_monitor();
09474    if (callwait)
09475       *cause = AST_CAUSE_BUSY;
09476    else if (!tmp) {
09477       if (channelmatched) {
09478          if (busy)
09479             *cause = AST_CAUSE_BUSY;
09480       } else if (groupmatched) {
09481          *cause = AST_CAUSE_CONGESTION;
09482       }
09483    }
09484       
09485    return tmp;
09486 }

static int dahdi_restart ( void   )  [static]

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

12274 {
12275 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12276    int i, j;
12277 #endif
12278    int cancel_code;
12279    struct dahdi_pvt *p;
12280 
12281    ast_mutex_lock(&restart_lock);
12282 
12283    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12284    dahdi_softhangup_all();
12285    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12286 
12287 #if defined(HAVE_PRI)
12288    for (i = 0; i < NUM_SPANS; i++) {
12289       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12290          cancel_code = pthread_cancel(pris[i].master);
12291          pthread_kill(pris[i].master, SIGURG);
12292          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12293          pthread_join(pris[i].master, NULL);
12294          ast_debug(4, "Joined thread of span %d\n", i);
12295       }
12296    }
12297 #endif
12298 
12299 #if defined(HAVE_SS7)
12300    for (i = 0; i < NUM_SPANS; i++) {
12301       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12302          cancel_code = pthread_cancel(linksets[i].master);
12303          pthread_kill(linksets[i].master, SIGURG);
12304          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12305          pthread_join(linksets[i].master, NULL);
12306          ast_debug(4, "Joined thread of span %d\n", i);
12307       }
12308     }
12309 #endif
12310 
12311    ast_mutex_lock(&monlock);
12312    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12313       cancel_code = pthread_cancel(monitor_thread);
12314       pthread_kill(monitor_thread, SIGURG);
12315       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12316       pthread_join(monitor_thread, NULL);
12317       ast_debug(4, "Joined monitor thread\n");
12318    }
12319    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12320 
12321    ast_mutex_lock(&ss_thread_lock);
12322    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12323       int x = DAHDI_FLASH;
12324       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12325 
12326       for (p = iflist; p; p = p->next) {
12327          if (p->owner)
12328             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 */      
12329          }
12330          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12331       }
12332 
12333    /* ensure any created channels before monitor threads were stopped are hungup */
12334    dahdi_softhangup_all();
12335    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12336    destroy_all_channels();
12337    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12338 
12339    ast_mutex_unlock(&monlock);
12340 
12341 #ifdef HAVE_PRI
12342    for (i = 0; i < NUM_SPANS; i++) {
12343       for (j = 0; j < NUM_DCHANS; j++)
12344          dahdi_close_pri_fd(&(pris[i]), j);
12345    }
12346 
12347    memset(pris, 0, sizeof(pris));
12348    for (i = 0; i < NUM_SPANS; i++) {
12349       ast_mutex_init(&pris[i].lock);
12350       pris[i].offset = -1;
12351       pris[i].master = AST_PTHREADT_NULL;
12352       for (j = 0; j < NUM_DCHANS; j++)
12353          pris[i].fds[j] = -1;
12354       }
12355    pri_set_error(dahdi_pri_error);
12356    pri_set_message(dahdi_pri_message);
12357 #endif
12358 #ifdef HAVE_SS7
12359    for (i = 0; i < NUM_SPANS; i++) {
12360       for (j = 0; j < NUM_DCHANS; j++)
12361          dahdi_close_ss7_fd(&(linksets[i]), j);
12362    }
12363 
12364    memset(linksets, 0, sizeof(linksets));
12365    for (i = 0; i < NUM_SPANS; i++) {
12366       ast_mutex_init(&linksets[i].lock);
12367       linksets[i].master = AST_PTHREADT_NULL;
12368       for (j = 0; j < NUM_DCHANS; j++)
12369          linksets[i].fds[j] = -1;
12370    }
12371    ss7_set_error(dahdi_ss7_error);
12372    ss7_set_message(dahdi_ss7_message);
12373 #endif
12374 
12375    if (setup_dahdi(2) != 0) {
12376       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12377       ast_mutex_unlock(&ss_thread_lock);
12378       return 1;
12379    }
12380    ast_mutex_unlock(&ss_thread_lock);
12381    ast_mutex_unlock(&restart_lock);
12382    return 0;
12383 }

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

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

12386 {
12387    switch (cmd) {
12388    case CLI_INIT:
12389       e->command = "dahdi restart";
12390       e->usage = 
12391          "Usage: dahdi restart\n"
12392          "  Restarts the DAHDI channels: destroys them all and then\n"
12393          "  re-reads them from chan_dahdi.conf.\n"
12394          "  Note that this will STOP any running CALL on DAHDI channels.\n"
12395          "";
12396       return NULL;
12397    case CLI_GENERATE:
12398       return NULL;
12399    }
12400    if (a->argc != 2)
12401       return CLI_SHOWUSAGE;
12402 
12403    if (dahdi_restart() != 0)
12404       return CLI_FAILURE;
12405    return CLI_SUCCESS;
12406 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 4463 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), and dahdi_handle_event().

04464 {
04465    int x;
04466    int res;
04467    /* Make sure our transmit state is on hook */
04468    x = 0;
04469    x = DAHDI_ONHOOK;
04470    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04471    do {
04472       x = DAHDI_RING;
04473       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
04474       if (res) {
04475          switch (errno) {
04476          case EBUSY:
04477          case EINTR:
04478             /* Wait just in case */
04479             usleep(10000);
04480             continue;
04481          case EINPROGRESS:
04482             res = 0;
04483             break;
04484          default:
04485             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
04486             res = 0;
04487          }
04488       }
04489    } while (res);
04490    return res;
04491 }

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

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

03258 {
03259    /* Data will be our digit string */
03260    struct dahdi_pvt *p;
03261    char *digits = (char *) data;
03262 
03263    if (ast_strlen_zero(digits)) {
03264       ast_debug(1, "No digit string sent to application!\n");
03265       return -1;
03266    }
03267 
03268    p = (struct dahdi_pvt *)chan->tech_pvt;
03269 
03270    if (!p) {
03271       ast_debug(1, "Unable to find technology private\n");
03272       return -1;
03273    }
03274 
03275    ast_mutex_lock(&p->lock);
03276 
03277    if (!p->pri || !p->call) {
03278       ast_debug(1, "Unable to find pri or call on channel!\n");
03279       ast_mutex_unlock(&p->lock);
03280       return -1;
03281    }
03282 
03283    if (!pri_grab(p, p->pri)) {
03284       pri_keypad_facility(p->pri->pri, p->call, digits);
03285       pri_rel(p->pri);
03286    } else {
03287       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03288       ast_mutex_unlock(&p->lock);
03289       return -1;
03290    }
03291 
03292    ast_mutex_unlock(&p->lock);
03293 
03294    return 0;
03295 }

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

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

15044 {
15045 #define  END_SILENCE_LEN 400
15046 #define  HEADER_MS 50
15047 #define  TRAILER_MS 5
15048 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15049 #define  ASCII_BYTES_PER_CHAR 80
15050 
15051    unsigned char *buf,*mybuf;
15052    struct dahdi_pvt *p = c->tech_pvt;
15053    struct pollfd fds[1];
15054    int size,res,fd,len,x;
15055    int bytes=0;
15056    /* Initial carrier (imaginary) */
15057    float cr = 1.0;
15058    float ci = 0.0;
15059    float scont = 0.0;
15060    int index;
15061 
15062    index = dahdi_get_index(c, p, 0);
15063    if (index < 0) {
15064       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
15065       return -1;
15066    }
15067    if (!text[0]) return(0); /* if nothing to send, dont */
15068    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
15069    if (p->mate) 
15070       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15071    else
15072       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15073    if (!buf)
15074       return -1;
15075    mybuf = buf;
15076    if (p->mate) {
15077       int codec = AST_LAW(p);
15078       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
15079          PUT_CLID_MARKMS;
15080       }
15081       /* Put actual message */
15082       for (x = 0; text[x]; x++) {
15083          PUT_CLID(text[x]);
15084       }
15085       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
15086          PUT_CLID_MARKMS;
15087       }
15088       len = bytes;
15089       buf = mybuf;
15090    } else {
15091       len = tdd_generate(p->tdd, buf, text);
15092       if (len < 1) {
15093          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15094          ast_free(mybuf);
15095          return -1;
15096       }
15097    }
15098    memset(buf + len, 0x7f, END_SILENCE_LEN);
15099    len += END_SILENCE_LEN;
15100    fd = p->subs[index].dfd;
15101    while (len) {
15102       if (ast_check_hangup(c)) {
15103          ast_free(mybuf);
15104          return -1;
15105       }
15106       size = len;
15107       if (size > READ_SIZE)
15108          size = READ_SIZE;
15109       fds[0].fd = fd;
15110       fds[0].events = POLLOUT | POLLPRI;
15111       fds[0].revents = 0;
15112       res = poll(fds, 1, -1);
15113       if (!res) {
15114          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15115          continue;
15116       }
15117         /* if got exception */
15118       if (fds[0].revents & POLLPRI) {
15119          ast_free(mybuf);
15120          return -1;
15121       }
15122       if (!(fds[0].revents & POLLOUT)) {
15123          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15124          continue;
15125       }
15126       res = write(fd, buf, size);
15127       if (res != size) {
15128          if (res == -1) {
15129             ast_free(mybuf);
15130             return -1;
15131          }
15132          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15133          break;
15134       }
15135       len -= size;
15136       buf += size;
15137    }
15138    ast_free(mybuf);
15139    return(0);
15140 }

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

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

13033 {
13034    int channel;
13035    int on;
13036    struct dahdi_pvt *dahdi_chan = NULL;
13037 
13038    switch (cmd) {
13039    case CLI_INIT:
13040       e->command = "dahdi set dnd";
13041       e->usage = 
13042          "Usage: dahdi set dnd <chan#> <on|off>\n"
13043          "   Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13044          "   Changes take effect immediately.\n"
13045          "   <chan num> is the channel number\n"
13046          "   <on|off> Enable or disable DND mode?\n"
13047          ;
13048       return NULL;
13049    case CLI_GENERATE:
13050       return NULL;   
13051    }
13052 
13053    if (a->argc != 5)
13054       return CLI_SHOWUSAGE;
13055 
13056    if ((channel = atoi(a->argv[3])) <= 0) {
13057       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13058       return CLI_SHOWUSAGE;
13059    }
13060    
13061    if (ast_true(a->argv[4]))
13062       on = 1;
13063    else if (ast_false(a->argv[4]))
13064       on = 0;
13065    else {
13066       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13067       return CLI_SHOWUSAGE;
13068    }
13069 
13070    ast_mutex_lock(&iflock);
13071    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13072       if (dahdi_chan->channel != channel)
13073          continue;
13074 
13075       /* Found the channel. Actually set it */
13076       dahdi_dnd(dahdi_chan, on);
13077       break;
13078    }
13079    ast_mutex_unlock(&iflock);
13080 
13081    if (!dahdi_chan) {
13082       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13083       return CLI_FAILURE;
13084    }
13085 
13086    return CLI_SUCCESS;
13087 }

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

Definition at line 2208 of file chan_dahdi.c.

References ast_log(), errno, and LOG_WARNING.

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

02209 {
02210    int x, res;
02211 
02212    x = hs;
02213    res = ioctl(fd, DAHDI_HOOK, &x);
02214 
02215    if (res < 0) {
02216       if (errno == EINPROGRESS)
02217          return 0;
02218       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02219       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02220    }
02221 
02222    return res;
02223 }

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

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

12890 {
12891    int channel;
12892    int gain;
12893    int tx;
12894    struct dahdi_hwgain hwgain;
12895    struct dahdi_pvt *tmp = NULL;
12896 
12897    switch (cmd) {
12898    case CLI_INIT:
12899       e->command = "dahdi set hwgain";
12900       e->usage = 
12901          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
12902          "  Sets the hardware gain on a a given channel, overriding the\n"
12903          "   value provided at module loadtime, whether the channel is in\n"
12904          "   use or not.  Changes take effect immediately.\n"
12905          "   <rx|tx> which direction do you want to change (relative to our module)\n"
12906          "   <chan num> is the channel number relative to the device\n"
12907          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12908       return NULL;
12909    case CLI_GENERATE:
12910       return NULL;   
12911    }
12912 
12913    if (a->argc != 6)
12914       return CLI_SHOWUSAGE;
12915    
12916    if (!strcasecmp("rx", a->argv[3]))
12917       tx = 0; /* rx */
12918    else if (!strcasecmp("tx", a->argv[3]))
12919       tx = 1; /* tx */
12920    else
12921       return CLI_SHOWUSAGE;
12922 
12923    channel = atoi(a->argv[4]);
12924    gain = atof(a->argv[5])*10.0;
12925 
12926    ast_mutex_lock(&iflock);
12927 
12928    for (tmp = iflist; tmp; tmp = tmp->next) {
12929 
12930       if (tmp->channel != channel)
12931          continue;
12932 
12933       if (tmp->subs[SUB_REAL].dfd == -1)
12934          break;
12935 
12936       hwgain.newgain = gain;
12937       hwgain.tx = tx;
12938       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
12939          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
12940          ast_mutex_unlock(&iflock);
12941          return CLI_FAILURE;
12942       }
12943       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
12944          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
12945       break;
12946    }
12947 
12948    ast_mutex_unlock(&iflock);
12949 
12950    if (tmp)
12951       return CLI_SUCCESS;
12952 
12953    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12954    return CLI_FAILURE;
12955 
12956 }

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

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

12959 {
12960    int channel;
12961    float gain;
12962    int tx;
12963    int res;
12964    ast_mutex_t *lock;
12965    struct dahdi_pvt *tmp = NULL;
12966 
12967    switch (cmd) {
12968    case CLI_INIT:
12969       e->command = "dahdi set swgain";
12970       e->usage = 
12971          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
12972          "  Sets the software gain on a a given channel, overriding the\n"
12973          "   value provided at module loadtime, whether the channel is in\n"
12974          "   use or not.  Changes take effect immediately.\n"
12975          "   <rx|tx> which direction do you want to change (relative to our module)\n"
12976          "   <chan num> is the channel number relative to the device\n"
12977          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
12978       return NULL;
12979    case CLI_GENERATE:
12980       return NULL;   
12981    }
12982 
12983    lock = &iflock;
12984 
12985    if (a->argc != 6)
12986       return CLI_SHOWUSAGE;
12987    
12988    if (!strcasecmp("rx", a->argv[3]))
12989       tx = 0; /* rx */
12990    else if (!strcasecmp("tx", a->argv[3]))
12991       tx = 1; /* tx */
12992    else
12993       return CLI_SHOWUSAGE;
12994 
12995    channel = atoi(a->argv[4]);
12996    gain = atof(a->argv[5]);
12997 
12998    ast_mutex_lock(lock);
12999    for (tmp = iflist; tmp; tmp = tmp->next) {
13000 
13001       if (tmp->channel != channel)
13002          continue;
13003 
13004       if (tmp->subs[SUB_REAL].dfd == -1)
13005          break;
13006 
13007       if (tx)
13008          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13009       else
13010          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13011 
13012       if (res) {
13013          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13014          ast_mutex_unlock(lock);
13015          return CLI_FAILURE;
13016       }
13017 
13018       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13019          tx ? "tx" : "rx", gain, channel);
13020       break;
13021    }
13022    ast_mutex_unlock(lock);
13023 
13024    if (tmp)
13025       return CLI_SUCCESS;
13026 
13027    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13028    return CLI_FAILURE;
13029 
13030 }

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

Definition at line 9489 of file chan_dahdi.c.

09490 {
09491    return ioctl(dfd, DAHDI_SETLAW, &law);
09492 }

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

Definition at line 1512 of file chan_dahdi.c.

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

01513 {
01514    int res;
01515    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
01516    if (res)
01517       return res;
01518    return 0;
01519 }

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

Definition at line 3833 of file chan_dahdi.c.

References ast_check_hangup(), ast_debug, ast_dsp_digitmode(), ast_log(), AST_OPTION_AUDIO_MODE, AST_OPTION_ECHOCAN, AST_OPTION_OPRMODE, AST_OPTION_RELAXDTMF, AST_OPTION_RXGAIN, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, AST_OPTION_TXGAIN, ast_tdd_gen_ecdisa(), 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.

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

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

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

12543 {
12544    int channel;
12545    struct dahdi_pvt *tmp = NULL;
12546    struct dahdi_confinfo ci;
12547    struct dahdi_params ps;
12548    int x;
12549    ast_mutex_t *lock;
12550    struct dahdi_pvt *start;
12551 #ifdef HAVE_PRI
12552    char *c;
12553    int trunkgroup;
12554    struct dahdi_pri *pri=NULL;
12555 #endif
12556    switch (cmd) {
12557    case CLI_INIT:
12558       e->command = "dahdi show channel";
12559       e->usage = 
12560          "Usage: dahdi show channel <chan num>\n"
12561          "  Detailed information about a given channel\n";
12562       return NULL;
12563    case CLI_GENERATE:
12564       return NULL;   
12565    }
12566 
12567    lock = &iflock;
12568    start = iflist;
12569 
12570    if (a->argc != 4)
12571       return CLI_SHOWUSAGE;
12572 #ifdef HAVE_PRI
12573    if ((c = strchr(a->argv[3], ':'))) {
12574       if (sscanf(a->argv[3], "%d:%d", &trunkgroup, &channel) != 2)
12575          return CLI_SHOWUSAGE;
12576       if ((trunkgroup < 1) || (channel < 1))
12577          return CLI_SHOWUSAGE;
12578       for (x = 0; x < NUM_SPANS; x++) {
12579          if (pris[x].trunkgroup == trunkgroup) {
12580             pri = pris + x;
12581             break;
12582          }
12583       }
12584       if (pri) {
12585          start = pri->crvs;
12586          lock = &pri->lock;
12587       } else {
12588          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12589          return CLI_FAILURE;
12590       }
12591    } else
12592 #endif
12593       channel = atoi(a->argv[3]);
12594 
12595    ast_mutex_lock(lock);
12596    tmp = start;
12597    while (tmp) {
12598       if (tmp->channel == channel) {
12599 #ifdef HAVE_PRI
12600          if (pri) 
12601             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12602          else
12603 #endif         
12604          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12605          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12606          ast_cli(a->fd, "Span: %d\n", tmp->span);
12607          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12608          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12609          ast_cli(a->fd, "Context: %s\n", tmp->context);
12610          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12611          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12612          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12613          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12614          if (tmp->vars) {
12615             struct ast_variable *v;
12616             ast_cli(a->fd, "Variables:\n");
12617             for (v = tmp->vars ; v ; v = v->next)
12618                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
12619          }
12620          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12621          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12622          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12623          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12624          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12625          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)" : "");
12626          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)" : "");
12627          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)" : "");
12628          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12629          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12630          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12631          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12632          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12633          if (tmp->busydetect) {
12634 #if defined(BUSYDETECT_TONEONLY)
12635             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12636 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12637             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12638 #endif
12639 #ifdef BUSYDETECT_DEBUG
12640             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
12641 #endif
12642             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
12643             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busytonelength, tmp->busyquietlength);
12644          }
12645          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12646          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12647          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12648          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12649          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12650          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12651          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12652          ast_cli(a->fd, "Echo Cancellation:\n");
12653          if (tmp->echocancel.head.tap_length) {
12654             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12655             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12656                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12657             }
12658             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12659          } else {
12660             ast_cli(a->fd, "\tnone\n");
12661          }
12662          if (tmp->master)
12663             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12664          for (x = 0; x < MAX_SLAVES; x++) {
12665             if (tmp->slaves[x])
12666                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12667          }
12668 #ifdef HAVE_SS7
12669          if (tmp->ss7) {
12670             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12671          }
12672 #endif
12673 #ifdef HAVE_PRI
12674          if (tmp->pri) {
12675             ast_cli(a->fd, "PRI Flags: ");
12676             if (tmp->resetting)
12677                ast_cli(a->fd, "Resetting ");
12678             if (tmp->call)
12679                ast_cli(a->fd, "Call ");
12680             if (tmp->bearer)
12681                ast_cli(a->fd, "Bearer ");
12682             ast_cli(a->fd, "\n");
12683             if (tmp->logicalspan) 
12684                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12685             else
12686                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12687          }
12688             
12689 #endif
12690          memset(&ci, 0, sizeof(ci));
12691          ps.channo = tmp->channel;
12692          if (tmp->subs[SUB_REAL].dfd > -1) {
12693             memset(&ci, 0, sizeof(ci));
12694             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12695                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12696             }
12697             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12698                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12699             }
12700             memset(&ps, 0, sizeof(ps));
12701             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12702                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12703             } else {
12704                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12705             }
12706          }
12707          if (ISTRUNK(tmp)) {
12708             ast_cli(a->fd, "Call Progress: %s\n", tmp->callprogress ? "yes" : "no");  
12709             if (!ast_strlen_zero(progzone))
12710                ast_cli(a->fd, "Progress Zone: %s\n", progzone);
12711             ast_cli(a->fd, "Busy Detect: %s\n", tmp->busydetect ? "yes" : "no");  
12712             if(tmp->busydetect) {
12713                ast_cli(a->fd, "Busy Count: %d\n", tmp->busycount);
12714                if(tmp->busytonelength > 0) {
12715                   ast_cli(a->fd, "Busy Pattern:\n");
12716                   ast_cli(a->fd, " -- Tone Length: %6d ms\n", tmp->busytonelength);
12717                   if (tmp->busyquietlength > 0) 
12718                      ast_cli(a->fd, " -- Quiet Length: %6d ms\n", tmp->busyquietlength);
12719                   else 
12720                      ast_cli(a->fd, " -- Detect Tone Only\n");
12721                   if(tmp->busyfuzziness > 0)
12722                      ast_cli(a->fd, "Busy Pattern Fuziness: %d\n", tmp->busyfuzziness);
12723                }
12724             }
12725          }
12726          ast_mutex_unlock(lock);
12727          return CLI_SUCCESS;
12728       }
12729       tmp = tmp->next;
12730    }
12731    
12732    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12733    ast_mutex_unlock(lock);
12734    return CLI_FAILURE;
12735 }

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

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

12419 {
12420 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12421 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12422    unsigned int targetnum = 0;
12423    int filtertype = 0;
12424    struct dahdi_pvt *tmp = NULL;
12425    char tmps[20] = "";
12426    char statestr[20] = "";
12427    char blockstr[20] = "";
12428    ast_mutex_t *lock;
12429    struct dahdi_pvt *start;
12430 #ifdef HAVE_PRI
12431    int trunkgroup;
12432    struct dahdi_pri *pri = NULL;
12433    int x;
12434 #endif
12435    switch (cmd) {
12436    case CLI_INIT:
12437       e->command = "dahdi show channels [trunkgroup|group|context]";
12438       e->usage = 
12439          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12440          "  Shows a list of available channels with optional filtering\n"
12441          "  <group> must be a number between 0 and 63\n";
12442       return NULL;
12443    case CLI_GENERATE:
12444       return NULL;   
12445    }
12446 
12447    lock = &iflock;
12448    start = iflist;
12449 
12450    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12451 
12452    if (!((a->argc == 3) || (a->argc == 5)))
12453       return CLI_SHOWUSAGE;
12454 
12455    if (a->argc == 5) {
12456 #ifdef HAVE_PRI
12457       if (!strcasecmp(a->argv[3], "trunkgroup")) {
12458          /* this option requires no special handling, so leave filtertype to zero */
12459          if ((trunkgroup = atoi(a->argv[4])) < 1)
12460             return CLI_SHOWUSAGE;
12461          for (x = 0; x < NUM_SPANS; x++) {
12462             if (pris[x].trunkgroup == trunkgroup) {
12463                pri = pris + x;
12464                break;
12465             }
12466          }
12467          if (pri) {
12468             start = pri->crvs;
12469             lock = &pri->lock;
12470          } else {
12471             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12472             return CLI_FAILURE;
12473          }
12474       } else
12475 #endif   
12476       if (!strcasecmp(a->argv[3], "group")) {
12477          targetnum = atoi(a->argv[4]);
12478          if ((targetnum < 0) || (targetnum > 63))
12479             return CLI_SHOWUSAGE;
12480          targetnum = 1 << targetnum;
12481          filtertype = 1;
12482       } else if (!strcasecmp(a->argv[3], "context")) {
12483          filtertype = 2;
12484       }
12485    }
12486 
12487    ast_mutex_lock(lock);
12488 #ifdef HAVE_PRI
12489    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12490 #else
12491    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12492 #endif   
12493    
12494    tmp = start;
12495    while (tmp) {
12496       if (filtertype) {
12497          switch(filtertype) {
12498          case 1: /* dahdi show channels group <group> */
12499             if (!(tmp->group & targetnum)) {
12500                tmp = tmp->next;
12501                continue;
12502             }
12503             break;
12504          case 2: /* dahdi show channels context <context> */
12505             if (strcasecmp(tmp->context, a->argv[4])) {
12506                tmp = tmp->next;
12507                continue;
12508             }
12509             break;
12510          default:
12511             ;
12512          }
12513       }
12514       if (tmp->channel > 0) {
12515          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12516       } else
12517          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12518 
12519       if (tmp->locallyblocked)
12520          blockstr[0] = 'L';
12521       else
12522          blockstr[0] = ' ';
12523 
12524       if (tmp->remotelyblocked)
12525          blockstr[1] = 'R';
12526       else
12527          blockstr[1] = ' ';
12528 
12529       blockstr[2] = '\0';
12530 
12531       snprintf(statestr, sizeof(statestr), "%s", "In Service");
12532 
12533       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12534       tmp = tmp->next;
12535    }
12536    ast_mutex_unlock(lock);
12537    return CLI_SUCCESS;
12538 #undef FORMAT
12539 #undef FORMAT2
12540 }

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

Definition at line 12774 of file chan_dahdi.c.

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

12775 {
12776    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
12777    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
12778    int span;
12779    int res;
12780    char alarms[50];
12781 
12782    int ctl;
12783    struct dahdi_spaninfo s;
12784 
12785    switch (cmd) {
12786    case CLI_INIT:
12787       e->command = "dahdi show status";
12788       e->usage = 
12789          "Usage: dahdi show status\n"
12790          "       Shows a list of DAHDI cards with status\n";
12791       return NULL;
12792    case CLI_GENERATE:
12793       return NULL;   
12794    }
12795    ctl = open("/dev/dahdi/ctl", O_RDWR);
12796    if (ctl < 0) {
12797       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
12798       return CLI_FAILURE;
12799    }
12800    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
12801 
12802    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
12803       s.spanno = span;
12804       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
12805       if (res) {
12806          continue;
12807       }
12808       alarms[0] = '\0';
12809       if (s.alarms > 0) {
12810          if (s.alarms & DAHDI_ALARM_BLUE)
12811             strcat(alarms, "BLU/");
12812          if (s.alarms & DAHDI_ALARM_YELLOW)
12813             strcat(alarms, "YEL/");
12814          if (s.alarms & DAHDI_ALARM_RED)
12815             strcat(alarms, "RED/");
12816          if (s.alarms & DAHDI_ALARM_LOOPBACK)
12817             strcat(alarms, "LB/");
12818          if (s.alarms & DAHDI_ALARM_RECOVER)
12819             strcat(alarms, "REC/");
12820          if (s.alarms & DAHDI_ALARM_NOTOPEN)
12821             strcat(alarms, "NOP/");
12822          if (!strlen(alarms))
12823             strcat(alarms, "UUU/");
12824          if (strlen(alarms)) {
12825             /* Strip trailing / */
12826             alarms[strlen(alarms) - 1] = '\0';
12827          }
12828       } else {
12829          if (s.numchans)
12830             strcpy(alarms, "OK");
12831          else
12832             strcpy(alarms, "UNCONFIGURED");
12833       }
12834 
12835       ast_cli(a->fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count
12836             , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
12837               s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
12838               s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
12839               "CAS"
12840             , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
12841               s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
12842               s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
12843               "Unk"
12844             , s.lineconfig & DAHDI_CONFIG_CRC4 ?
12845               s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
12846             , lbostr[s.lbo]
12847          );
12848    }
12849    close(ctl);
12850 
12851    return CLI_SUCCESS;
12852 #undef FORMAT
12853 #undef FORMAT2
12854 }

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

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

12857 {
12858    int pseudo_fd = -1;
12859    struct dahdi_versioninfo vi;
12860 
12861    switch (cmd) {
12862    case CLI_INIT:
12863       e->command = "dahdi show version";
12864       e->usage = 
12865          "Usage: dahdi show version\n"
12866          "       Shows the DAHDI version in use\n";
12867       return NULL;
12868    case CLI_GENERATE:
12869       return NULL;
12870    }
12871    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
12872       ast_cli(a->fd, "Failed to open control file to get version.\n");
12873       return CLI_SUCCESS;
12874    }
12875 
12876    strcpy(vi.version, "Unknown");
12877    strcpy(vi.echo_canceller, "Unknown");
12878 
12879    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
12880       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
12881    else
12882       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
12883 
12884    close(pseudo_fd);
12885 
12886    return CLI_SUCCESS;
12887 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

01756 {
01757    static char buf[256];
01758    switch (sig) {
01759    case SIG_EM:
01760       return "E & M Immediate";
01761    case SIG_EMWINK:
01762       return "E & M Wink";
01763    case SIG_EM_E1:
01764       return "E & M E1";
01765    case SIG_FEATD:
01766       return "Feature Group D (DTMF)";
01767    case SIG_FEATDMF:
01768       return "Feature Group D (MF)";
01769    case SIG_FEATDMF_TA:
01770       return "Feature Groud D (MF) Tandem Access";
01771    case SIG_FEATB:
01772       return "Feature Group B (MF)";
01773    case SIG_E911:
01774       return "E911 (MF)";
01775    case SIG_FGC_CAMA:
01776       return "FGC/CAMA (Dialpulse)";
01777    case SIG_FGC_CAMAMF:
01778       return "FGC/CAMA (MF)";
01779    case SIG_FXSLS:
01780       return "FXS Loopstart";
01781    case SIG_FXSGS:
01782       return "FXS Groundstart";
01783    case SIG_FXSKS:
01784       return "FXS Kewlstart";
01785    case SIG_FXOLS:
01786       return "FXO Loopstart";
01787    case SIG_FXOGS:
01788       return "FXO Groundstart";
01789    case SIG_FXOKS:
01790       return "FXO Kewlstart";
01791    case SIG_PRI:
01792       return "ISDN PRI";
01793    case SIG_BRI:
01794       return "ISDN BRI Point to Point";
01795    case SIG_BRI_PTMP:
01796       return "ISDN BRI Point to MultiPoint";
01797    case SIG_SS7:
01798       return "SS7";
01799    case SIG_SF:
01800       return "SF (Tone) Immediate";
01801    case SIG_SFWINK:
01802       return "SF (Tone) Wink";
01803    case SIG_SF_FEATD:
01804       return "SF (Tone) with Feature Group D (DTMF)";
01805    case SIG_SF_FEATDMF:
01806       return "SF (Tone) with Feature Group D (MF)";
01807    case SIG_SF_FEATB:
01808       return "SF (Tone) with Feature Group B (MF)";
01809    case SIG_GR303FXOKS:
01810       return "GR-303 with FXOKS";
01811    case SIG_GR303FXSKS:
01812       return "GR-303 with FXSKS";
01813    case 0:
01814       return "Pseudo";
01815    default:
01816       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
01817       return buf;
01818    }
01819 }

static void dahdi_softhangup_all ( void   )  [static]

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

12245 {
12246    struct dahdi_pvt *p;
12247 retry:
12248    ast_mutex_lock(&iflock);
12249     for (p = iflist; p; p = p->next) {
12250       ast_mutex_lock(&p->lock);
12251         if (p->owner && !p->restartpending) {
12252          if (ast_channel_trylock(p->owner)) {
12253             if (option_debug > 2)
12254                ast_verbose("Avoiding deadlock\n");
12255             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
12256             ast_mutex_unlock(&p->lock);
12257             ast_mutex_unlock(&iflock);
12258             goto retry;
12259          }
12260          if (option_debug > 2)
12261             ast_verbose("Softhanging up on %s\n", p->owner->name);
12262          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12263          p->restartpending = 1;
12264          num_restart_pending++;
12265          ast_channel_unlock(p->owner);
12266       }
12267       ast_mutex_unlock(&p->lock);
12268     }
12269    ast_mutex_unlock(&iflock);
12270 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

02038 {
02039    int x;
02040    int res;
02041    
02042    if (p && p->echocanon && p->echotraining) {
02043       x = p->echotraining;
02044       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02045       if (res)
02046          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02047       else
02048          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02049    } else {
02050       ast_debug(1, "No echo training requested\n");
02051    }
02052 }

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

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

04034 {
04035    /* Unlink a specific slave or all slaves/masters from a given master */
04036    int x;
04037    int hasslaves;
04038    if (!master)
04039       return;
04040    if (needlock) {
04041       ast_mutex_lock(&master->lock);
04042       if (slave) {
04043          while (ast_mutex_trylock(&slave->lock)) {
04044             DEADLOCK_AVOIDANCE(&master->lock);
04045          }
04046       }
04047    }
04048    hasslaves = 0;
04049    for (x = 0; x < MAX_SLAVES; x++) {
04050       if (master->slaves[x]) {
04051          if (!slave || (master->slaves[x] == slave)) {
04052             /* Take slave out of the conference */
04053             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
04054             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
04055             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
04056             master->slaves[x]->master = NULL;
04057             master->slaves[x] = NULL;
04058          } else
04059             hasslaves = 1;
04060       }
04061       if (!hasslaves)
04062          master->inconference = 0;
04063    }
04064    if (!slave) {
04065       if (master->master) {
04066          /* Take master out of the conference */
04067          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
04068          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
04069          hasslaves = 0;
04070          for (x = 0; x < MAX_SLAVES; x++) {
04071             if (master->master->slaves[x] == master)
04072                master->master->slaves[x] = NULL;
04073             else if (master->master->slaves[x])
04074                hasslaves = 1;
04075          }
04076          if (!hasslaves)
04077             master->master->inconference = 0;
04078       }
04079       master->master = NULL;
04080    }
04081    update_conf(master);
04082    if (needlock) {
04083       if (slave)
04084          ast_mutex_unlock(&slave->lock);
04085       ast_mutex_unlock(&master->lock);
04086    }
04087 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 306 of file chan_dahdi.c.

Referenced by flash_exec(), and ss_thread().

00307 {
00308    int i, j = 0;
00309    i = DAHDI_IOMUX_SIGEVENT;
00310    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00311       return -1;
00312    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00313       return -1;
00314    return j;
00315 }

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

Definition at line 6481 of file chan_dahdi.c.

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

Referenced by ss_thread().

06482 {
06483    int j;
06484    dahdi_set_hook(p->subs[index].dfd, DAHDI_WINK);
06485    for (;;)
06486    {
06487          /* set bits of interest */
06488       j = DAHDI_IOMUX_SIGEVENT;
06489           /* wait for some happening */
06490       if (ioctl(p->subs[index].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06491          /* exit loop if we have it */
06492       if (j & DAHDI_IOMUX_SIGEVENT) break;
06493    }
06494      /* get the event info */
06495    if (ioctl(p->subs[index].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06496    return 0;
06497 }

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

Definition at line 5961 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, PVT_TO_CHANNEL, dahdi_pvt::sig, SIG_PRI, dahdi_pvt::span, ast_frame::subclass, dahdi_pvt::subs, and ast_channel::tech_pvt.

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

static void destroy_all_channels ( void   )  [static]

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

03219 {
03220    int x;
03221    struct dahdi_pvt *p, *pl;
03222 
03223    while (num_restart_pending) {
03224       usleep(1);
03225    }
03226 
03227    ast_mutex_lock(&iflock);
03228    /* Destroy all the interfaces and free their memory */
03229    p = iflist;
03230    while (p) {
03231       /* Free any callerid */
03232       if (p->cidspill)
03233          ast_free(p->cidspill);
03234       pl = p;
03235       p = p->next;
03236       x = pl->channel;
03237       /* Free associated memory */
03238       if (pl)
03239          destroy_dahdi_pvt(&pl);
03240       if (option_verbose > 2) 
03241          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03242    }
03243    iflist = NULL;
03244    ifcount = 0;
03245    ast_mutex_unlock(&iflock);
03246 }

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

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

03169 {
03170    int owned = 0;
03171    int i = 0;
03172 
03173    if (!now) {
03174       if (cur->owner) {
03175          owned = 1;
03176       }
03177 
03178       for (i = 0; i < 3; i++) {
03179          if (cur->subs[i].owner) {
03180             owned = 1;
03181          }
03182       }
03183       if (!owned) {
03184          if (prev) {
03185             prev->next = cur->next;
03186             if (prev->next)
03187                prev->next->prev = prev;
03188             else
03189                ifend = prev;
03190          } else {
03191             iflist = cur->next;
03192             if (iflist)
03193                iflist->prev = NULL;
03194             else
03195                ifend = NULL;
03196          }
03197          destroy_dahdi_pvt(&cur);
03198       }
03199    } else {
03200       if (prev) {
03201          prev->next = cur->next;
03202          if (prev->next)
03203             prev->next->prev = prev;
03204          else
03205             ifend = prev;
03206       } else {
03207          iflist = cur->next;
03208          if (iflist)
03209             iflist->prev = NULL;
03210          else
03211             ifend = NULL;
03212       }
03213       destroy_dahdi_pvt(&cur);
03214    }
03215    return 0;
03216 }

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

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

03147 {
03148    struct dahdi_pvt *p = *pvt;
03149    /* Remove channel from the list */
03150    if (p->prev)
03151       p->prev->next = p->next;
03152    if (p->next)
03153       p->next->prev = p->prev;
03154    if (p->use_smdi)
03155       ast_smdi_interface_unref(p->smdi_iface);
03156    if (p->mwi_event_sub)
03157       ast_event_unsubscribe(p->mwi_event_sub);
03158    if (p->vars)
03159       ast_variables_destroy(p->vars);
03160    ast_mutex_destroy(&p->lock);
03161    dahdi_close_sub(p, SUB_REAL);
03162    if (p->owner)
03163       p->owner->tech_pvt = NULL;
03164    free(p);
03165    *pvt = NULL;
03166 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 1746 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

01747 {
01748    if (dialplan == -1 || dialplan == -2) {
01749       return("Dynamically set dialplan in ISDN");
01750    }
01751    return (pri_plan2str(dialplan));
01752 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1576 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

01577 {
01578    if (isdigit(digit))
01579       return DAHDI_TONE_DTMF_BASE + (digit - '0');
01580    else if (digit >= 'A' && digit <= 'D')
01581       return DAHDI_TONE_DTMF_A + (digit - 'A');
01582    else if (digit >= 'a' && digit <= 'd')
01583       return DAHDI_TONE_DTMF_A + (digit - 'a');
01584    else if (digit == '*')
01585       return DAHDI_TONE_DTMF_s;
01586    else if (digit == '#')
01587       return DAHDI_TONE_DTMF_p;
01588    else
01589       return -1;
01590 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4112 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

04113 {
04114    int val;
04115 
04116    p->ignoredtmf = 1;
04117 
04118    val = 0;
04119    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04120 
04121    if (!p->hardwaredtmf && p->dsp) {
04122       p->dsp_features &= ~DSP_FEATURE_DTMF_DETECT;
04123       ast_dsp_set_features(p->dsp, p->dsp_features);
04124    }
04125 }

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

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

10447 {
10448    struct ast_channel *chan = vchan;
10449    struct dahdi_pvt *pvt = chan->tech_pvt;
10450    struct ast_frame *f;
10451    char ex[80];
10452    /* Wait up to 30 seconds for an answer */
10453    int newms, ms = 30000;
10454    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10455    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10456    if (ast_call(chan, ex, 0)) {
10457       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10458       ast_hangup(chan);
10459       return NULL;
10460    }
10461    while ((newms = ast_waitfor(chan, ms)) > 0) {
10462       f = ast_read(chan);
10463       if (!f) {
10464          /* Got hangup */
10465          break;
10466       }
10467       if (f->frametype == AST_FRAME_CONTROL) {
10468          switch (f->subclass) {
10469          case AST_CONTROL_ANSWER:
10470             /* Launch the PBX */
10471             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10472             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10473             chan->priority = 1;
10474             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10475             ast_pbx_run(chan);
10476             /* It's already hungup, return immediately */
10477             return NULL;
10478          case AST_CONTROL_BUSY:
10479             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10480             break;
10481          case AST_CONTROL_CONGESTION:
10482             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10483             break;
10484          };
10485       }
10486       ast_frfree(f);
10487       ms = newms;
10488    }
10489    /* Hangup the channel since nothing happend */
10490    ast_hangup(chan);
10491    return NULL;
10492 }

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

Definition at line 8103 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::next, dahdi_pvt::owner, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

08104 {
08105    int count, res, res2, spoint, pollres=0;
08106    struct dahdi_pvt *i;
08107    struct dahdi_pvt *last = NULL;
08108    time_t thispass = 0, lastpass = 0;
08109    int found;
08110    char buf[1024];
08111    struct pollfd *pfds=NULL;
08112    int lastalloc = -1;
08113    /* This thread monitors all the frame relay interfaces which are not yet in use
08114       (and thus do not have a separate thread) indefinitely */
08115    /* From here on out, we die whenever asked */
08116 #if 0
08117    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
08118       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
08119       return NULL;
08120    }
08121    ast_debug(1, "Monitor starting...\n");
08122 #endif
08123    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08124 
08125    for (;;) {
08126       /* Lock the interface list */
08127       ast_mutex_lock(&iflock);
08128       if (!pfds || (lastalloc != ifcount)) {
08129          if (pfds) {
08130             ast_free(pfds);
08131             pfds = NULL;
08132          }
08133          if (ifcount) {
08134             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
08135                ast_mutex_unlock(&iflock);
08136                return NULL;
08137             }
08138          }
08139          lastalloc = ifcount;
08140       }
08141       /* Build the stuff we're going to poll on, that is the socket of every
08142          dahdi_pvt that does not have an associated owner channel */
08143       count = 0;
08144       i = iflist;
08145       while (i) {
08146          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
08147             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive) {
08148                /* This needs to be watched, as it lacks an owner */
08149                pfds[count].fd = i->subs[SUB_REAL].dfd;
08150                pfds[count].events = POLLPRI;
08151                pfds[count].revents = 0;
08152                /* If we are monitoring for VMWI or sending CID, we need to
08153                   read from the channel as well */
08154                if (i->cidspill || i->mwimonitor_fsk)
08155                   pfds[count].events |= POLLIN;
08156                count++;
08157             }
08158          }
08159          i = i->next;
08160       }
08161       /* Okay, now that we know what to do, release the interface lock */
08162       ast_mutex_unlock(&iflock);
08163       
08164       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
08165       pthread_testcancel();
08166       /* Wait at least a second for something to happen */
08167       res = poll(pfds, count, 1000);
08168       pthread_testcancel();
08169       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
08170 
08171       /* Okay, poll has finished.  Let's see what happened.  */
08172       if (res < 0) {
08173          if ((errno != EAGAIN) && (errno != EINTR))
08174             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
08175          continue;
08176       }
08177       /* Alright, lock the interface list again, and let's look and see what has
08178          happened */
08179       ast_mutex_lock(&iflock);
08180       found = 0;
08181       spoint = 0;
08182       lastpass = thispass;
08183       thispass = time(NULL);
08184       i = iflist;
08185       while (i) {
08186          if (thispass != lastpass) {
08187             if (!found && ((i == last) || ((i == iflist) && !last))) {
08188                last = i;
08189                if (last) {
08190                   if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
08191                      (last->sig & __DAHDI_SIG_FXO)) {
08192                      res = has_voicemail(last);
08193                      if (last->msgstate != res) {
08194                         int x;
08195                         ast_debug(1, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
08196                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
08197                         if (res2)
08198                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
08199                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
08200                         x = DAHDI_FLUSH_BOTH;
08201                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
08202                         if (res2)
08203                            ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
08204                         if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
08205                            /* Turn on on hook transfer for 4 seconds */
08206                            x = 4000;
08207                            ioctl(last->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
08208                            last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
08209                            last->cidpos = 0;
08210                            last->msgstate = res;
08211                            last->onhooktime = thispass;
08212                         }
08213                         found ++;
08214                      }
08215                   }
08216                   last = last->next;
08217                }
08218             }
08219          }
08220          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
08221             if (i->radio && !i->owner)
08222             {
08223                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08224                if (res)
08225                {
08226                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
08227                   /* Don't hold iflock while handling init events */
08228                   ast_mutex_unlock(&iflock);
08229                   handle_init_event(i, res);
08230                   ast_mutex_lock(&iflock);   
08231                }
08232                i = i->next;
08233                continue;
08234             }              
08235             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
08236             if (pollres & POLLIN) {
08237                if (i->owner || i->subs[SUB_REAL].owner) {
08238 #ifdef HAVE_PRI
08239                   if (!i->pri)
08240 #endif                  
08241                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
08242                   i = i->next;
08243                   continue;
08244                }
08245                if (!i->cidspill && !i->mwimonitor_fsk) {
08246                   ast_log(LOG_WARNING, "Whoa....  I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
08247                   i = i->next;
08248                   continue;
08249                }
08250                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
08251                if (res > 0) {
08252                   if (i->mwimonitor_fsk) {
08253                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
08254                         pthread_attr_t attr;
08255                         pthread_t threadid;
08256                         struct mwi_thread_data *mtd;
08257 
08258                         pthread_attr_init(&attr);
08259                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
08260 
08261                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
08262                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
08263                            mtd->pvt = i;
08264                            memcpy(mtd->buf, buf, res);
08265                            mtd->len = res;
08266                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
08267                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
08268                               ast_free(mtd);
08269                            }
08270                            i->mwimonitoractive = 1;
08271                         }
08272                      }
08273                   } else if (i->cidspill) {
08274                      /* We read some number of bytes.  Write an equal amount of data */
08275                      if (res > i->cidlen - i->cidpos) 
08276                         res = i->cidlen - i->cidpos;
08277                      res2 = write(i->subs[SUB_REAL].dfd, i->cidspill + i->cidpos, res);
08278                      if (res2 > 0) {
08279                         i->cidpos += res2;
08280                         if (i->cidpos >= i->cidlen) {
08281                            free(i->cidspill);
08282                            i->cidspill = 0;
08283                            i->cidpos = 0;
08284                            i->cidlen = 0;
08285                         }
08286                      } else {
08287                         ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
08288                         i->msgstate = -1;
08289                      }
08290                   }
08291                } else {
08292                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
08293                }
08294             }
08295             if (pollres & POLLPRI) {
08296                if (i->owner || i->subs[SUB_REAL].owner) {
08297 #ifdef HAVE_PRI
08298                   if (!i->pri)
08299 #endif                  
08300                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
08301                   i = i->next;
08302                   continue;
08303                }
08304                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
08305                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
08306                /* Don't hold iflock while handling init events */
08307                ast_mutex_unlock(&iflock);
08308                handle_init_event(i, res);
08309                ast_mutex_lock(&iflock);   
08310             }
08311          }
08312          i=i->next;
08313       }
08314       ast_mutex_unlock(&iflock);
08315    }
08316    /* Never reached */
08317    return NULL;
08318    
08319 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4127 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

04128 {
04129    int val;
04130 
04131    if (p->channel == CHAN_PSEUDO)
04132       return;
04133 
04134    p->ignoredtmf = 0;
04135 
04136    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04137    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04138 
04139    if (!p->hardwaredtmf && p->dsp) {
04140       p->dsp_features |= DSP_FEATURE_DTMF_DETECT;
04141       ast_dsp_set_features(p->dsp, p->dsp_features);
04142    }
04143 }

static char* event2str ( int  event  )  [static]

Definition at line 1736 of file chan_dahdi.c.

References ARRAY_LEN, and buf.

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

01737 {
01738    static char buf[256];
01739    if ((event < (ARRAY_LEN(events))) && (event > -1))
01740       return events[event];
01741    sprintf(buf, "Event %d", event); /* safe */
01742    return buf;
01743 }

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

Definition at line 2106 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

02107 {
02108    int j;
02109    int k;
02110    float linear_gain = pow(10.0, gain / 20.0);
02111 
02112    switch (law) {
02113    case DAHDI_LAW_ALAW:
02114       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02115          if (gain) {
02116             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02117             if (k > 32767) k = 32767;
02118             if (k < -32767) k = -32767;
02119             g->rxgain[j] = AST_LIN2A(k);
02120          } else {
02121             g->rxgain[j] = j;
02122          }
02123       }
02124       break;
02125    case DAHDI_LAW_MULAW:
02126       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02127          if (gain) {
02128             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02129             if (k > 32767) k = 32767;
02130             if (k < -32767) k = -32767;
02131             g->rxgain[j] = AST_LIN2MU(k);
02132          } else {
02133             g->rxgain[j] = j;
02134          }
02135       }
02136       break;
02137    }
02138 }

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

Definition at line 2072 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

02073 {
02074    int j;
02075    int k;
02076    float linear_gain = pow(10.0, gain / 20.0);
02077 
02078    switch (law) {
02079    case DAHDI_LAW_ALAW:
02080       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02081          if (gain) {
02082             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02083             if (k > 32767) k = 32767;
02084             if (k < -32767) k = -32767;
02085             g->txgain[j] = AST_LIN2A(k);
02086          } else {
02087             g->txgain[j] = j;
02088          }
02089       }
02090       break;
02091    case DAHDI_LAW_MULAW:
02092       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02093          if (gain) {
02094             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02095             if (k > 32767) k = 32767;
02096             if (k < -32767) k = -32767;
02097             g->txgain[j] = AST_LIN2MU(k);
02098          } else {
02099             g->txgain[j] = j;
02100          }
02101       }
02102       break;
02103    }
02104 }

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

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

13122 {
13123    struct dahdi_pvt *p = iflist;
13124    while (p) {
13125       if (p->channel == channel) {
13126          break;
13127       }
13128       p = p->next;
13129    }
13130    return p;
13131 }

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

04576 {
04577    int res;
04578    struct dahdi_spaninfo zi;
04579    struct dahdi_params params;
04580 
04581    memset(&zi, 0, sizeof(zi));
04582    zi.spanno = p->span;
04583 
04584    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
04585       if (zi.alarms != DAHDI_ALARM_NONE)
04586          return zi.alarms;
04587    } else {
04588       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
04589       return 0;
04590    }
04591 
04592    /* No alarms on the span. Check for channel alarms. */
04593    memset(&params, 0, sizeof(params));
04594    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
04595       return params.chan_alarms;
04596 
04597    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
04598 
04599    return DAHDI_ALARM_NONE;
04600 }

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

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

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

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

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

12738 {
12739    int i, j;
12740    switch (cmd) {
12741    case CLI_INIT:
12742       e->command = "dahdi show cadences";
12743       e->usage = 
12744          "Usage: dahdi show cadences\n"
12745          "       Shows all cadences currently defined\n";
12746       return NULL;
12747    case CLI_GENERATE:
12748       return NULL;   
12749    }
12750    for (i = 0; i < num_cadence; i++) {
12751       char output[1024];
12752       char tmp[16], tmp2[64];
12753       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
12754       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
12755 
12756       for (j = 0; j < 16; j++) {
12757          if (cadences[i].ringcadence[j] == 0)
12758             break;
12759          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
12760          if (cidrings[i] * 2 - 1 == j)
12761             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
12762          else
12763             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
12764          if (j != 0)
12765             strncat(output, ",", sizeof(output) - strlen(output) - 1);
12766          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
12767       }
12768       ast_cli(a->fd,"%s\n",output);
12769    }
12770    return CLI_SUCCESS;
12771 }

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

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

07884 {
07885    int res;
07886    pthread_t threadid;
07887    struct ast_channel *chan;
07888 
07889    /* Handle an event on a given channel for the monitor thread. */
07890 
07891    switch (event) {
07892    case DAHDI_EVENT_NONE:
07893    case DAHDI_EVENT_BITSCHANGED:
07894       break;
07895    case DAHDI_EVENT_WINKFLASH:
07896    case DAHDI_EVENT_RINGOFFHOOK:
07897       if (i->inalarm) break;
07898       if (i->radio) break;
07899       /* Got a ring/answer.  What kind of channel are we? */
07900       switch (i->sig) {
07901       case SIG_FXOLS:
07902       case SIG_FXOGS:
07903       case SIG_FXOKS:
07904          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07905          if (res && (errno == EBUSY))
07906             break;
07907          if (i->cidspill) {
07908             /* Cancel VMWI spill */
07909             ast_free(i->cidspill);
07910             i->cidspill = NULL;
07911          }
07912          if (i->immediate) {
07913             dahdi_enable_ec(i);
07914             /* The channel is immediately up.  Start right away */
07915             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
07916             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
07917             if (!chan) {
07918                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
07919                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07920                if (res < 0)
07921                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07922             }
07923          } else {
07924             /* Check for callerid, digits, etc */
07925             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
07926             if (chan) {
07927                if (has_voicemail(i))
07928                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
07929                else
07930                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
07931                if (res < 0) 
07932                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
07933                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07934                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07935                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07936                   if (res < 0)
07937                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07938                   ast_hangup(chan);
07939                }
07940             } else
07941                ast_log(LOG_WARNING, "Unable to create channel\n");
07942          }
07943          break;
07944       case SIG_FXSLS:
07945       case SIG_FXSGS:
07946       case SIG_FXSKS:
07947             i->ringt = i->ringt_base;
07948             /* Fall through */
07949       case SIG_EMWINK:
07950       case SIG_FEATD:
07951       case SIG_FEATDMF:
07952       case SIG_FEATDMF_TA:
07953       case SIG_E911:
07954       case SIG_FGC_CAMA:
07955       case SIG_FGC_CAMAMF:
07956       case SIG_FEATB:
07957       case SIG_EM:
07958       case SIG_EM_E1:
07959       case SIG_SFWINK:
07960       case SIG_SF_FEATD:
07961       case SIG_SF_FEATDMF:
07962       case SIG_SF_FEATB:
07963       case SIG_SF:
07964             /* Check for callerid, digits, etc */
07965             if (i->cid_start == CID_START_POLARITY_IN) {
07966                chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
07967             } else {
07968                chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
07969             }
07970             if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
07971                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
07972                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07973                if (res < 0)
07974                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07975                ast_hangup(chan);
07976             } else if (!chan) {
07977                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
07978             }
07979             break;
07980       default:
07981          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
07982          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
07983          if (res < 0)
07984                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
07985          return -1;
07986       }
07987       break;
07988    case DAHDI_EVENT_NOALARM:
07989       i->inalarm = 0;
07990       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
07991       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
07992          "Channel: %d\r\n", i->channel);
07993       break;
07994    case DAHDI_EVENT_ALARM:
07995       i->inalarm = 1;
07996       res = get_alarms(i);
07997       handle_alarms(i, res);
07998       /* fall thru intentionally */
07999    case DAHDI_EVENT_ONHOOK:
08000       if (i->radio)
08001          break;
08002       /* Back on hook.  Hang up. */
08003       switch (i->sig) {
08004       case SIG_FXOLS:
08005       case SIG_FXOGS:
08006       case SIG_FEATD:
08007       case SIG_FEATDMF:
08008       case SIG_FEATDMF_TA:
08009       case SIG_E911:
08010       case SIG_FGC_CAMA:
08011       case SIG_FGC_CAMAMF:
08012       case SIG_FEATB:
08013       case SIG_EM:
08014       case SIG_EM_E1:
08015       case SIG_EMWINK:
08016       case SIG_SF_FEATD:
08017       case SIG_SF_FEATDMF:
08018       case SIG_SF_FEATB:
08019       case SIG_SF:
08020       case SIG_SFWINK:
08021       case SIG_FXSLS:
08022       case SIG_FXSGS:
08023       case SIG_FXSKS:
08024       case SIG_GR303FXSKS:
08025          dahdi_disable_ec(i);
08026          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08027          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08028          break;
08029       case SIG_GR303FXOKS:
08030       case SIG_FXOKS:
08031          dahdi_disable_ec(i);
08032          /* Diddle the battery for the zhone */
08033 #ifdef ZHONE_HACK
08034          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08035          usleep(1);
08036 #endif         
08037          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08038          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08039          break;
08040       case SIG_PRI:
08041       case SIG_SS7:
08042       case SIG_BRI:
08043       case SIG_BRI_PTMP:
08044          dahdi_disable_ec(i);
08045          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08046          break;
08047       default:
08048          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
08049          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
08050          return -1;
08051       }
08052       break;
08053    case DAHDI_EVENT_POLARITY:
08054       switch (i->sig) {
08055       case SIG_FXSLS:
08056       case SIG_FXSKS:
08057       case SIG_FXSGS:
08058          /* We have already got a PR before the channel was 
08059             created, but it wasn't handled. We need polarity 
08060             to be REV for remote hangup detection to work. 
08061             At least in Spain */
08062          if (i->hanguponpolarityswitch)
08063             i->polarity = POLARITY_REV;
08064          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
08065             i->polarity = POLARITY_REV;
08066             ast_verb(2, "Starting post polarity "
08067                    "CID detection on channel %d\n",
08068                    i->channel);
08069             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
08070             if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08071                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
08072             }
08073          }
08074          break;
08075       default:
08076          ast_log(LOG_WARNING, "handle_init_event detected "
08077             "polarity reversal on non-FXO (SIG_FXS) "
08078             "interface %d\n", i->channel);
08079       }
08080       break;
08081    case DAHDI_EVENT_REMOVED: /* destroy channel */
08082       ast_log(LOG_NOTICE, 
08083             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n", 
08084             i->channel);
08085       dahdi_destroy_channel_bynum(i->channel);
08086       break;
08087    case DAHDI_EVENT_NEONMWI_ACTIVE:
08088       if (i->mwimonitor_neon) {
08089          notify_message(i->mailbox, 1);
08090          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
08091       }
08092       break;
08093    case DAHDI_EVENT_NEONMWI_INACTIVE:
08094       if (i->mwimonitor_neon) {
08095          notify_message(i->mailbox, 0);
08096          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
08097       }
08098       break;
08099    }
08100    return 0;
08101 }

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

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

11960 {
11961    int span;
11962    int x;
11963    switch (cmd) {
11964    case CLI_INIT: 
11965       e->command = "pri debug span";
11966       e->usage = 
11967          "Usage: pri debug span <span>\n"
11968          "       Enables debugging on a given PRI span\n";
11969       return NULL;
11970    case CLI_GENERATE:   
11971       return complete_span_4(a->line, a->word, a->pos, a->n);
11972    }
11973    if (a->argc < 4) {
11974       return CLI_SHOWUSAGE;
11975    }
11976    span = atoi(a->argv[3]);
11977    if ((span < 1) || (span > NUM_SPANS)) {
11978       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
11979       return CLI_SUCCESS;
11980    }
11981    if (!pris[span-1].pri) {
11982       ast_cli(a->fd, "No PRI running on span %d\n", span);
11983       return CLI_SUCCESS;
11984    }
11985    for (x = 0; x < NUM_DCHANS; x++) {
11986       if (pris[span-1].dchans[x])
11987          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
11988                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
11989                                                PRI_DEBUG_Q921_STATE);
11990    }
11991    ast_cli(a->fd, "Enabled debugging on span %d\n", span);
11992    return CLI_SUCCESS;
11993 }

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

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

11998 {
11999    int span;
12000    int x;
12001    switch (cmd) {
12002    case CLI_INIT:
12003       e->command = "pri no debug span";
12004       e->usage = 
12005          "Usage: pri no debug span <span>\n"
12006          "       Disables debugging on a given PRI span\n";
12007       return NULL;
12008    case CLI_GENERATE:
12009       return complete_span_5(a->line, a->word, a->pos, a->n);
12010    }
12011    if (a->argc < 5)
12012       return CLI_SHOWUSAGE;
12013 
12014    span = atoi(a->argv[4]);
12015    if ((span < 1) || (span > NUM_SPANS)) {
12016       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12017       return CLI_SUCCESS;
12018    }
12019    if (!pris[span-1].pri) {
12020       ast_cli(a->fd, "No PRI running on span %d\n", span);
12021       return CLI_SUCCESS;
12022    }
12023    for (x = 0; x < NUM_DCHANS; x++) {
12024       if (pris[span-1].dchans[x])
12025          pri_set_debug(pris[span-1].dchans[x], 0);
12026    }
12027    ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12028    return CLI_SUCCESS;
12029 }

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

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

12032 {
12033    int span;
12034    int x;
12035    switch (cmd) {
12036    case CLI_INIT:
12037       e->command = "pri intensive debug span";
12038       e->usage = 
12039          "Usage: pri intensive debug span <span>\n"
12040          "       Enables debugging down to the Q.921 level\n";
12041       return NULL;
12042    case CLI_GENERATE:
12043       return complete_span_5(a->line, a->word, a->pos, a->n);
12044    }
12045 
12046    if (a->argc < 5)
12047       return CLI_SHOWUSAGE;
12048    span = atoi(a->argv[4]);
12049    if ((span < 1) || (span > NUM_SPANS)) {
12050       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12051       return CLI_SUCCESS;
12052    }
12053    if (!pris[span-1].pri) {
12054       ast_cli(a->fd, "No PRI running on span %d\n", span);
12055       return CLI_SUCCESS;
12056    }
12057    for (x = 0; x < NUM_DCHANS; x++) {
12058       if (pris[span-1].dchans[x])
12059          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12060                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12061                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12062    }
12063    ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12064    return CLI_SUCCESS;
12065 }

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

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

11924 {
11925    int myfd;
11926    switch (cmd) {
11927    case CLI_INIT:
11928       e->command = "pri set debug file";
11929       e->usage = "Usage: pri set debug file [output-file]\n"
11930             "       Sends PRI debug output to the specified output file\n";
11931       return NULL;
11932    case CLI_GENERATE:
11933       return NULL;   
11934    }
11935    if (a->argc < 5)
11936       return CLI_SHOWUSAGE;
11937 
11938    if (ast_strlen_zero(a->argv[4]))
11939       return CLI_SHOWUSAGE;
11940 
11941    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
11942    if (myfd < 0) {
11943       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
11944       return CLI_SUCCESS;
11945    }
11946 
11947    ast_mutex_lock(&pridebugfdlock);
11948 
11949    if (pridebugfd >= 0)
11950       close(pridebugfd);
11951 
11952    pridebugfd = myfd;
11953    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
11954    ast_mutex_unlock(&pridebugfdlock);
11955    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
11956    return CLI_SUCCESS;
11957 }

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

Definition at line 12171 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, and pris.

12172 {
12173    int x;
12174    int span;
12175    int count=0;
12176    int debug=0;
12177 
12178    switch (cmd) {
12179    case CLI_INIT: 
12180       e->command = "pri show debug";
12181       return NULL;
12182    case CLI_GENERATE:
12183       return NULL;   
12184    }
12185 
12186    for (span = 0; span < NUM_SPANS; span++) {
12187            if (pris[span].pri) {
12188          for (x = 0; x < NUM_DCHANS; x++) {
12189             debug = 0;
12190                if (pris[span].dchans[x]) {
12191                   debug = pri_get_debug(pris[span].dchans[x]);
12192                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" );
12193                count++;
12194             }
12195          }
12196       }
12197 
12198    }
12199    ast_mutex_lock(&pridebugfdlock);
12200    if (pridebugfd >= 0) 
12201       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12202    ast_mutex_unlock(&pridebugfdlock);
12203        
12204    if (!count) 
12205       ast_cli(a->fd, "No debug set or no PRI running\n");
12206    return CLI_SUCCESS;
12207 }

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

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

12122 {
12123    int span;
12124    int x;
12125    char status[256];
12126    switch (cmd) {
12127    case CLI_INIT: 
12128       e->command = "pri show span";
12129       e->usage = 
12130          "Usage: pri show span <span>\n"
12131          "       Displays PRI Information on a given PRI span\n";
12132       return NULL;
12133    case CLI_GENERATE:
12134       return complete_span_4(a->line, a->word, a->pos, a->n);
12135    }
12136 
12137    if (a->argc < 4)
12138       return CLI_SHOWUSAGE;
12139    span = atoi(a->argv[3]);
12140    if ((span < 1) || (span > NUM_SPANS)) {
12141       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12142       return CLI_SUCCESS;
12143    }
12144    if (!pris[span-1].pri) {
12145       ast_cli(a->fd, "No PRI running on span %d\n", span);
12146       return CLI_SUCCESS;
12147    }
12148    for (x = 0; x < NUM_DCHANS; x++) {
12149       if (pris[span-1].dchannels[x]) {
12150 #ifdef PRI_DUMP_INFO_STR
12151          char *info_str = NULL;
12152 #endif
12153          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12154          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12155          ast_cli(a->fd, "Status: %s\n", status);
12156 #ifdef PRI_DUMP_INFO_STR
12157          info_str = pri_dump_info_str(pris[span-1].pri);
12158          if (info_str) {
12159             ast_cli(a->fd, "%s", info_str);
12160             ast_free(info_str);
12161          }
12162 #else
12163          pri_dump_info(pris[span-1].pri);
12164 #endif
12165          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12166       }
12167    }
12168    return CLI_SUCCESS;
12169 }

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

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

12089 {
12090    int span;
12091    int x;
12092    char status[256];
12093 
12094    switch (cmd) {
12095    case CLI_INIT:
12096       e->command = "pri show spans";
12097       e->usage = 
12098          "Usage: pri show spans\n"
12099          "       Displays PRI Information\n";
12100       return NULL;
12101    case CLI_GENERATE:
12102       return NULL;   
12103    }
12104 
12105    if (a->argc != 3)
12106       return CLI_SHOWUSAGE;
12107 
12108    for (span = 0; span < NUM_SPANS; span++) {
12109       if (pris[span].pri) {
12110          for (x = 0; x < NUM_DCHANS; x++) {
12111             if (pris[span].dchannels[x]) {
12112                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12113                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12114             }
12115          }
12116       }
12117    }
12118    return CLI_SUCCESS;
12119 }

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

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

11903 {
11904    switch (cmd) {
11905    case CLI_INIT:
11906       e->command = "pri unset debug file";
11907       e->usage = "Usage: pri unset debug file\n"
11908             "       Stop sending debug output to the previously \n"
11909                  "       specified file\n";
11910       return NULL;
11911    case CLI_GENERATE:
11912       return NULL;   
11913    }
11914    /* Assume it is unset */
11915    ast_mutex_lock(&pridebugfdlock);
11916    close(pridebugfd);
11917    pridebugfd = -1;
11918    ast_cli(a->fd, "PRI debug output to file disabled\n");
11919    ast_mutex_unlock(&pridebugfdlock);
11920    return CLI_SUCCESS;
11921 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 2349 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_EXISTS, 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(), and vm_execmain().

02350 {
02351    int new_msgs;
02352    struct ast_event *event;
02353    char *mailbox, *context;
02354 
02355    mailbox = context = ast_strdupa(p->mailbox);
02356    strsep(&context, "@");
02357    if (ast_strlen_zero(context))
02358       context = "default";
02359 
02360    event = ast_event_get_cached(AST_EVENT_MWI,
02361       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02362       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02363       AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
02364       AST_EVENT_IE_END);
02365 
02366    if (event) {
02367       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02368       ast_event_destroy(event);
02369    } else
02370       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
02371 
02372    return new_msgs;
02373 }

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

Definition at line 1861 of file chan_dahdi.c.

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

Referenced by conf_del().

01862 {
01863    /* If they're listening to our channel, they're ours */  
01864    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
01865       return 1;
01866    /* If they're a talker on our (allocated) conference, they're ours */
01867    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
01868       return 1;
01869    return 0;
01870 }

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

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

01892 {
01893    int x;
01894    int useslavenative;
01895    struct dahdi_pvt *slave = NULL;
01896    /* Start out optimistic */
01897    useslavenative = 1;
01898    /* Update conference state in a stateless fashion */
01899    for (x = 0; x < 3; x++) {
01900       /* Any three-way calling makes slave native mode *definitely* out
01901          of the question */
01902       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
01903          useslavenative = 0;
01904    }
01905    /* If we don't have any 3-way calls, check to see if we have
01906       precisely one slave */
01907    if (useslavenative) {
01908       for (x = 0; x < MAX_SLAVES; x++) {
01909          if (p->slaves[x]) {
01910             if (slave) {
01911                /* Whoops already have a slave!  No 
01912                   slave native and stop right away */
01913                slave = NULL;
01914                useslavenative = 0;
01915                break;
01916             } else {
01917                /* We have one slave so far */
01918                slave = p->slaves[x];
01919             }
01920          }
01921       }
01922    }
01923    /* If no slave, slave native definitely out */
01924    if (!slave)
01925       useslavenative = 0;
01926    else if (slave->law != p->law) {
01927       useslavenative = 0;
01928       slave = NULL;
01929    }
01930    if (out)
01931       *out = slave;
01932    return useslavenative;
01933 }

static int load_module ( void   )  [static]

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

14978 {
14979    int res;
14980 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14981    int y, i;
14982 #endif
14983 
14984 #ifdef HAVE_PRI
14985    memset(pris, 0, sizeof(pris));
14986    for (y = 0; y < NUM_SPANS; y++) {
14987       ast_mutex_init(&pris[y].lock);
14988       pris[y].offset = -1;
14989       pris[y].master = AST_PTHREADT_NULL;
14990       for (i = 0; i < NUM_DCHANS; i++)
14991          pris[y].fds[i] = -1;
14992    }
14993    pri_set_error(dahdi_pri_error);
14994    pri_set_message(dahdi_pri_message);
14995    ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
14996          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
14997 #endif
14998 #ifdef HAVE_SS7
14999    memset(linksets, 0, sizeof(linksets));
15000    for (y = 0; y < NUM_SPANS; y++) {
15001       ast_mutex_init(&linksets[y].lock);
15002       linksets[y].master = AST_PTHREADT_NULL;
15003       for (i = 0; i < NUM_DCHANS; i++)
15004          linksets[y].fds[i] = -1;
15005    }
15006    ss7_set_error(dahdi_ss7_error);
15007    ss7_set_message(dahdi_ss7_message);
15008 #endif /* HAVE_SS7 */
15009    res = setup_dahdi(0);
15010    /* Make sure we can register our DAHDI channel type */
15011    if (res)
15012       return AST_MODULE_LOAD_DECLINE;
15013    if (ast_channel_register(&dahdi_tech)) {
15014       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15015       __unload_module();
15016       return AST_MODULE_LOAD_FAILURE;
15017    }
15018 #ifdef HAVE_PRI
15019    ast_string_field_init(&inuse, 16);
15020    ast_string_field_set(&inuse, name, "GR-303InUse");
15021    ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
15022 #endif   
15023 #ifdef HAVE_SS7
15024    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15025 #endif
15026 
15027    ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
15028    
15029    memset(round_robin, 0, sizeof(round_robin));
15030    ast_manager_register("DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15031    ast_manager_register("DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15032    ast_manager_register("DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15033    ast_manager_register("DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15034    ast_manager_register("DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15035    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status dahdi channels");
15036    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15037 
15038    ast_cond_init(&ss_thread_complete, NULL);
15039 
15040    return res;
15041 }

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

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

08506 {
08507    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
08508    struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
08509    char fn[80];
08510    struct dahdi_bufferinfo bi;
08511    int res;
08512    int span = 0;
08513    int here = 0;
08514    int x;
08515    struct dahdi_pvt **wlist;
08516    struct dahdi_pvt **wend;
08517    struct dahdi_params p;
08518 
08519    wlist = &iflist;
08520    wend = &ifend;
08521 
08522 #ifdef HAVE_PRI
08523    if (pri) {
08524       wlist = &pri->crvs;
08525       wend = &pri->crvend;
08526    }
08527 #endif
08528 
08529    tmp2 = *wlist;
08530    prev = NULL;
08531 
08532    while (tmp2) {
08533       if (!tmp2->destroy) {
08534          if (tmp2->channel == channel) {
08535             tmp = tmp2;
08536             here = 1;
08537             break;
08538          }
08539          if (tmp2->channel > channel) {
08540             break;
08541          }
08542       }
08543       prev = tmp2;
08544       tmp2 = tmp2->next;
08545    }
08546 
08547    if (!here && reloading != 1) {
08548       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
08549          if (tmp)
08550             free(tmp);
08551          return NULL;
08552       }
08553       ast_mutex_init(&tmp->lock);
08554       ifcount++;
08555       for (x = 0; x < 3; x++)
08556          tmp->subs[x].dfd = -1;
08557       tmp->channel = channel;
08558    }
08559 
08560    if (tmp) {
08561       int chan_sig = conf->chan.sig;
08562       if (!here) {
08563          if ((channel != CHAN_PSEUDO) && !pri) {
08564             int count = 0;
08565             snprintf(fn, sizeof(fn), "%d", channel);
08566             /* Open non-blocking */
08567             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08568             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 */
08569                usleep(1);
08570                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
08571                count++;
08572             }
08573             /* Allocate a DAHDI structure */
08574             if (tmp->subs[SUB_REAL].dfd < 0) {
08575                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);
08576                destroy_dahdi_pvt(&tmp);
08577                return NULL;
08578             }
08579             memset(&p, 0, sizeof(p));
08580             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08581             if (res < 0) {
08582                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
08583                destroy_dahdi_pvt(&tmp);
08584                return NULL;
08585             }
08586             if (conf->is_sig_auto)
08587                chan_sig = sigtype_to_signalling(p.sigtype);
08588             if (p.sigtype != (chan_sig & 0x3ffff)) {
08589                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));
08590                destroy_dahdi_pvt(&tmp);
08591                return NULL;
08592             }
08593             tmp->law = p.curlaw;
08594             tmp->span = p.spanno;
08595             span = p.spanno - 1;
08596          } else {
08597             if (channel == CHAN_PSEUDO)
08598                chan_sig = 0;
08599             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
08600                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
08601                return NULL;
08602             }
08603          }
08604 #ifdef HAVE_SS7
08605          if (chan_sig == SIG_SS7) {
08606             struct dahdi_ss7 *ss7;
08607             int clear = 0;
08608             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
08609                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08610                destroy_dahdi_pvt(&tmp);
08611                return NULL;
08612             }
08613 
08614             ss7 = ss7_resolve_linkset(cur_linkset);
08615             if (!ss7) {
08616                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
08617                destroy_dahdi_pvt(&tmp);
08618                return NULL;
08619             }
08620             if (cur_cicbeginswith < 0) {
08621                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
08622                destroy_dahdi_pvt(&tmp);
08623                return NULL;
08624             }
08625 
08626             tmp->cic = cur_cicbeginswith++;
08627 
08628             /* DB: Add CIC's DPC information */
08629             tmp->dpc = cur_defaultdpc;
08630 
08631             tmp->ss7 = ss7;
08632             tmp->ss7call = NULL;
08633             ss7->pvts[ss7->numchans++] = tmp;
08634 
08635             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
08636             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
08637             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
08638             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
08639 
08640             ss7->called_nai = conf->ss7.called_nai;
08641             ss7->calling_nai = conf->ss7.calling_nai;
08642          }
08643 #endif
08644 #ifdef HAVE_PRI
08645          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
08646             int offset;
08647             int myswitchtype;
08648             int matchesdchan;
08649             int x,y;
08650             offset = 0;
08651             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 
08652                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
08653                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
08654                destroy_dahdi_pvt(&tmp);
08655                return NULL;
08656             }
08657             if (span >= NUM_SPANS) {
08658                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
08659                destroy_dahdi_pvt(&tmp);
08660                return NULL;
08661             } else {
08662                struct dahdi_spaninfo si;
08663                si.spanno = 0;
08664                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
08665                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
08666                   destroy_dahdi_pvt(&tmp);
08667                   return NULL;
08668                }
08669                /* Store the logical span first based upon the real span */
08670                tmp->logicalspan = pris[span].prilogicalspan;
08671                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
08672                if (span < 0) {
08673                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
08674                   destroy_dahdi_pvt(&tmp);
08675                   return NULL;
08676                }
08677                if ((chan_sig == SIG_PRI) ||
08678                      (chan_sig == SIG_BRI) ||
08679                      (chan_sig == SIG_BRI_PTMP))
08680                   myswitchtype = conf->pri.switchtype;
08681                else
08682                   myswitchtype = PRI_SWITCH_GR303_TMC;
08683                /* Make sure this isn't a d-channel */
08684                matchesdchan=0;
08685                for (x = 0; x < NUM_SPANS; x++) {
08686                   for (y = 0; y < NUM_DCHANS; y++) {
08687                      if (pris[x].dchannels[y] == tmp->channel) {
08688                         matchesdchan = 1;
08689                         break;
08690                      }
08691                   }
08692                }
08693                offset = p.chanpos;
08694                if (!matchesdchan) {
08695                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
08696                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
08697                      destroy_dahdi_pvt(&tmp);
08698                      return NULL;
08699                   }
08700                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
08701                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
08702                      destroy_dahdi_pvt(&tmp);
08703                      return NULL;
08704                   }
08705                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
08706                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
08707                      destroy_dahdi_pvt(&tmp);
08708                      return NULL;
08709                   }
08710                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
08711                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
08712                      destroy_dahdi_pvt(&tmp);
08713                      return NULL;
08714                   }
08715                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
08716                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
08717                      destroy_dahdi_pvt(&tmp);
08718                      return NULL;
08719                   }
08720                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
08721                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
08722                      destroy_dahdi_pvt(&tmp);
08723                      return NULL;
08724                   }
08725                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
08726                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
08727                      destroy_dahdi_pvt(&tmp);
08728                      return NULL;
08729                   }
08730                   if (pris[span].numchans >= MAX_CHANNELS) {
08731                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
08732                         pris[span].trunkgroup);
08733                      destroy_dahdi_pvt(&tmp);
08734                      return NULL;
08735                   }
08736 
08737                   pris[span].sig = chan_sig;
08738                   pris[span].nodetype = conf->pri.nodetype;
08739                   pris[span].switchtype = myswitchtype;
08740                   pris[span].nsf = conf->pri.nsf;
08741                   pris[span].dialplan = conf->pri.dialplan;
08742                   pris[span].localdialplan = conf->pri.localdialplan;
08743                   pris[span].pvts[pris[span].numchans++] = tmp;
08744                   pris[span].minunused = conf->pri.minunused;
08745                   pris[span].minidle = conf->pri.minidle;
08746                   pris[span].overlapdial = conf->pri.overlapdial;
08747 #ifdef HAVE_PRI_INBANDDISCONNECT
08748                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
08749 #endif
08750                   pris[span].facilityenable = conf->pri.facilityenable;
08751                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
08752                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
08753                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
08754                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
08755                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
08756                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
08757                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
08758                   pris[span].resetinterval = conf->pri.resetinterval;
08759                   
08760                   tmp->pri = &pris[span];
08761                   tmp->prioffset = offset;
08762                   tmp->call = NULL;
08763                } else {
08764                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
08765                   destroy_dahdi_pvt(&tmp);
08766                   return NULL;
08767                }
08768             }
08769          } else {
08770             tmp->prioffset = 0;
08771          }
08772 #endif
08773       } else {
08774          chan_sig = tmp->sig;
08775          if (tmp->subs[SUB_REAL].dfd > -1) {
08776             memset(&p, 0, sizeof(p));
08777             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
08778          }
08779       }
08780       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
08781       switch (chan_sig) {
08782       case SIG_FXSKS:
08783       case SIG_FXSLS:
08784       case SIG_EM:
08785       case SIG_EM_E1:
08786       case SIG_EMWINK:
08787       case SIG_FEATD:
08788       case SIG_FEATDMF:
08789       case SIG_FEATDMF_TA:
08790       case SIG_FEATB:
08791       case SIG_E911:
08792       case SIG_SF:
08793       case SIG_SFWINK:
08794       case SIG_FGC_CAMA:
08795       case SIG_FGC_CAMAMF:
08796       case SIG_SF_FEATD:
08797       case SIG_SF_FEATDMF:
08798       case SIG_SF_FEATB:
08799          p.starttime = 250;
08800          break;
08801       }
08802 
08803       if (tmp->radio) {
08804          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
08805          p.channo = channel;
08806          p.rxwinktime = 1;
08807          p.rxflashtime = 1;
08808          p.starttime = 1;
08809          p.debouncetime = 5;
08810       }
08811       if (!tmp->radio) {
08812          p.channo = channel;
08813          /* Override timing settings based on config file */
08814          if (conf->timing.prewinktime >= 0)
08815             p.prewinktime = conf->timing.prewinktime;
08816          if (conf->timing.preflashtime >= 0)
08817             p.preflashtime = conf->timing.preflashtime;
08818          if (conf->timing.winktime >= 0)
08819             p.winktime = conf->timing.winktime;
08820          if (conf->timing.flashtime >= 0)
08821             p.flashtime = conf->timing.flashtime;
08822          if (conf->timing.starttime >= 0)
08823             p.starttime = conf->timing.starttime;
08824          if (conf->timing.rxwinktime >= 0)
08825             p.rxwinktime = conf->timing.rxwinktime;
08826          if (conf->timing.rxflashtime >= 0)
08827             p.rxflashtime = conf->timing.rxflashtime;
08828          if (conf->timing.debouncetime >= 0)
08829             p.debouncetime = conf->timing.debouncetime;
08830       }
08831 
08832       /* dont set parms on a pseudo-channel (or CRV) */
08833       if (tmp->subs[SUB_REAL].dfd >= 0)
08834       {
08835          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
08836          if (res < 0) {
08837             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
08838             destroy_dahdi_pvt(&tmp);
08839             return NULL;
08840          }
08841       }
08842 #if 1
08843       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
08844          memset(&bi, 0, sizeof(bi));
08845          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
08846          if (!res) {
08847             bi.txbufpolicy = conf->chan.buf_policy;
08848             bi.rxbufpolicy = conf->chan.buf_policy;
08849             bi.numbufs = conf->chan.buf_no;
08850             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
08851             if (res < 0) {
08852                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
08853             }
08854          } else
08855             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
08856       }
08857 #endif
08858       tmp->immediate = conf->chan.immediate;
08859       tmp->transfertobusy = conf->chan.transfertobusy;
08860       if (chan_sig & __DAHDI_SIG_FXS) {
08861          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
08862          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
08863       }
08864       tmp->sig = chan_sig;
08865       tmp->outsigmod = conf->chan.outsigmod;
08866       tmp->ringt_base = ringt_base;
08867       tmp->firstradio = 0;
08868       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
08869          tmp->permcallwaiting = conf->chan.callwaiting;
08870       else
08871          tmp->permcallwaiting = 0;
08872       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
08873       tmp->destroy = 0;
08874       tmp->drings = conf->chan.drings;
08875 
08876       /* 10 is a nice default. */
08877       if (tmp->drings.ringnum[0].range == 0)
08878          tmp->drings.ringnum[0].range = 10;
08879       if (tmp->drings.ringnum[1].range == 0)
08880          tmp->drings.ringnum[1].range = 10;
08881       if (tmp->drings.ringnum[2].range == 0)
08882          tmp->drings.ringnum[2].range = 10;
08883 
08884       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
08885       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
08886       tmp->threewaycalling = conf->chan.threewaycalling;
08887       tmp->adsi = conf->chan.adsi;
08888       tmp->use_smdi = conf->chan.use_smdi;
08889       tmp->permhidecallerid = conf->chan.hidecallerid;
08890       tmp->callreturn = conf->chan.callreturn;
08891       tmp->echocancel = conf->chan.echocancel;
08892       tmp->echotraining = conf->chan.echotraining;
08893       tmp->pulse = conf->chan.pulse;
08894       if (tmp->echocancel.head.tap_length) {
08895          tmp->echocanbridged = conf->chan.echocanbridged;
08896       } else {
08897          if (conf->chan.echocanbridged)
08898             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
08899          tmp->echocanbridged = 0;
08900       }
08901       tmp->busydetect = conf->chan.busydetect;
08902       tmp->busycount = conf->chan.busycount;
08903       tmp->busycompare = conf->chan.busycompare;
08904       tmp->busytonelength = conf->chan.busytonelength;
08905       tmp->busyquietlength = conf->chan.busyquietlength;
08906       tmp->busyfuzziness = conf->chan.busyfuzziness;
08907       tmp->silencethreshold = conf->chan.silencethreshold;
08908       tmp->callprogress = conf->chan.callprogress;
08909       tmp->cancallforward = conf->chan.cancallforward;
08910       tmp->dtmfrelax = conf->chan.dtmfrelax;
08911       tmp->callwaiting = tmp->permcallwaiting;
08912       tmp->hidecallerid = tmp->permhidecallerid;
08913       tmp->channel = channel;
08914       tmp->stripmsd = conf->chan.stripmsd;
08915       tmp->use_callerid = conf->chan.use_callerid;
08916       tmp->cid_signalling = conf->chan.cid_signalling;
08917       tmp->cid_start = conf->chan.cid_start;
08918       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
08919       tmp->restrictcid = conf->chan.restrictcid;
08920       tmp->use_callingpres = conf->chan.use_callingpres;
08921       tmp->priindication_oob = conf->chan.priindication_oob;
08922       tmp->priexclusive = conf->chan.priexclusive;
08923       if (tmp->usedistinctiveringdetection) {
08924          if (!tmp->use_callerid) {
08925             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
08926             tmp->use_callerid = 1;
08927          }
08928       }
08929 
08930       if (tmp->cid_signalling == CID_SIG_SMDI) {
08931          if (!tmp->use_smdi) {
08932             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
08933             tmp->use_smdi = 1;
08934          }
08935       }
08936       if (tmp->use_smdi) {
08937          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
08938          if (!(tmp->smdi_iface)) {
08939             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
08940             tmp->use_smdi = 0;
08941          }
08942       }
08943 
08944       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
08945       tmp->amaflags = conf->chan.amaflags;
08946       if (!here) {
08947          tmp->confno = -1;
08948          tmp->propconfno = -1;
08949       }
08950       tmp->canpark = conf->chan.canpark;
08951       tmp->transfer = conf->chan.transfer;
08952       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
08953       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
08954       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
08955       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
08956       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
08957       ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
08958       tmp->cid_ton = 0;
08959       ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
08960       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
08961       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
08962          char *mailbox, *context;
08963          mailbox = context = ast_strdupa(tmp->mailbox);
08964          strsep(&context, "@");
08965          if (ast_strlen_zero(context))
08966             context = "default";
08967          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
08968             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
08969             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
08970             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
08971             AST_EVENT_IE_END);
08972       }
08973       tmp->msgstate = -1;
08974       tmp->group = conf->chan.group;
08975       tmp->callgroup = conf->chan.callgroup;
08976       tmp->pickupgroup= conf->chan.pickupgroup;
08977       if (conf->chan.vars) {
08978          tmp->vars = conf->chan.vars;
08979       }
08980       tmp->cid_rxgain = conf->chan.cid_rxgain;
08981       tmp->rxgain = conf->chan.rxgain;
08982       tmp->txgain = conf->chan.txgain;
08983       tmp->tonezone = conf->chan.tonezone;
08984       tmp->onhooktime = time(NULL);
08985       if (tmp->subs[SUB_REAL].dfd > -1) {
08986          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
08987          if (tmp->dsp)
08988             ast_dsp_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
08989          update_conf(tmp);
08990          if (!here) {
08991             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI) && (chan_sig != SIG_SS7))
08992                /* Hang it up to be sure it's good */
08993                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08994          }
08995          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
08996 #ifdef HAVE_PRI
08997          /* the dchannel is down so put the channel in alarm */
08998          if (tmp->pri && !pri_is_up(tmp->pri))
08999             tmp->inalarm = 1;
09000 #endif            
09001          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
09002             tmp->inalarm = 1;
09003             handle_alarms(tmp, res);
09004          }
09005       }
09006 
09007       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
09008       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
09009       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
09010       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
09011       if (!here) {
09012          tmp->locallyblocked = tmp->remotelyblocked = 0;
09013          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
09014             tmp->inservice = 0;
09015          else /* We default to in service on protocols that don't have a reset */
09016             tmp->inservice = 1;
09017       }
09018    }
09019    if (tmp && !here) {
09020       /* nothing on the iflist */
09021       if (!*wlist) {
09022          *wlist = tmp;
09023          tmp->prev = NULL;
09024          tmp->next = NULL;
09025          *wend = tmp;
09026       } else {
09027          /* at least one member on the iflist */
09028          struct dahdi_pvt *working = *wlist;
09029 
09030          /* check if we maybe have to put it on the begining */
09031          if (working->channel > tmp->channel) {
09032             tmp->next = *wlist;
09033             tmp->prev = NULL;
09034             (*wlist)->prev = tmp;
09035             *wlist = tmp;
09036          } else {
09037          /* go through all the members and put the member in the right place */
09038             while (working) {
09039                /* in the middle */
09040                if (working->next) {
09041                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
09042                      tmp->next = working->next;
09043                      tmp->prev = working;
09044                      working->next->prev = tmp;
09045                      working->next = tmp;
09046                      break;
09047                   }
09048                } else {
09049                /* the last */
09050                   if (working->channel < tmp->channel) {
09051                      working->next = tmp;
09052                      tmp->next = NULL;
09053                      tmp->prev = working;
09054                      *wend = tmp;
09055                      break;
09056                   }
09057                }
09058                working = working->next;
09059             }
09060          }
09061       }
09062    }
09063    return tmp;
09064 }

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

Definition at line 288 of file chan_dahdi.c.

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

00289 {
00290    /* This module does not handle MWI in an event-based manner.  However, it
00291     * subscribes to MWI for each mailbox that is configured so that the core
00292     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00293     * event cache instead of checking the mailbox directly. */
00294 }

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

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

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

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

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

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

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

Definition at line 6462 of file chan_dahdi.c.

References ast_waitfordigit(), and chan.

Referenced by ss_thread().

06463 {
06464    char c;
06465 
06466    *str = 0; /* start with empty output buffer */
06467    for (;;)
06468    {
06469       /* Wait for the first digit (up to specified ms). */
06470       c = ast_waitfordigit(chan, ms);
06471       /* if timeout, hangup or error, return as such */
06472       if (c < 1)
06473          return c;
06474       *str++ = c;
06475       *str = 0;
06476       if (strchr(term, c))
06477          return 1;
06478    }
06479 }

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

02286 {
02287    char s[sizeof(mwimonitornotify) + 80];
02288    struct ast_event *event;
02289    char *mailbox, *context;
02290 
02291    /* Strip off @default */
02292    context = mailbox = ast_strdupa(mailbox_full);
02293    strsep(&context, "@");
02294    if (ast_strlen_zero(context))
02295       context = "default";
02296 
02297    if (!(event = ast_event_new(AST_EVENT_MWI,
02298          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02299          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02300          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02301          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02302          AST_EVENT_IE_END))) {
02303       return;
02304    }
02305 
02306    ast_event_queue_and_cache(event,
02307       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
02308       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
02309       AST_EVENT_IE_END);
02310 
02311    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02312       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02313       ast_safe_system(s);
02314    }
02315 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

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

03338 {
03339    int x = -1;
03340 
03341    for (x = 0; x < NUM_DCHANS; x++) {
03342       if ((pri->dchans[x] == pri->pri))
03343          break;
03344    }
03345 
03346    return pri->fds[x];
03347 }

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

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

03308 {
03309    bearer->owner = &inuse;
03310    bearer->realcall = crv;
03311    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
03312    if (crv->subs[SUB_REAL].owner)
03313       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
03314    crv->bearer = bearer;
03315    crv->call = bearer->call;
03316    crv->pri = pri;
03317    return 0;
03318 }

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

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

10576 {
10577    do {
10578       pri->resetpos++;
10579    } while ((pri->resetpos < pri->numchans) &&
10580        (!pri->pvts[pri->resetpos] ||
10581         pri->pvts[pri->resetpos]->call ||
10582         pri->pvts[pri->resetpos]->resetting));
10583    if (pri->resetpos < pri->numchans) {
10584       /* Mark the channel as resetting and restart it */
10585       pri->pvts[pri->resetpos]->resetting = 1;
10586       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10587    } else {
10588       pri->resetting = 0;
10589       time(&pri->lastreset);
10590    }
10591    return 0;
10592 }

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

Definition at line 8457 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08458 {
08459    if (pris[span].mastertrunkgroup) {
08460       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);
08461       return -1;
08462    }
08463    pris[span].mastertrunkgroup = trunkgroup;
08464    pris[span].prilogicalspan = logicalspan;
08465    return 0;
08466 }

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

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

08395 {
08396    struct dahdi_spaninfo si;
08397    struct dahdi_params p;
08398    int fd;
08399    int span;
08400    int ospan=0;
08401    int x,y;
08402    for (x = 0; x < NUM_SPANS; x++) {
08403       if (pris[x].trunkgroup == trunkgroup) {
08404          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08405          return -1;
08406       }
08407    }
08408    for (y = 0; y < NUM_DCHANS; y++) {
08409       if (!channels[y]) 
08410          break;
08411       memset(&si, 0, sizeof(si));
08412       memset(&p, 0, sizeof(p));
08413       fd = open("/dev/dahdi/channel", O_RDWR);
08414       if (fd < 0) {
08415          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08416          return -1;
08417       }
08418       x = channels[y];
08419       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08420          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08421          close(fd);
08422          return -1;
08423       }
08424       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08425          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08426          return -1;
08427       }
08428       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08429          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08430          close(fd);
08431          return -1;
08432       }
08433       span = p.spanno - 1;
08434       if (pris[span].trunkgroup) {
08435          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08436          close(fd);
08437          return -1;
08438       }
08439       if (pris[span].pvts[0]) {
08440          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08441          close(fd);
08442          return -1;
08443       }
08444       if (!y) {
08445          pris[span].trunkgroup = trunkgroup;
08446          pris[span].offset = channels[y] - p.chanpos;
08447          ospan = span;
08448       }
08449       pris[ospan].dchannels[y] = channels[y];
08450       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08451       pris[span].span = span + 1;
08452       close(fd);
08453    }
08454    return 0;   
08455 }

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

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

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

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

Definition at line 10322 of file chan_dahdi.c.

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

10323 {
10324    struct dahdi_pvt *p;
10325    p = pri->crvs;
10326    while (p) {
10327       if (p->channel == crv)
10328          return p;
10329       p = p->next;
10330    }
10331    return NULL;
10332 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 3349 of file chan_dahdi.c.

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

03350 {
03351    int oldslot = -1;
03352    struct pri *old;
03353    int newslot = -1;
03354    int x;
03355    old = pri->pri;
03356    for (x = 0; x < NUM_DCHANS; x++) {
03357       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
03358          newslot = x;
03359       if (pri->dchans[x] == old) {
03360          oldslot = x;
03361       }
03362    }
03363    if (newslot < 0) {
03364       newslot = 0;
03365       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
03366          pri->dchannels[newslot]);
03367    }
03368    if (old && (oldslot != newslot))
03369       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
03370          pri->dchannels[oldslot], pri->dchannels[newslot]);
03371    pri->pri = pri->dchans[newslot];
03372    return 0;
03373 }

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

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

09223 {
09224    int x;
09225    if (backwards)
09226       x = pri->numchans;
09227    else
09228       x = 0;
09229    for (;;) {
09230       if (backwards && (x < 0))
09231          break;
09232       if (!backwards && (x >= pri->numchans))
09233          break;
09234       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09235          ast_debug(1, "Found empty available channel %d/%d\n", 
09236             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09237          return x;
09238       }
09239       if (backwards)
09240          x--;
09241       else
09242          x++;
09243    }
09244    return -1;
09245 }

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

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

10336 {
10337    int x;
10338    int span = PRI_SPAN(channel);
10339    int spanfd;
10340    struct dahdi_params param;
10341    int principle = -1;
10342    int explicit = PRI_EXPLICIT(channel);
10343    channel = PRI_CHANNEL(channel);
10344 
10345    if (!explicit) {
10346       spanfd = pri_active_dchan_fd(pri);
10347       memset(&param, 0, sizeof(param));
10348       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10349          return -1;
10350       span = pris[param.spanno - 1].prilogicalspan;
10351    }
10352 
10353    for (x = 0; x < pri->numchans; x++) {
10354       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10355          principle = x;
10356          break;
10357       }
10358    }
10359    
10360    return principle;
10361 }

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

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

10364 {
10365    int x;
10366    struct dahdi_pvt *crv;
10367    if (!c) {
10368       if (principle < 0)
10369          return -1;
10370       return principle;
10371    }
10372    if ((principle > -1) && 
10373       (principle < pri->numchans) && 
10374       (pri->pvts[principle]) && 
10375       (pri->pvts[principle]->call == c))
10376       return principle;
10377    /* First, check for other bearers */
10378    for (x = 0; x < pri->numchans; x++) {
10379       if (!pri->pvts[x])
10380          continue;
10381       if (pri->pvts[x]->call == c) {
10382          /* Found our call */
10383          if (principle != x) {
10384             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10385 
10386             ast_verb(3, "Moving call from channel %d to channel %d\n",
10387                 old->channel, new->channel);
10388             if (new->owner) {
10389                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10390                   old->channel, new->channel, new->channel);
10391                return -1;
10392             }
10393             /* Fix it all up now */
10394             new->owner = old->owner;
10395             old->owner = NULL;
10396             if (new->owner) {
10397                ast_string_field_build(new->owner, name, 
10398                             "DAHDI/%d:%d-%d", pri->trunkgroup,
10399                             new->channel, 1);
10400                new->owner->tech_pvt = new;
10401                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10402                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10403                old->subs[SUB_REAL].owner = NULL;
10404             } else
10405                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);
10406             new->call = old->call;
10407             old->call = NULL;
10408 
10409             /* Copy any DSP that may be present */
10410             new->dsp = old->dsp;
10411             new->dsp_features = old->dsp_features;
10412             old->dsp = NULL;
10413             old->dsp_features = 0;
10414          }
10415          return principle;
10416       }
10417    }
10418    /* Now check for a CRV with no bearer */
10419    crv = pri->crvs;
10420    while (crv) {
10421       if (crv->call == c) {
10422          /* This is our match...  Perform some basic checks */
10423          if (crv->bearer)
10424             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10425          else if (pri->pvts[principle]->owner) 
10426             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10427          else {
10428             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
10429                wakeup the potential sleeper */
10430             dahdi_close_sub(crv, SUB_REAL);
10431             pri->pvts[principle]->call = crv->call;
10432             pri_assign_bearer(crv, pri, pri->pvts[principle]);
10433             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10434                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10435                pri->trunkgroup, crv->channel);
10436             wakeup_sub(crv, SUB_REAL, pri);
10437          }
10438          return principle;
10439       }
10440       crv = crv->next;
10441    }
10442    ast_log(LOG_WARNING, "Call specified, but not found?\n");
10443    return -1;
10444 }

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

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

01229 {
01230    int res;
01231    /* Grab the lock first */
01232    do {
01233       res = ast_mutex_trylock(&pri->lock);
01234       if (res) {
01235          DEADLOCK_AVOIDANCE(&pvt->lock);
01236       }
01237    } while (res);
01238    /* Then break the poll */
01239    if (pri->master != AST_PTHREADT_NULL)
01240       pthread_kill(pri->master, SIGURG);
01241    return 0;
01242 }

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

Definition at line 10594 of file chan_dahdi.c.

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

10595 {
10596    int x;
10597    int redo;
10598    ast_mutex_unlock(&pri->lock);
10599    ast_mutex_lock(&p->lock);
10600    do {
10601       redo = 0;
10602       for (x = 0; x < 3; x++) {
10603          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10604             redo++;
10605             DEADLOCK_AVOIDANCE(&p->lock);
10606          }
10607          if (p->subs[x].owner) {
10608             ast_queue_hangup(p->subs[x].owner);
10609             ast_channel_unlock(p->subs[x].owner);
10610          }
10611       }
10612    } while (redo);
10613    ast_mutex_unlock(&p->lock);
10614    ast_mutex_lock(&pri->lock);
10615    return 0;
10616 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3297 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

03298 {
03299    int x;
03300    for (x = 0; x < NUM_DCHANS; x++) {
03301       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
03302          return 1;
03303    }
03304    return 0;
03305 }

static char* pri_order ( int  level  )  [static]

Definition at line 3320 of file chan_dahdi.c.

Referenced by handle_pri_show_span().

03321 {
03322    switch (level) {
03323    case 0:
03324       return "Primary";
03325    case 1:
03326       return "Secondary";
03327    case 2:
03328       return "Tertiary";
03329    case 3:
03330       return "Quaternary";
03331    default:
03332       return "<Unknown>";
03333    }     
03334 }

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

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

00450 {
00451    ast_mutex_unlock(&pri->lock);
00452 }

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

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

08349 {
08350    int x;
08351    int trunkgroup;
08352    /* Get appropriate trunk group if there is one */
08353    trunkgroup = pris[*span].mastertrunkgroup;
08354    if (trunkgroup) {
08355       /* Select a specific trunk group */
08356       for (x = 0; x < NUM_SPANS; x++) {
08357          if (pris[x].trunkgroup == trunkgroup) {
08358             *span = x;
08359             return 0;
08360          }
08361       }
08362       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08363       *span = -1;
08364    } else {
08365       if (pris[*span].trunkgroup) {
08366          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08367          *span = -1;
08368       } else if (pris[*span].mastertrunkgroup) {
08369          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08370          *span = -1;
08371       } else {
08372          if (si->totalchans == 31) {
08373             /* E1 */
08374             pris[*span].dchannels[0] = 16 + offset;
08375          } else if (si->totalchans == 24) {
08376             /* T1 or J1 */
08377             pris[*span].dchannels[0] = 24 + offset;
08378          } else if (si->totalchans == 3) {
08379             /* BRI */
08380             pris[*span].dchannels[0] = 3 + offset;
08381          } else {
08382             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);
08383             *span = -1;
08384             return 0;
08385          }
08386          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08387          pris[*span].offset = offset;
08388          pris[*span].span = *span + 1;
08389       }
08390    }
08391    return 0;
08392 }

static int process_dahdi ( struct dahdi_chan_conf confp,
struct ast_variable v,
int  reload,
int  skipchannels 
) [static]

Definition at line 13996 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_callerid_split(), ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_jb_read_conf(), ast_log(), ast_strdupa, ast_true(), ast_variable_new(), ast_verb, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busycompare, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::busyfuzziness, dahdi_pvt::busyquietlength, dahdi_pvt::busytonelength, dahdi_pvt::callgroup, dahdi_pvt::callprogress, CALLPROGRESS_FAX, CALLPROGRESS_FAX_INCOMING, CALLPROGRESS_FAX_OUTGOING, CALLPROGRESS_PROGRESS, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_BELL, CID_SIG_DTMF, CID_SIG_SMDI, CID_SIG_V23, CID_SIG_V23_JP, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, CID_START_POLARITY, CID_START_POLARITY_IN, CID_START_RING, dahdi_pvt::context, ringContextData::contextData, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, dahdi_pri::facilityenable, global_jbconf, dahdi_pvt::group, dahdi_pvt::hanguponpolarityswitch, HAVE_PRI, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pri::inbanddisconnect, dahdi_pri::internationalprefix, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, ast_variable::lineno, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_ERROR, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, ast_variable::name, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_SPANS, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, process_echocancel(), dahdi_pvt::pulse, dahdi_pvt::radio, distRingData::range, READ_SIZE, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, dahdi_pvt::sig, SIG_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_SFWINK, SIG_SS7, dahdi_pvt::silencethreshold, dahdi_chan_conf::smdi_port, dahdi_pvt::stripmsd, strsep(), dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, ast_variable::value, and dahdi_pvt::vars.

Referenced by setup_dahdi().

13997 {
13998    struct dahdi_pvt *tmp;
13999    int y;
14000    int found_pseudo = 0;
14001         char dahdichan[MAX_CHANLIST_LEN] = {};
14002 
14003    for (; v; v = v->next) {
14004       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
14005          continue;
14006 
14007       /* Create the interface list */
14008       if (!strcasecmp(v->name, "channel")
14009 #ifdef HAVE_PRI
14010           || !strcasecmp(v->name, "crv")
14011 #endif         
14012          ) {
14013          int iscrv;
14014          if (skipchannels)
14015             continue;
14016          iscrv = !strcasecmp(v->name, "crv");
14017          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
14018                return -1;
14019       } else if (!strcasecmp(v->name, "buffers")) {
14020          int res;
14021          char policy[21] = "";
14022 
14023          res = sscanf(v->value, "%d,%20s", &confp->chan.buf_no, policy);
14024          if (res != 2) {
14025             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
14026             confp->chan.buf_no = numbufs;
14027             continue;
14028          }
14029          if (confp->chan.buf_no < 0)
14030             confp->chan.buf_no = numbufs;
14031          if (!strcasecmp(policy, "full")) {
14032             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
14033          } else if (!strcasecmp(policy, "immediate")) {
14034             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
14035          } else {
14036             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
14037          }
14038       } else if (!strcasecmp(v->name, "dahdichan")) {
14039          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
14040       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
14041          usedistinctiveringdetection = ast_true(v->value);
14042       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
14043          distinctiveringaftercid = ast_true(v->value);
14044       } else if (!strcasecmp(v->name, "dring1context")) {
14045          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
14046       } else if (!strcasecmp(v->name, "dring2context")) {
14047          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
14048       } else if (!strcasecmp(v->name, "dring3context")) {
14049          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
14050       } else if (!strcasecmp(v->name, "dring1range")) {
14051          confp->chan.drings.ringnum[0].range = atoi(v->value);
14052       } else if (!strcasecmp(v->name, "dring2range")) {
14053          confp->chan.drings.ringnum[1].range = atoi(v->value);
14054       } else if (!strcasecmp(v->name, "dring3range")) {
14055          confp->chan.drings.ringnum[2].range = atoi(v->value);
14056       } else if (!strcasecmp(v->name, "dring1")) {
14057          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]);
14058       } else if (!strcasecmp(v->name, "dring2")) {
14059          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]);
14060       } else if (!strcasecmp(v->name, "dring3")) {
14061          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]);
14062       } else if (!strcasecmp(v->name, "usecallerid")) {
14063          confp->chan.use_callerid = ast_true(v->value);
14064       } else if (!strcasecmp(v->name, "cidsignalling")) {
14065          if (!strcasecmp(v->value, "bell"))
14066             confp->chan.cid_signalling = CID_SIG_BELL;
14067          else if (!strcasecmp(v->value, "v23"))
14068             confp->chan.cid_signalling = CID_SIG_V23;
14069          else if (!strcasecmp(v->value, "dtmf"))
14070             confp->chan.cid_signalling = CID_SIG_DTMF;
14071          else if (!strcasecmp(v->value, "smdi"))
14072             confp->chan.cid_signalling = CID_SIG_SMDI;
14073          else if (!strcasecmp(v->value, "v23_jp"))
14074             confp->chan.cid_signalling = CID_SIG_V23_JP;
14075          else if (ast_true(v->value))
14076             confp->chan.cid_signalling = CID_SIG_BELL;
14077       } else if (!strcasecmp(v->name, "cidstart")) {
14078          if (!strcasecmp(v->value, "ring"))
14079             confp->chan.cid_start = CID_START_RING;
14080          else if (!strcasecmp(v->value, "polarity_in"))
14081             confp->chan.cid_start = CID_START_POLARITY_IN;
14082          else if (!strcasecmp(v->value, "polarity"))
14083             confp->chan.cid_start = CID_START_POLARITY;
14084          else if (ast_true(v->value))
14085             confp->chan.cid_start = CID_START_RING;
14086       } else if (!strcasecmp(v->name, "threewaycalling")) {
14087          confp->chan.threewaycalling = ast_true(v->value);
14088       } else if (!strcasecmp(v->name, "cancallforward")) {
14089          confp->chan.cancallforward = ast_true(v->value);
14090       } else if (!strcasecmp(v->name, "relaxdtmf")) {
14091          if (ast_true(v->value)) 
14092             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
14093          else
14094             confp->chan.dtmfrelax = 0;
14095       } else if (!strcasecmp(v->name, "mailbox")) {
14096          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
14097       } else if (!strcasecmp(v->name, "adsi")) {
14098          confp->chan.adsi = ast_true(v->value);
14099       } else if (!strcasecmp(v->name, "usesmdi")) {
14100          confp->chan.use_smdi = ast_true(v->value);
14101       } else if (!strcasecmp(v->name, "smdiport")) {
14102          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
14103       } else if (!strcasecmp(v->name, "transfer")) {
14104          confp->chan.transfer = ast_true(v->value);
14105       } else if (!strcasecmp(v->name, "canpark")) {
14106          confp->chan.canpark = ast_true(v->value);
14107       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
14108          confp->chan.echocanbridged = ast_true(v->value);
14109       } else if (!strcasecmp(v->name, "busydetect")) {
14110          confp->chan.busydetect = ast_true(v->value);
14111       } else if (!strcasecmp(v->name, "busycount")) {
14112          confp->chan.busycount = atoi(v->value);
14113       } else if (!strcasecmp(v->name, "silencethreshold")) {
14114          confp->chan.silencethreshold = atoi(v->value);
14115       } else if (!strcasecmp(v->name, "busycompare")) {
14116          confp->chan.busycompare = ast_true(v->value);
14117       } else if (!strcasecmp(v->name, "busypattern")) {
14118          if (sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength) != 2) {
14119             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
14120          }
14121          int count = sscanf(v->value, "%d,%d", &confp->chan.busytonelength, &confp->chan.busyquietlength);
14122          if (count == 1)
14123             confp->chan.busyquietlength = 0;
14124          else if (count < 1)
14125             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength[,quietlength] at line %d.\n", v->lineno);
14126       } else if (!strcasecmp(v->name, "busyfuzziness")) {
14127          confp->chan.busyfuzziness = atoi(v->value);
14128       } else if (!strcasecmp(v->name, "callprogress")) {
14129          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
14130          if (ast_true(v->value))
14131             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
14132       } else if (!strcasecmp(v->name, "faxdetect")) {
14133          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
14134          if (!strcasecmp(v->value, "incoming")) {
14135             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
14136          } else if (!strcasecmp(v->value, "outgoing")) {
14137             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
14138          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
14139             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
14140       } else if (!strcasecmp(v->name, "echocancel")) {
14141          process_echocancel(confp, v->value, v->lineno);
14142       } else if (!strcasecmp(v->name, "echotraining")) {
14143          if (sscanf(v->value, "%d", &y) == 1) {
14144             if ((y < 10) || (y > 4000)) {
14145                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);             
14146             } else {
14147                confp->chan.echotraining = y;
14148             }
14149          } else if (ast_true(v->value)) {
14150             confp->chan.echotraining = 400;
14151          } else
14152             confp->chan.echotraining = 0;
14153       } else if (!strcasecmp(v->name, "hidecallerid")) {
14154          confp->chan.hidecallerid = ast_true(v->value);
14155       } else if (!strcasecmp(v->name, "hidecalleridname")) {
14156          confp->chan.hidecalleridname = ast_true(v->value);
14157       } else if (!strcasecmp(v->name, "pulsedial")) {
14158          confp->chan.pulse = ast_true(v->value);
14159       } else if (!strcasecmp(v->name, "callreturn")) {
14160          confp->chan.callreturn = ast_true(v->value);
14161       } else if (!strcasecmp(v->name, "callwaiting")) {
14162          confp->chan.callwaiting = ast_true(v->value);
14163       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
14164          confp->chan.callwaitingcallerid = ast_true(v->value);
14165       } else if (!strcasecmp(v->name, "context")) {
14166          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
14167       } else if (!strcasecmp(v->name, "language")) {
14168          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
14169       } else if (!strcasecmp(v->name, "progzone")) {
14170          ast_copy_string(progzone, v->value, sizeof(progzone));
14171       } else if (!strcasecmp(v->name, "mohinterpret") 
14172          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
14173          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
14174       } else if (!strcasecmp(v->name, "mohsuggest")) {
14175          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
14176       } else if (!strcasecmp(v->name, "stripmsd")) {
14177          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
14178          confp->chan.stripmsd = atoi(v->value);
14179       } else if (!strcasecmp(v->name, "jitterbuffers")) {
14180          numbufs = atoi(v->value);
14181       } else if (!strcasecmp(v->name, "group")) {
14182          confp->chan.group = ast_get_group(v->value);
14183       } else if (!strcasecmp(v->name, "callgroup")) {
14184          if (!strcasecmp(v->value, "none"))
14185             confp->chan.callgroup = 0;
14186          else
14187             confp->chan.callgroup = ast_get_group(v->value);
14188       } else if (!strcasecmp(v->name, "pickupgroup")) {
14189          if (!strcasecmp(v->value, "none"))
14190             confp->chan.pickupgroup = 0;
14191          else
14192             confp->chan.pickupgroup = ast_get_group(v->value);
14193       } else if (!strcasecmp(v->name, "setvar")) {
14194          char *varname = ast_strdupa(v->value), *varval = NULL;
14195          struct ast_variable *tmpvar;
14196          if (varname && (varval = strchr(varname, '='))) {
14197             *varval++ = '\0';
14198             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
14199                tmpvar->next = confp->chan.vars;
14200                confp->chan.vars = tmpvar;
14201             }
14202          }
14203       } else if (!strcasecmp(v->name, "immediate")) {
14204          confp->chan.immediate = ast_true(v->value);
14205       } else if (!strcasecmp(v->name, "transfertobusy")) {
14206          confp->chan.transfertobusy = ast_true(v->value);
14207       } else if (!strcasecmp(v->name, "mwimonitor")) {
14208          if (!strcasecmp(v->value, "neon")) {
14209             confp->chan.mwimonitor_neon = 1;
14210             confp->chan.mwimonitor_fsk = 0;
14211          } else {
14212             confp->chan.mwimonitor_neon = 0;
14213             if (!strcasecmp(v->value, "fsk"))
14214                confp->chan.mwimonitor_fsk = 1;
14215             else 
14216                confp->chan.mwimonitor_fsk = ast_true(v->value) ? 1 : 0;
14217          }
14218       } else if (!strcasecmp(v->name, "cid_rxgain")) {
14219          if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
14220             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
14221          }
14222       } else if (!strcasecmp(v->name, "rxgain")) {
14223          if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
14224             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
14225          }
14226       } else if (!strcasecmp(v->name, "txgain")) {
14227          if (sscanf(v->value, "%f", &confp->chan.txgain) != 1) {
14228             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
14229          }
14230       } else if (!strcasecmp(v->name, "tonezone")) {
14231          if (sscanf(v->value, "%d", &confp->chan.tonezone) != 1) {
14232             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
14233          }
14234       } else if (!strcasecmp(v->name, "callerid")) {
14235          if (!strcasecmp(v->value, "asreceived")) {
14236             confp->chan.cid_num[0] = '\0';
14237             confp->chan.cid_name[0] = '\0';
14238          } else {
14239             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
14240          } 
14241       } else if (!strcasecmp(v->name, "fullname")) {
14242          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
14243       } else if (!strcasecmp(v->name, "cid_number")) {
14244          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
14245       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
14246          confp->chan.dahditrcallerid = ast_true(v->value);
14247       } else if (!strcasecmp(v->name, "restrictcid")) {
14248          confp->chan.restrictcid = ast_true(v->value);
14249       } else if (!strcasecmp(v->name, "usecallingpres")) {
14250          confp->chan.use_callingpres = ast_true(v->value);
14251       } else if (!strcasecmp(v->name, "accountcode")) {
14252          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
14253       } else if (!strcasecmp(v->name, "amaflags")) {
14254          y = ast_cdr_amaflags2int(v->value);
14255          if (y < 0) 
14256             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
14257          else
14258             confp->chan.amaflags = y;
14259       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
14260          confp->chan.polarityonanswerdelay = atoi(v->value);
14261       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
14262          confp->chan.answeronpolarityswitch = ast_true(v->value);
14263       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
14264          confp->chan.hanguponpolarityswitch = ast_true(v->value);
14265       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
14266          confp->chan.sendcalleridafter = atoi(v->value);
14267       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
14268          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
14269       } else if (reload != 1) { 
14270           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
14271             int orig_radio = confp->chan.radio;
14272             int orig_outsigmod = confp->chan.outsigmod;
14273             int orig_auto = confp->is_sig_auto;
14274 
14275             confp->chan.radio = 0;
14276             confp->chan.outsigmod = -1;
14277             confp->is_sig_auto = 0;
14278             if (!strcasecmp(v->value, "em")) {
14279                confp->chan.sig = SIG_EM;
14280             } else if (!strcasecmp(v->value, "em_e1")) {
14281                confp->chan.sig = SIG_EM_E1;
14282             } else if (!strcasecmp(v->value, "em_w")) {
14283                confp->chan.sig = SIG_EMWINK;
14284             } else if (!strcasecmp(v->value, "fxs_ls")) {
14285                confp->chan.sig = SIG_FXSLS;
14286             } else if (!strcasecmp(v->value, "fxs_gs")) {
14287                confp->chan.sig = SIG_FXSGS;
14288             } else if (!strcasecmp(v->value, "fxs_ks")) {
14289                confp->chan.sig = SIG_FXSKS;
14290             } else if (!strcasecmp(v->value, "fxo_ls")) {
14291                confp->chan.sig = SIG_FXOLS;
14292             } else if (!strcasecmp(v->value, "fxo_gs")) {
14293                confp->chan.sig = SIG_FXOGS;
14294             } else if (!strcasecmp(v->value, "fxo_ks")) {
14295                confp->chan.sig = SIG_FXOKS;
14296             } else if (!strcasecmp(v->value, "fxs_rx")) {
14297                confp->chan.sig = SIG_FXSKS;
14298                confp->chan.radio = 1;
14299             } else if (!strcasecmp(v->value, "fxo_rx")) {
14300                confp->chan.sig = SIG_FXOLS;
14301                confp->chan.radio = 1;
14302             } else if (!strcasecmp(v->value, "fxs_tx")) {
14303                confp->chan.sig = SIG_FXSLS;
14304                confp->chan.radio = 1;
14305             } else if (!strcasecmp(v->value, "fxo_tx")) {
14306                confp->chan.sig = SIG_FXOGS;
14307                confp->chan.radio = 1;
14308             } else if (!strcasecmp(v->value, "em_rx")) {
14309                confp->chan.sig = SIG_EM;
14310                confp->chan.radio = 1;
14311             } else if (!strcasecmp(v->value, "em_tx")) {
14312                confp->chan.sig = SIG_EM;
14313                confp->chan.radio = 1;
14314             } else if (!strcasecmp(v->value, "em_rxtx")) {
14315                confp->chan.sig = SIG_EM;
14316                confp->chan.radio = 2;
14317             } else if (!strcasecmp(v->value, "em_txrx")) {
14318                confp->chan.sig = SIG_EM;
14319                confp->chan.radio = 2;
14320             } else if (!strcasecmp(v->value, "sf")) {
14321                confp->chan.sig = SIG_SF;
14322             } else if (!strcasecmp(v->value, "sf_w")) {
14323                confp->chan.sig = SIG_SFWINK;
14324             } else if (!strcasecmp(v->value, "sf_featd")) {
14325                confp->chan.sig = SIG_FEATD;
14326             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14327                confp->chan.sig = SIG_FEATDMF;
14328             } else if (!strcasecmp(v->value, "sf_featb")) {
14329                confp->chan.sig = SIG_SF_FEATB;
14330             } else if (!strcasecmp(v->value, "sf")) {
14331                confp->chan.sig = SIG_SF;
14332             } else if (!strcasecmp(v->value, "sf_rx")) {
14333                confp->chan.sig = SIG_SF;
14334                confp->chan.radio = 1;
14335             } else if (!strcasecmp(v->value, "sf_tx")) {
14336                confp->chan.sig = SIG_SF;
14337                confp->chan.radio = 1;
14338             } else if (!strcasecmp(v->value, "sf_rxtx")) {
14339                confp->chan.sig = SIG_SF;
14340                confp->chan.radio = 2;
14341             } else if (!strcasecmp(v->value, "sf_txrx")) {
14342                confp->chan.sig = SIG_SF;
14343                confp->chan.radio = 2;
14344             } else if (!strcasecmp(v->value, "featd")) {
14345                confp->chan.sig = SIG_FEATD;
14346             } else if (!strcasecmp(v->value, "featdmf")) {
14347                confp->chan.sig = SIG_FEATDMF;
14348             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14349                confp->chan.sig = SIG_FEATDMF_TA;
14350             } else if (!strcasecmp(v->value, "e911")) {
14351                confp->chan.sig = SIG_E911;
14352             } else if (!strcasecmp(v->value, "fgccama")) {
14353                confp->chan.sig = SIG_FGC_CAMA;
14354             } else if (!strcasecmp(v->value, "fgccamamf")) {
14355                confp->chan.sig = SIG_FGC_CAMAMF;
14356             } else if (!strcasecmp(v->value, "featb")) {
14357                confp->chan.sig = SIG_FEATB;
14358 #ifdef HAVE_PRI
14359             } else if (!strcasecmp(v->value, "pri_net")) {
14360                confp->chan.sig = SIG_PRI;
14361                confp->pri.nodetype = PRI_NETWORK;
14362             } else if (!strcasecmp(v->value, "pri_cpe")) {
14363                confp->chan.sig = SIG_PRI;
14364                confp->pri.nodetype = PRI_CPE;
14365             } else if (!strcasecmp(v->value, "bri_cpe")) {
14366                confp->chan.sig = SIG_BRI;
14367                confp->pri.nodetype = PRI_CPE;
14368             } else if (!strcasecmp(v->value, "bri_net")) {
14369                confp->chan.sig = SIG_BRI;
14370                confp->pri.nodetype = PRI_NETWORK;
14371             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
14372                confp->chan.sig = SIG_BRI_PTMP;
14373                confp->pri.nodetype = PRI_CPE;
14374             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
14375                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
14376             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
14377                confp->chan.sig = SIG_GR303FXOKS;
14378                confp->pri.nodetype = PRI_NETWORK;
14379             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
14380                confp->chan.sig = SIG_GR303FXSKS;
14381                confp->pri.nodetype = PRI_CPE;
14382 #endif
14383 #ifdef HAVE_SS7
14384             } else if (!strcasecmp(v->value, "ss7")) {
14385                confp->chan.sig = SIG_SS7;
14386 #endif
14387             } else if (!strcasecmp(v->value, "auto")) {
14388                confp->is_sig_auto = 1;
14389             } else {
14390                confp->chan.outsigmod = orig_outsigmod;
14391                confp->chan.radio = orig_radio;
14392                confp->is_sig_auto = orig_auto;
14393                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14394             }
14395           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
14396             if (!strcasecmp(v->value, "em")) {
14397                confp->chan.outsigmod = SIG_EM;
14398             } else if (!strcasecmp(v->value, "em_e1")) {
14399                confp->chan.outsigmod = SIG_EM_E1;
14400             } else if (!strcasecmp(v->value, "em_w")) {
14401                confp->chan.outsigmod = SIG_EMWINK;
14402             } else if (!strcasecmp(v->value, "sf")) {
14403                confp->chan.outsigmod = SIG_SF;
14404             } else if (!strcasecmp(v->value, "sf_w")) {
14405                confp->chan.outsigmod = SIG_SFWINK;
14406             } else if (!strcasecmp(v->value, "sf_featd")) {
14407                confp->chan.outsigmod = SIG_FEATD;
14408             } else if (!strcasecmp(v->value, "sf_featdmf")) {
14409                confp->chan.outsigmod = SIG_FEATDMF;
14410             } else if (!strcasecmp(v->value, "sf_featb")) {
14411                confp->chan.outsigmod = SIG_SF_FEATB;
14412             } else if (!strcasecmp(v->value, "sf")) {
14413                confp->chan.outsigmod = SIG_SF;
14414             } else if (!strcasecmp(v->value, "featd")) {
14415                confp->chan.outsigmod = SIG_FEATD;
14416             } else if (!strcasecmp(v->value, "featdmf")) {
14417                confp->chan.outsigmod = SIG_FEATDMF;
14418             } else if (!strcasecmp(v->value, "featdmf_ta")) {
14419                confp->chan.outsigmod = SIG_FEATDMF_TA;
14420             } else if (!strcasecmp(v->value, "e911")) {
14421                confp->chan.outsigmod = SIG_E911;
14422             } else if (!strcasecmp(v->value, "fgccama")) {
14423                confp->chan.outsigmod = SIG_FGC_CAMA;
14424             } else if (!strcasecmp(v->value, "fgccamamf")) {
14425                confp->chan.outsigmod = SIG_FGC_CAMAMF;
14426             } else if (!strcasecmp(v->value, "featb")) {
14427                confp->chan.outsigmod = SIG_FEATB;
14428             } else {
14429                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
14430             }
14431 #ifdef HAVE_PRI
14432          } else if (!strcasecmp(v->name, "pridialplan")) {
14433             if (!strcasecmp(v->value, "national")) {
14434                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
14435             } else if (!strcasecmp(v->value, "unknown")) {
14436                confp->pri.dialplan = PRI_UNKNOWN + 1;
14437             } else if (!strcasecmp(v->value, "private")) {
14438                confp->pri.dialplan = PRI_PRIVATE + 1;
14439             } else if (!strcasecmp(v->value, "international")) {
14440                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
14441             } else if (!strcasecmp(v->value, "local")) {
14442                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
14443             } else if (!strcasecmp(v->value, "dynamic")) {
14444                confp->pri.dialplan = -1;
14445             } else if (!strcasecmp(v->value, "redundant")) {
14446                confp->pri.dialplan = -2;
14447             } else {
14448                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
14449             }
14450          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
14451             if (!strcasecmp(v->value, "national")) {
14452                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
14453             } else if (!strcasecmp(v->value, "unknown")) {
14454                confp->pri.localdialplan = PRI_UNKNOWN + 1;
14455             } else if (!strcasecmp(v->value, "private")) {
14456                confp->pri.localdialplan = PRI_PRIVATE + 1;
14457             } else if (!strcasecmp(v->value, "international")) {
14458                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
14459             } else if (!strcasecmp(v->value, "local")) {
14460                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
14461             } else if (!strcasecmp(v->value, "dynamic")) {
14462                confp->pri.localdialplan = -1;
14463             } else if (!strcasecmp(v->value, "redundant")) {
14464                confp->pri.localdialplan = -2;
14465             } else {
14466                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
14467             }
14468          } else if (!strcasecmp(v->name, "switchtype")) {
14469             if (!strcasecmp(v->value, "national")) 
14470                confp->pri.switchtype = PRI_SWITCH_NI2;
14471             else if (!strcasecmp(v->value, "ni1"))
14472                confp->pri.switchtype = PRI_SWITCH_NI1;
14473             else if (!strcasecmp(v->value, "dms100"))
14474                confp->pri.switchtype = PRI_SWITCH_DMS100;
14475             else if (!strcasecmp(v->value, "4ess"))
14476                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
14477             else if (!strcasecmp(v->value, "5ess"))
14478                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
14479             else if (!strcasecmp(v->value, "euroisdn"))
14480                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
14481             else if (!strcasecmp(v->value, "qsig"))
14482                confp->pri.switchtype = PRI_SWITCH_QSIG;
14483             else {
14484                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
14485                return -1;
14486             }
14487          } else if (!strcasecmp(v->name, "nsf")) {
14488             if (!strcasecmp(v->value, "sdn"))
14489                confp->pri.nsf = PRI_NSF_SDN;
14490             else if (!strcasecmp(v->value, "megacom"))
14491                confp->pri.nsf = PRI_NSF_MEGACOM;
14492             else if (!strcasecmp(v->value, "tollfreemegacom"))
14493                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;           
14494             else if (!strcasecmp(v->value, "accunet"))
14495                confp->pri.nsf = PRI_NSF_ACCUNET;
14496             else if (!strcasecmp(v->value, "none"))
14497                confp->pri.nsf = PRI_NSF_NONE;
14498             else {
14499                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
14500                confp->pri.nsf = PRI_NSF_NONE;
14501             }
14502          } else if (!strcasecmp(v->name, "priindication")) {
14503             if (!strcasecmp(v->value, "outofband"))
14504                confp->chan.priindication_oob = 1;
14505             else if (!strcasecmp(v->value, "inband"))
14506                confp->chan.priindication_oob = 0;
14507             else
14508                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
14509                   v->value, v->lineno);
14510          } else if (!strcasecmp(v->name, "priexclusive")) {
14511             confp->chan.priexclusive = ast_true(v->value);
14512          } else if (!strcasecmp(v->name, "internationalprefix")) {
14513             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
14514          } else if (!strcasecmp(v->name, "nationalprefix")) {
14515             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
14516          } else if (!strcasecmp(v->name, "localprefix")) {
14517             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
14518          } else if (!strcasecmp(v->name, "privateprefix")) {
14519             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
14520          } else if (!strcasecmp(v->name, "unknownprefix")) {
14521             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
14522          } else if (!strcasecmp(v->name, "resetinterval")) {
14523             if (!strcasecmp(v->value, "never"))
14524                confp->pri.resetinterval = -1;
14525             else if (atoi(v->value) >= 60)
14526                confp->pri.resetinterval = atoi(v->value);
14527             else
14528                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
14529                   v->value, v->lineno);
14530          } else if (!strcasecmp(v->name, "minunused")) {
14531             confp->pri.minunused = atoi(v->value);
14532          } else if (!strcasecmp(v->name, "minidle")) {
14533             confp->pri.minidle = atoi(v->value); 
14534          } else if (!strcasecmp(v->name, "idleext")) {
14535             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
14536          } else if (!strcasecmp(v->name, "idledial")) {
14537             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
14538          } else if (!strcasecmp(v->name, "overlapdial")) {
14539             if (ast_true(v->value)) {
14540                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14541             } else if (!strcasecmp(v->value, "incoming")) {
14542                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
14543             } else if (!strcasecmp(v->value, "outgoing")) {
14544                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
14545             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
14546                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
14547             } else {
14548                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
14549             }
14550 #ifdef HAVE_PRI_INBANDDISCONNECT
14551          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
14552             confp->pri.inbanddisconnect = ast_true(v->value);
14553 #endif
14554          } else if (!strcasecmp(v->name, "pritimer")) {
14555 #ifdef PRI_GETSET_TIMERS
14556             char tmp[20], *timerc, *c = tmp;
14557             int timer, timeridx;
14558             ast_copy_string(tmp, v->value, sizeof(tmp));
14559             timerc = strsep(&c, ",");
14560             if (timerc) {
14561                timer = atoi(c);
14562                if (!timer)
14563                   ast_log(LOG_WARNING, "'%s' is not a valid value for an ISDN timer at line %d.\n", timerc, v->lineno);
14564                else {
14565                   if ((timeridx = pri_timer2idx(timerc)) >= 0)
14566                      pritimers[timeridx] = timer;
14567                   else
14568                      ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer at line %d.\n", timerc, v->lineno);
14569                }
14570             } else
14571                ast_log(LOG_WARNING, "'%s' is not a valid ISDN timer configuration string at line %d.\n", v->value, v->lineno);
14572 
14573          } else if (!strcasecmp(v->name, "facilityenable")) {
14574             confp->pri.facilityenable = ast_true(v->value);
14575 #endif /* PRI_GETSET_TIMERS */
14576 #endif /* HAVE_PRI */
14577 #ifdef HAVE_SS7
14578          } else if (!strcasecmp(v->name, "ss7type")) {
14579             if (!strcasecmp(v->value, "itu")) {
14580                cur_ss7type = SS7_ITU;
14581             } else if (!strcasecmp(v->value, "ansi")) {
14582                cur_ss7type = SS7_ANSI;
14583             } else
14584                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
14585          } else if (!strcasecmp(v->name, "linkset")) {
14586             cur_linkset = atoi(v->value);
14587          } else if (!strcasecmp(v->name, "pointcode")) {
14588             cur_pointcode = parse_pointcode(v->value);
14589          } else if (!strcasecmp(v->name, "adjpointcode")) {
14590             cur_adjpointcode = parse_pointcode(v->value);
14591          } else if (!strcasecmp(v->name, "defaultdpc")) {
14592             cur_defaultdpc = parse_pointcode(v->value);
14593          } else if (!strcasecmp(v->name, "cicbeginswith")) {
14594             cur_cicbeginswith = atoi(v->value);
14595          } else if (!strcasecmp(v->name, "networkindicator")) {
14596             if (!strcasecmp(v->value, "national"))
14597                cur_networkindicator = SS7_NI_NAT;
14598             else if (!strcasecmp(v->value, "national_spare"))
14599                cur_networkindicator = SS7_NI_NAT_SPARE;
14600             else if (!strcasecmp(v->value, "international"))
14601                cur_networkindicator = SS7_NI_INT;
14602             else if (!strcasecmp(v->value, "international_spare"))
14603                cur_networkindicator = SS7_NI_INT_SPARE;
14604             else
14605                cur_networkindicator = -1;
14606          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
14607             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
14608          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
14609             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
14610          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
14611             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
14612          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
14613             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
14614          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
14615             if (!strcasecmp(v->value, "national")) {
14616                confp->ss7.called_nai = SS7_NAI_NATIONAL;
14617             } else if (!strcasecmp(v->value, "international")) {
14618                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
14619             } else if (!strcasecmp(v->value, "subscriber")) {
14620                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
14621             } else if (!strcasecmp(v->value, "dynamic")) {
14622                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
14623             } else {
14624                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
14625             }
14626          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
14627             if (!strcasecmp(v->value, "national")) {
14628                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
14629             } else if (!strcasecmp(v->value, "international")) {
14630                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
14631             } else if (!strcasecmp(v->value, "subscriber")) {
14632                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
14633             } else if (!strcasecmp(v->value, "dynamic")) {
14634                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
14635             } else {
14636                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
14637             }
14638          } else if (!strcasecmp(v->name, "sigchan")) {
14639             int sigchan, res;
14640             sigchan = atoi(v->value);
14641             res = linkset_addsigchan(sigchan);
14642             if (res < 0)
14643                return -1;
14644 
14645          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
14646             struct dahdi_ss7 *link;
14647             link = ss7_resolve_linkset(cur_linkset);
14648             if (!link) {
14649                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
14650                return -1;
14651             }
14652             if (ast_true(v->value))
14653                link->flags |= LINKSET_FLAG_EXPLICITACM;
14654 
14655 #endif /* HAVE_SS7 */
14656          } else if (!strcasecmp(v->name, "cadence")) {
14657             /* setup to scan our argument */
14658             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
14659             int i;
14660             struct dahdi_ring_cadence new_cadence;
14661             int cid_location = -1;
14662             int firstcadencepos = 0;
14663             char original_args[80];
14664             int cadence_is_ok = 1;
14665 
14666             ast_copy_string(original_args, v->value, sizeof(original_args));
14667             /* 16 cadences allowed (8 pairs) */
14668             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]);
14669    
14670             /* Cadence must be even (on/off) */
14671             if (element_count % 2 == 1) {
14672                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
14673                cadence_is_ok = 0;
14674             }
14675    
14676             /* Ring cadences cannot be negative */
14677             for (i = 0; i < element_count; i++) {
14678                if (c[i] == 0) {
14679                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
14680                   cadence_is_ok = 0;
14681                   break;
14682                } else if (c[i] < 0) {
14683                   if (i % 2 == 1) {
14684                      /* Silence duration, negative possibly okay */
14685                      if (cid_location == -1) {
14686                         cid_location = i;
14687                         c[i] *= -1;
14688                      } else {
14689                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
14690                         cadence_is_ok = 0;
14691                         break;
14692                      }
14693                   } else {
14694                      if (firstcadencepos == 0) {
14695                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
14696                                  /* duration will be passed negative to the DAHDI driver */
14697                      } else {
14698                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
14699                         cadence_is_ok = 0;
14700                         break;
14701                      }
14702                   }
14703                }
14704             }
14705    
14706             /* Substitute our scanned cadence */
14707             for (i = 0; i < 16; i++) {
14708                new_cadence.ringcadence[i] = c[i];
14709             }
14710    
14711             if (cadence_is_ok) {
14712                /* ---we scanned it without getting annoyed; now some sanity checks--- */
14713                if (element_count < 2) {
14714                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
14715                } else {
14716                   if (cid_location == -1) {
14717                      /* user didn't say; default to first pause */
14718                      cid_location = 1;
14719                   } else {
14720                      /* convert element_index to cidrings value */
14721                      cid_location = (cid_location + 1) / 2;
14722                   }
14723                   /* ---we like their cadence; try to install it--- */
14724                   if (!user_has_defined_cadences++)
14725                      /* this is the first user-defined cadence; clear the default user cadences */
14726                      num_cadence = 0;
14727                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
14728                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
14729                   else {
14730                      cadences[num_cadence] = new_cadence;
14731                      cidrings[num_cadence++] = cid_location;
14732                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
14733                   }
14734                }
14735             }
14736          } else if (!strcasecmp(v->name, "ringtimeout")) {
14737             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
14738          } else if (!strcasecmp(v->name, "prewink")) {
14739             confp->timing.prewinktime = atoi(v->value);
14740          } else if (!strcasecmp(v->name, "preflash")) {
14741             confp->timing.preflashtime = atoi(v->value);
14742          } else if (!strcasecmp(v->name, "wink")) {
14743             confp->timing.winktime = atoi(v->value);
14744          } else if (!strcasecmp(v->name, "flash")) {
14745             confp->timing.flashtime = atoi(v->value);
14746          } else if (!strcasecmp(v->name, "start")) {
14747             confp->timing.starttime = atoi(v->value);
14748          } else if (!strcasecmp(v->name, "rxwink")) {
14749             confp->timing.rxwinktime = atoi(v->value);
14750          } else if (!strcasecmp(v->name, "rxflash")) {
14751             confp->timing.rxflashtime = atoi(v->value);
14752          } else if (!strcasecmp(v->name, "debounce")) {
14753             confp->timing.debouncetime = atoi(v->value);
14754          } else if (!strcasecmp(v->name, "toneduration")) {
14755             int toneduration;
14756             int ctlfd;
14757             int res;
14758             struct dahdi_dialparams dps;
14759 
14760             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
14761             if (ctlfd == -1) {
14762                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
14763                return -1;
14764             }
14765 
14766             toneduration = atoi(v->value);
14767             if (toneduration > -1) {
14768                memset(&dps, 0, sizeof(dps));
14769 
14770                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
14771                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
14772                if (res < 0) {
14773                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
14774                   return -1;
14775                }
14776             }
14777             close(ctlfd);
14778          } else if (!strcasecmp(v->name, "defaultcic")) {
14779             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
14780          } else if (!strcasecmp(v->name, "defaultozz")) {
14781             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
14782          } else if (!strcasecmp(v->name, "mwilevel")) {
14783             mwilevel = atoi(v->value);
14784          }
14785       } else if (!skipchannels)
14786          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
14787    }
14788    if (dahdichan[0]) { 
14789       /* The user has set 'dahdichan' */
14790       /*< \todo pass proper line number instead of 0 */
14791       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
14792          return -1;
14793       }
14794    }
14795    /*< \todo why check for the pseudo in the per-channel section.
14796     * Any actual use for manual setup of the pseudo channel? */
14797    if (!found_pseudo && reload == 0) {
14798       /* Make sure pseudo isn't a member of any groups if
14799          we're automatically making it. */   
14800       
14801       confp->chan.group = 0;
14802       confp->chan.callgroup = 0;
14803       confp->chan.pickupgroup = 0;
14804 
14805       tmp = mkintf(CHAN_PSEUDO, confp, NULL, reload);
14806 
14807       if (tmp) {
14808          ast_verb(3, "Automatically generated pseudo channel\n");
14809       } else {
14810          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
14811       }
14812    }
14813    return 0;
14814 }

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

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

Referenced by process_dahdi().

13945 {
13946    char *parse = ast_strdupa(data);
13947    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
13948    unsigned int param_count;
13949    unsigned int x;
13950 
13951    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
13952       return;
13953 
13954    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
13955 
13956    /* first parameter is tap length, process it here */
13957 
13958    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
13959    
13960    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
13961       confp->chan.echocancel.head.tap_length = x;
13962    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
13963       confp->chan.echocancel.head.tap_length = 128;
13964 
13965    /* now process any remaining parameters */
13966 
13967    for (x = 1; x < param_count; x++) {
13968       struct {
13969          char *name;
13970          char *value;
13971       } param;
13972 
13973       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
13974          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
13975          continue;
13976       }
13977 
13978       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
13979          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
13980          continue;
13981       }
13982 
13983       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
13984 
13985       if (param.value) {
13986          if (sscanf(param.value, "%d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
13987             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
13988             continue;
13989          }
13990       }
13991       confp->chan.echocancel.head.param_count++;
13992    }
13993 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 10618 of file chan_dahdi.c.

Referenced by __oh323_new().

10619 {
10620    switch (redirectingreason) {
10621    case 0:
10622       return "UNKNOWN";
10623    case 1:
10624       return "BUSY";
10625    case 2:
10626       return "NO_REPLY";
10627    case 0xF:
10628       return "UNCONDITIONAL";
10629    default:
10630       return "NOREDIRECT";
10631    }
10632 }

static int reload ( void   )  [static]

Definition at line 15143 of file chan_dahdi.c.

References ast_log(), and setup_dahdi().

15144 {
15145    int res = 0;
15146 
15147    res = setup_dahdi(1);
15148    if (res) {
15149       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15150       return -1;
15151    }
15152    return 0;
15153 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

01936 {
01937    p->confno = -1;
01938    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
01939    if (p->subs[SUB_REAL].dfd > -1) {
01940       struct dahdi_confinfo zi;
01941 
01942       memset(&zi, 0, sizeof(zi));
01943       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
01944          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
01945    }
01946    return 0;
01947 }

static int restart_monitor ( void   )  [static]

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

08322 {
08323    /* If we're supposed to be stopped -- stay stopped */
08324    if (monitor_thread == AST_PTHREADT_STOP)
08325       return 0;
08326    ast_mutex_lock(&monlock);
08327    if (monitor_thread == pthread_self()) {
08328       ast_mutex_unlock(&monlock);
08329       ast_log(LOG_WARNING, "Cannot kill myself\n");
08330       return -1;
08331    }
08332    if (monitor_thread != AST_PTHREADT_NULL) {
08333       /* Wake up the thread */
08334       pthread_kill(monitor_thread, SIGURG);
08335    } else {
08336       /* Start a new monitor */
08337       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08338          ast_mutex_unlock(&monlock);
08339          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08340          return -1;
08341       }
08342    }
08343    ast_mutex_unlock(&monlock);
08344    return 0;
08345 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

02318 {
02319    int res;
02320    if (p->saveconf.confmode) {
02321       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02322       p->saveconf.confmode = 0;
02323       if (res) {
02324          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02325          return -1;
02326       }
02327    }
02328    ast_debug(1, "Restored conferencing\n");
02329    return 0;
02330 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

02196 {
02197    int res;
02198 
02199    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02200    if (res) {
02201       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02202       return -1;
02203    }
02204 
02205    return 0;
02206 }

static int save_conference ( struct dahdi_pvt p  )  [static]

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

02242 {
02243    struct dahdi_confinfo c;
02244    int res;
02245    if (p->saveconf.confmode) {
02246       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02247       return -1;
02248    }
02249    p->saveconf.chan = 0;
02250    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02251    if (res) {
02252       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02253       p->saveconf.confmode = 0;
02254       return -1;
02255    }
02256    memset(&c, 0, sizeof(c));
02257    c.confmode = DAHDI_CONF_NORMAL;
02258    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02259    if (res) {
02260       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02261       return -1;
02262    }
02263    ast_debug(1, "Disabled conferencing\n");
02264    return 0;
02265 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

02376 {
02377    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
02378    int res;
02379    /* Take out of linear mode if necessary */
02380    if (p->subs[SUB_REAL].linear) {
02381       p->subs[SUB_REAL].linear = 0;
02382       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
02383    }
02384    while (p->cidpos < p->cidlen) {
02385       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
02386       if (res < 0) {
02387          if (errno == EAGAIN)
02388             return 0;
02389          else {
02390             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
02391             return -1;
02392          }
02393       }
02394       if (!res)
02395          return 0;
02396       p->cidpos += res;
02397    }
02398    ast_free(p->cidspill);
02399    p->cidspill = NULL;
02400    if (p->callwaitcas) {
02401       /* Wait for CID/CW to expire */
02402       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
02403    } else
02404       restore_conference(p);
02405    return 0;
02406 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

02335 {
02336    p->callwaitcas = 0;
02337    p->cidcwexpire = 0;
02338    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02339       return -1;
02340    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02341    /* Make sure we account for the end */
02342    p->cidlen += READ_SIZE * 4;
02343    p->cidpos = 0;
02344    send_callerid(p);
02345    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02346    return 0;
02347 }

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

Definition at line 2176 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

02177 {
02178    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02179 }

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

Definition at line 2158 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

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

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

Definition at line 2140 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

02141 {
02142    struct dahdi_gains g;
02143    int res;
02144 
02145    memset(&g, 0, sizeof(g));
02146    g.chan = chan;
02147    res = ioctl(fd, DAHDI_GETGAINS, &g);
02148    if (res) {
02149       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02150       return res;
02151    }
02152 
02153    fill_txgain(&g, gain, law);
02154 
02155    return ioctl(fd, DAHDI_SETGAINS, &g);
02156 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 14816 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_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, process_dahdi(), pvts, restart_monitor(), start_pri(), and ast_variable::value.

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

14817 {
14818    struct ast_config *cfg, *ucfg;
14819    struct ast_variable *v;
14820    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
14821    struct dahdi_chan_conf conf;
14822    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
14823    int res;
14824 
14825 #ifdef HAVE_PRI
14826    char *c;
14827    int spanno;
14828    int i;
14829    int logicalspan;
14830    int trunkgroup;
14831    int dchannels[NUM_DCHANS];
14832 #endif
14833 
14834    cfg = ast_config_load(config, config_flags);
14835 
14836    /* Error if we have no config file */
14837    if (!cfg) {
14838       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
14839       return 0;
14840    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
14841       ucfg = ast_config_load("users.conf", config_flags);
14842       if (ucfg == CONFIG_STATUS_FILEUNCHANGED)
14843          return 0;
14844       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14845       cfg = ast_config_load(config, config_flags);
14846    } else {
14847       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
14848       ucfg = ast_config_load("users.conf", config_flags);
14849    }
14850 
14851    /* It's a little silly to lock it, but we mind as well just to be sure */
14852    ast_mutex_lock(&iflock);
14853 #ifdef HAVE_PRI
14854    if (reload != 1) {
14855       /* Process trunkgroups first */
14856       v = ast_variable_browse(cfg, "trunkgroups");
14857       while (v) {
14858          if (!strcasecmp(v->name, "trunkgroup")) {
14859             trunkgroup = atoi(v->value);
14860             if (trunkgroup > 0) {
14861                if ((c = strchr(v->value, ','))) {
14862                   i = 0;
14863                   memset(dchannels, 0, sizeof(dchannels));
14864                   while (c && (i < NUM_DCHANS)) {
14865                      dchannels[i] = atoi(c + 1);
14866                      if (dchannels[i] < 0) {
14867                         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);
14868                      } else
14869                         i++;
14870                      c = strchr(c + 1, ',');
14871                   }
14872                   if (i) {
14873                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
14874                         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);
14875                   } else
14876                         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");
14877                   } else
14878                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14879                } else
14880                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
14881             } else
14882                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
14883          } else if (!strcasecmp(v->name, "spanmap")) {
14884             spanno = atoi(v->value);
14885             if (spanno > 0) {
14886                if ((c = strchr(v->value, ','))) {
14887                   trunkgroup = atoi(c + 1);
14888                   if (trunkgroup > 0) {
14889                      if ((c = strchr(c + 1, ','))) 
14890                         logicalspan = atoi(c + 1);
14891                      else
14892                         logicalspan = 0;
14893                      if (logicalspan >= 0) {
14894                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
14895                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14896                      } else
14897                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
14898                      } else
14899                         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);
14900                   } else
14901                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
14902                } else
14903                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
14904             } else
14905                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
14906          } else {
14907             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
14908          }
14909          v = v->next;
14910       }
14911    }
14912 #endif
14913    
14914    /* Copy the default jb config over global_jbconf */
14915    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
14916 
14917    mwimonitornotify[0] = '\0';
14918 
14919    v = ast_variable_browse(cfg, "channels");
14920    res = process_dahdi(&base_conf, v, reload, 0);
14921    ast_mutex_unlock(&iflock);
14922    ast_config_destroy(cfg);
14923    if (res)
14924       return res;
14925    if (ucfg) {
14926       char *cat;
14927       const char *chans;
14928       process_dahdi(&base_conf, ast_variable_browse(ucfg, "general"), 1, 1);
14929       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
14930          if (!strcasecmp(cat, "general"))
14931             continue;
14932          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
14933          if (!ast_strlen_zero(chans)) {
14934             if (memcpy(&conf, &base_conf, sizeof(conf)) == NULL) {
14935                ast_log(LOG_ERROR, "Not enough memory for conf copy\n");
14936                ast_config_destroy(ucfg);
14937                return -1;
14938             }
14939             process_dahdi(&conf, ast_variable_browse(ucfg, cat), reload, 0);
14940          }
14941       }
14942       ast_config_destroy(ucfg);
14943    }
14944 #ifdef HAVE_PRI
14945    if (reload != 1) {
14946       int x;
14947       for (x = 0; x < NUM_SPANS; x++) {
14948          if (pris[x].pvts[0]) {
14949             if (start_pri(pris + x)) {
14950                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
14951                return -1;
14952             } else
14953                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
14954          }
14955       }
14956    }
14957 #endif
14958 #ifdef HAVE_SS7
14959    if (reload != 1) {
14960       int x;
14961       for (x = 0; x < NUM_SPANS; x++) {
14962          if (linksets[x].ss7) {
14963             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
14964                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
14965                return -1;
14966             } else
14967                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
14968          }
14969       }
14970    }
14971 #endif
14972    /* And start the monitor for the first time */
14973    restart_monitor();
14974    return 0;
14975 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 8500 of file chan_dahdi.c.

Referenced by mkintf().

08501 {
08502         return sigtype;
08503 }

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

Definition at line 6521 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_digitmode(), ast_dsp_digitreset(), ast_dsp_free(), 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().

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

static int start_pri ( struct dahdi_pri pri  )  [static]

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

11776 {
11777    int res, x;
11778    struct dahdi_params p;
11779    struct dahdi_bufferinfo bi;
11780    struct dahdi_spaninfo si;
11781    int i;
11782    
11783    for (i = 0; i < NUM_DCHANS; i++) {
11784       if (!pri->dchannels[i])
11785          break;
11786       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
11787       x = pri->dchannels[i];
11788       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
11789          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
11790          return -1;
11791       }
11792       memset(&p, 0, sizeof(p));
11793       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
11794       if (res) {
11795          dahdi_close_pri_fd(pri, i);
11796          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
11797          return -1;
11798       }
11799       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
11800          dahdi_close_pri_fd(pri, i);
11801          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
11802          return -1;
11803       }
11804       memset(&si, 0, sizeof(si));
11805       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
11806       if (res) {
11807          dahdi_close_pri_fd(pri, i);
11808          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
11809       }
11810       if (!si.alarms)
11811          pri->dchanavail[i] |= DCHAN_NOTINALARM;
11812       else
11813          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
11814       memset(&bi, 0, sizeof(bi));
11815       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
11816       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
11817       bi.numbufs = 32;
11818       bi.bufsize = 1024;
11819       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
11820          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
11821          dahdi_close_pri_fd(pri, i);
11822          return -1;
11823       }
11824       switch (pri->sig) {
11825          case SIG_BRI:
11826             pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
11827             break;
11828          case SIG_BRI_PTMP:
11829             pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
11830             break;
11831          default:
11832             pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
11833       }
11834       /* Force overlap dial if we're doing GR-303! */
11835       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
11836          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
11837       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
11838 #ifdef HAVE_PRI_INBANDDISCONNECT
11839       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
11840 #endif
11841       /* Enslave to master if appropriate */
11842       if (i)
11843          pri_enslave(pri->dchans[0], pri->dchans[i]);
11844       if (!pri->dchans[i]) {
11845          dahdi_close_pri_fd(pri, i);
11846          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
11847          return -1;
11848       }
11849       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
11850       pri_set_nsf(pri->dchans[i], pri->nsf);
11851 #ifdef PRI_GETSET_TIMERS
11852       for (x = 0; x < PRI_MAX_TIMERS; x++) {
11853          if (pritimers[x] != 0)
11854             pri_set_timer(pri->dchans[i], x, pritimers[x]);
11855       }
11856 #endif
11857    }
11858    /* Assume primary is the one we use */
11859    pri->pri = pri->dchans[0];
11860    pri->resetpos = -1;
11861    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
11862       for (i = 0; i < NUM_DCHANS; i++) {
11863          if (!pri->dchannels[i])
11864             break;
11865          dahdi_close_pri_fd(pri, i);
11866       }
11867       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
11868       return -1;
11869    }
11870    return 0;
11871 }

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

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

01410 {
01411    int tchan;
01412    int tinthreeway;
01413    struct ast_channel *towner;
01414 
01415    ast_debug(1, "Swapping %d and %d\n", a, b);
01416 
01417    tchan = p->subs[a].chan;
01418    towner = p->subs[a].owner;
01419    tinthreeway = p->subs[a].inthreeway;
01420 
01421    p->subs[a].chan = p->subs[b].chan;
01422    p->subs[a].owner = p->subs[b].owner;
01423    p->subs[a].inthreeway = p->subs[b].inthreeway;
01424 
01425    p->subs[b].chan = tchan;
01426    p->subs[b].owner = towner;
01427    p->subs[b].inthreeway = tinthreeway;
01428 
01429    if (p->subs[a].owner) 
01430       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
01431    if (p->subs[b].owner) 
01432       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
01433    wakeup_sub(p, a, NULL);
01434    wakeup_sub(p, b, NULL);
01435 }

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

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

01560 {
01561    if (!x) {
01562       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
01563       return -1;
01564    }
01565    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
01566    dahdi_close_sub(p, x);
01567    p->subs[x].linear = 0;
01568    p->subs[x].chan = 0;
01569    p->subs[x].owner = NULL;
01570    p->subs[x].inthreeway = 0;
01571    p->polarity = POLARITY_IDLE;
01572    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
01573    return 0;
01574 }

static int unload_module ( void   )  [static]

Definition at line 13836 of file chan_dahdi.c.

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

13837 {
13838 #if defined(HAVE_PRI) || defined(HAVE_SS7)
13839    int y;
13840 #endif
13841 #ifdef HAVE_PRI
13842    for (y = 0; y < NUM_SPANS; y++)
13843       ast_mutex_destroy(&pris[y].lock);
13844 #endif
13845 #ifdef HAVE_SS7
13846    for (y = 0; y < NUM_SPANS; y++)
13847       ast_mutex_destroy(&linksets[y].lock);
13848 #endif /* HAVE_SS7 */
13849    return __unload_module();
13850 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

01950 {
01951    int needconf = 0;
01952    int x;
01953    int useslavenative;
01954    struct dahdi_pvt *slave = NULL;
01955 
01956    useslavenative = isslavenative(p, &slave);
01957    /* Start with the obvious, general stuff */
01958    for (x = 0; x < 3; x++) {
01959       /* Look for three way calls */
01960       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
01961          conf_add(p, &p->subs[x], x, 0);
01962          needconf++;
01963       } else {
01964          conf_del(p, &p->subs[x], x);
01965       }
01966    }
01967    /* If we have a slave, add him to our conference now. or DAX
01968       if this is slave native */
01969    for (x = 0; x < MAX_SLAVES; x++) {
01970       if (p->slaves[x]) {
01971          if (useslavenative)
01972             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
01973          else {
01974             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
01975             needconf++;
01976          }
01977       }
01978    }
01979    /* If we're supposed to be in there, do so now */
01980    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
01981       if (useslavenative)
01982          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
01983       else {
01984          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
01985          needconf++;
01986       }
01987    }
01988    /* If we have a master, add ourselves to his conference */
01989    if (p->master) {
01990       if (isslavenative(p->master, NULL)) {
01991          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
01992       } else {
01993          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
01994       }
01995    }
01996    if (!needconf) {
01997       /* Nobody is left (or should be left) in our conference.
01998          Kill it. */
01999       p->confno = -1;
02000    }
02001    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02002    return 0;
02003 }

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

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

01320 {
01321 #ifdef HAVE_PRI
01322    if (pri)
01323       ast_mutex_unlock(&pri->lock);
01324 #endif         
01325    for (;;) {
01326       if (p->subs[a].owner) {
01327          if (ast_channel_trylock(p->subs[a].owner)) {
01328             DEADLOCK_AVOIDANCE(&p->lock);
01329          } else {
01330             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01331             ast_channel_unlock(p->subs[a].owner);
01332             break;
01333          }
01334       } else
01335          break;
01336    }
01337 #ifdef HAVE_PRI
01338    if (pri)
01339       ast_mutex_lock(&pri->lock);
01340 #endif         
01341 }


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

Definition at line 15177 of file chan_dahdi.c.

int alarm

Definition at line 1714 of file chan_dahdi.c.

Referenced by action_dahdishowchannels().

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

Referenced by alarm2str(), and dahdi_show_status().

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 15177 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

Definition at line 1274 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 1285 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 13089 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 12209 of file chan_dahdi.c.

Referenced by __unload_module(), and load_module().

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

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

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

Definition at line 3251 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

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

char* events[] [static]

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

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

int gendigittimeout = 8000 [static]

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

Definition at line 254 of file chan_dahdi.c.

Referenced by mgcp_ss(), and skinny_ss().

struct ast_jb_conf global_jbconf [static]

Definition at line 125 of file chan_dahdi.c.

int ifcount = 0 [static]

Definition at line 263 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 260 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 242 of file chan_dahdi.c.

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

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

Referenced by mgcp_ss(), and skinny_ss().

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

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

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

int mwilevel = 512 [static]

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

char* name

Definition at line 1715 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1271 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 280 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 237 of file chan_dahdi.c.

int pridebugfd = -1 [static]

Definition at line 246 of file chan_dahdi.c.

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

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

struct dahdi_pri pris[NUM_SPANS] [static]

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

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

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

struct dahdi_pvt* round_robin[32]

Definition at line 1225 of file chan_dahdi.c.

Referenced by dahdi_request(), and load_module().

ast_cond_t ss_thread_complete [static]

Definition at line 276 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 279 of file chan_dahdi.c.

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

Definition at line 277 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

char* subnames[] [static]

Initial value:

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

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

int user_has_defined_cadences = 0 [static]

Definition at line 1272 of file chan_dahdi.c.


Generated on Thu Jul 9 13:40:57 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7