Tue Mar 2 17:32:47 2010

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 <libss7.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"
Include dependency graph for chan_dahdi.c:

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_ss7
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 LINKSET_FLAG_EXPLICITACM   (1 << 0)
#define LINKSTATE_DOWN   (1 << 3)
#define LINKSTATE_INALARM   (1 << 0)
#define LINKSTATE_STARTING   (1 << 1)
#define LINKSTATE_UP   (1 << 2)
#define MASK_AVAIL   (1 << 0)
#define MASK_INUSE   (1 << 1)
#define MAX_CHANLIST_LEN   80
#define MAX_CHANNELS   672
#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ( (2000) )
#define NEED_MFDETECT(p)   (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))
 Signaling types that need to use MF detection should be placed in this macro.
#define NUM_CADENCE_MAX   25
#define NUM_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0
#define POLARITY_REV   1
#define PRI_CHANNEL(p)   ((p) & 0xff)
#define PRI_EXPLICIT(p)   (((p) >> 16) & 0x01)
#define PRI_SPAN(p)   (((p) >> 8) & 0xff)
#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)
#define PROC_DAHDI_OPT_NOWARN   (1 << 1)
#define PVT_TO_CHANNEL(p)   (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
#define READ_SIZE   160
#define sig2str   dahdi_sig2str
#define SIG_BRI   (0x2000000 | DAHDI_SIG_CLEAR)
#define SIG_BRI_PTMP   (0X4000000 | DAHDI_SIG_CLEAR)
#define SIG_E911   (0x1000000 | DAHDI_SIG_EM)
#define SIG_EM   DAHDI_SIG_EM
#define SIG_EM_E1   DAHDI_SIG_EM_E1
#define SIG_EMWINK   (0x0100000 | DAHDI_SIG_EM)
#define SIG_FEATB   (0x0800000 | DAHDI_SIG_EM)
#define SIG_FEATD   (0x0200000 | DAHDI_SIG_EM)
#define SIG_FEATDMF   (0x0400000 | DAHDI_SIG_EM)
#define SIG_FEATDMF_TA   (0x2000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMA   (0x4000000 | DAHDI_SIG_EM)
#define SIG_FGC_CAMAMF   (0x8000000 | DAHDI_SIG_EM)
#define SIG_FXOGS   DAHDI_SIG_FXOGS
#define SIG_FXOKS   DAHDI_SIG_FXOKS
#define SIG_FXOLS   DAHDI_SIG_FXOLS
#define SIG_FXSGS   DAHDI_SIG_FXSGS
#define SIG_FXSKS   DAHDI_SIG_FXSKS
#define SIG_FXSLS   DAHDI_SIG_FXSLS
#define SIG_GR303FXOKS   (0x0100000 | DAHDI_SIG_FXOKS)
#define SIG_GR303FXSKS   (0x0100000 | DAHDI_SIG_FXSKS)
#define SIG_PRI   DAHDI_SIG_CLEAR
#define SIG_SF   DAHDI_SIG_SF
#define SIG_SF_FEATB   (0x0800000 | DAHDI_SIG_SF)
#define SIG_SF_FEATD   (0x0200000 | DAHDI_SIG_SF)
#define SIG_SF_FEATDMF   (0x0400000 | DAHDI_SIG_SF)
#define SIG_SFWINK   (0x0100000 | DAHDI_SIG_SF)
#define SIG_SS7   (0x1000000 | DAHDI_SIG_CLEAR)
#define SMDI_MD_WAIT_TIMEOUT   1500
#define SS7_NAI_DYNAMIC   -1
#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "DAHDI Telephony w/PRI & SS7"
#define TRAILER_MS   5
#define TRANSFER   0

Enumerations

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

Functions

static struct ast_frame__dahdi_exception (struct ast_channel *ast)
static void __reg_module (void)
static int __unload_module (void)
static void __unreg_module (void)
static int action_dahdidialoffhook (struct mansession *s, const struct message *m)
static int action_dahdidndoff (struct mansession *s, const struct message *m)
static int action_dahdidndon (struct mansession *s, const struct message *m)
static int action_dahdirestart (struct mansession *s, const struct message *m)
static int action_dahdishowchannels (struct mansession *s, const struct message *m)
static int action_transfer (struct mansession *s, const struct message *m)
static int action_transferhangup (struct mansession *s, const struct message *m)
static char * alarm2str (int alm)
static int alloc_sub (struct dahdi_pvt *p, int x)
static void apply_plan_to_number (char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
static int attempt_transfer (struct dahdi_pvt *p)
static int available (struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
static int build_channels (struct dahdi_chan_conf *conf, int iscrv, const char *value, int reload, int lineno, int *found_pseudo)
static void build_status (char *s, size_t len, int status, int active)
static int bump_gains (struct dahdi_pvt *p)
static int calc_energy (const unsigned char *buf, int len, int law)
static struct dahdi_pvtchandup (struct dahdi_pvt *src)
static int check_for_conference (struct dahdi_pvt *p)
static unsigned char cid_pres2ss7pres (int cid_pres)
static unsigned char cid_pres2ss7screen (int cid_pres)
static char * complete_span_4 (const char *line, const char *word, int pos, int state)
static char * complete_span_5 (const char *line, const char *word, int pos, int state)
static char * complete_span_helper (const char *line, const char *word, int pos, int state, int rpos)
static int conf_add (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx, int slavechannel)
static int conf_del (struct dahdi_pvt *p, struct dahdi_subchannel *c, int idx)
static int dahdi_answer (struct ast_channel *ast)
static enum ast_bridge_result dahdi_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
static int dahdi_call (struct ast_channel *ast, char *rdest, int timeout)
static int dahdi_callwait (struct ast_channel *ast)
static struct dahdi_chan_conf dahdi_chan_conf_default (void)
static void dahdi_close (int fd)
static void dahdi_close_pri_fd (struct dahdi_pri *pri, int fd_num)
static void dahdi_close_ss7_fd (struct dahdi_ss7 *ss7, int fd_num)
static void dahdi_close_sub (struct dahdi_pvt *chan_pvt, int sub_num)
static int dahdi_confmute (struct dahdi_pvt *p, int muted)
static char * dahdi_destroy_channel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int dahdi_destroy_channel_bynum (int channel)
static int dahdi_digit_begin (struct ast_channel *ast, char digit)
static int dahdi_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void dahdi_disable_ec (struct dahdi_pvt *p)
static void dahdi_dnd (struct dahdi_pvt *dahdichan, int on)
 enable or disable the chan_dahdi Do-Not-Disturb mode for a DAHDI channel
static void dahdi_enable_ec (struct dahdi_pvt *p)
static struct ast_framedahdi_exception (struct ast_channel *ast)
static int dahdi_fake_event (struct dahdi_pvt *p, int mode)
static int dahdi_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int dahdi_func_read (struct ast_channel *chan, const char *function, char *data, char *buf, size_t len)
static int dahdi_get_event (int fd)
 Avoid the silly dahdi_getevent which ignores a bunch of events.
static int dahdi_get_index (struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
static void dahdi_handle_dtmfup (struct ast_channel *ast, int idx, struct ast_frame **dest)
static struct ast_framedahdi_handle_event (struct ast_channel *ast)
static int dahdi_hangup (struct ast_channel *ast)
static int dahdi_indicate (struct ast_channel *chan, int condition, const void *data, size_t datalen)
static void dahdi_link (struct dahdi_pvt *slave, struct dahdi_pvt *master)
static void dahdi_loopback (struct dahdi_pvt *p, int enable)
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_ss7_error (struct ss7 *ss7, char *s)
static void dahdi_ss7_message (struct ss7 *ss7, char *s)
static void dahdi_train_ec (struct dahdi_pvt *p)
static void dahdi_unlink (struct dahdi_pvt *slave, struct dahdi_pvt *master, int needlock)
static int dahdi_wait_event (int fd)
 Avoid the silly dahdi_waitevent which ignores a bunch of events.
static int dahdi_wink (struct dahdi_pvt *p, int idx)
static int dahdi_write (struct ast_channel *ast, struct ast_frame *frame)
static void destroy_all_channels (void)
static int destroy_channel (struct dahdi_pvt *prev, struct dahdi_pvt *cur, int now)
static void destroy_dahdi_pvt (struct dahdi_pvt **pvt)
static char * dialplan2str (int dialplan)
static int digit_to_dtmfindex (char digit)
static void disable_dtmf_detect (struct dahdi_pvt *p)
static void * do_idle_thread (void *vchan)
static void * do_monitor (void *data)
static void enable_dtmf_detect (struct dahdi_pvt *p)
static char * event2str (int event)
static void fill_rxgain (struct dahdi_gains *g, float gain, int law)
static void fill_txgain (struct dahdi_gains *g, float gain, int law)
static struct dahdi_pvtfind_channel (int channel)
static int get_alarms (struct dahdi_pvt *p)
static void handle_alarms (struct dahdi_pvt *p, int alms)
static char * handle_dahdi_show_cadences (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct dahdi_pvthandle_init_event (struct dahdi_pvt *i, int event)
static char * handle_pri_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_no_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_really_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_set_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_span (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_show_spans (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_unset_debug_file (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_pri_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_block_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_block_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_no_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_show_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_unblock_cic (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_unblock_linkset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_ss7_version (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int has_voicemail (struct dahdi_pvt *p)
static int isourconf (struct dahdi_pvt *p, struct dahdi_subchannel *c)
static int isslavenative (struct dahdi_pvt *p, struct dahdi_pvt **out)
static int linkset_addsigchan (int sigchan)
static int load_module (void)
static struct dahdi_pvtmkintf (int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static void * mwi_send_thread (void *data)
static void * mwi_thread (void *data)
static int my_dahdi_write (struct dahdi_pvt *p, unsigned char *buf, int len, int idx, int linear)
static int my_getsigstr (struct ast_channel *chan, char *str, const char *term, int ms)
static void notify_message (char *mailbox_full, int thereornot)
 Send MWI state change.
static unsigned int parse_pointcode (const char *pcstring)
static int pri_active_dchan_fd (struct dahdi_pri *pri)
static int pri_assign_bearer (struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
static int pri_check_restart (struct dahdi_pri *pri)
static int pri_create_spanmap (int span, int trunkgroup, int logicalspan)
static int pri_create_trunkgroup (int trunkgroup, int *channels)
static void * pri_dchannel (void *vpri)
static struct dahdi_pvtpri_find_crv (struct dahdi_pri *pri, int crv)
static int pri_find_dchan (struct dahdi_pri *pri)
static int pri_find_empty_chan (struct dahdi_pri *pri, int backwards)
static int pri_find_principle (struct dahdi_pri *pri, int channel)
static int pri_fixup_principle (struct dahdi_pri *pri, int principle, q931_call *c)
static int pri_grab (struct dahdi_pvt *pvt, struct dahdi_pri *pri)
static int pri_hangup_all (struct dahdi_pvt *p, struct dahdi_pri *pri)
static int pri_is_up (struct dahdi_pri *pri)
static char * pri_order (int level)
static void pri_rel (struct dahdi_pri *pri)
static int pri_resolve_span (int *span, int channel, int offset, struct dahdi_spaninfo *si)
static int process_dahdi (struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
static void process_echocancel (struct dahdi_chan_conf *confp, const char *data, unsigned int line)
static char * redirectingreason2str (int redirectingreason)
static int reload (void)
static int reset_conf (struct dahdi_pvt *p)
static int restart_monitor (void)
static int restore_conference (struct dahdi_pvt *p)
static int restore_gains (struct dahdi_pvt *p)
static int save_conference (struct dahdi_pvt *p)
static int send_callerid (struct dahdi_pvt *p)
static int send_cwcidspill (struct dahdi_pvt *p)
static int set_actual_gain (int fd, int chan, float rxgain, float txgain, int law)
static int set_actual_rxgain (int fd, int chan, float gain, int law)
static int set_actual_txgain (int fd, int chan, float gain, int law)
static int setup_dahdi (int reload)
static int sigtype_to_signalling (int sigtype)
static void ss7_apply_plan_to_number (char *buf, size_t size, const struct dahdi_ss7 *ss7, const char *number, const unsigned nai)
static void ss7_block_cics (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
static int ss7_find_cic (struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
static int ss7_grab (struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
static void ss7_handle_cqm (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
static void ss7_inservice (struct dahdi_ss7 *linkset, int startcic, int endcic, unsigned int dpc)
static void * ss7_linkset (void *data)
static int ss7_pres_scr2cid_pres (char presentation_ind, char screening_ind)
static void ss7_rel (struct dahdi_ss7 *ss7)
static void ss7_reset_linkset (struct dahdi_ss7 *linkset)
static struct dahdi_ss7ss7_resolve_linkset (int linkset)
static void ss7_start_call (struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
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 & SS7" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
struct {
   int   alarm
   char *   name
alarms []
static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}}
static struct ast_module_infoast_module_info = &__mod_info
static struct dahdi_ring_cadence cadences [NUM_CADENCE_MAX]
static int cidrings [NUM_CADENCE_MAX]
 cidrings says in which pause to transmit the cid information, where the first pause is 1, the second pause is 2 and so on.
static const char config [] = "chan_dahdi.conf"
static int cur_adjpointcode = -1
static int cur_cicbeginswith = -1
static int cur_defaultdpc = -1
static int cur_linkset = -1
static int cur_networkindicator = -1
static int cur_pointcode = -1
static int cur_ss7type = -1
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_cli_entry dahdi_ss7_cli []
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 struct dahdi_ss7 linksets [NUM_SPANS]
static int matchdigittimeout = 3000
 How long to wait for an extra digit, if there is an ambiguous match.
static pthread_t monitor_thread = AST_PTHREADT_NULL
 This is the thread for the monitor which checks for input on the channels which are not currently in use.
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
 Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
static ast_cond_t mwi_thread_complete
static int mwi_thread_count = 0
static ast_mutex_t mwi_thread_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int mwilevel = 512
static char mwimonitornotify [PATH_MAX] = ""
static int mwisend_rpas = 0
static int num_cadence = 4
static int num_restart_pending = 0
static int numbufs = 4
static char parkinglot [AST_MAX_EXTENSION] = ""
static int pridebugfd = -1
static ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static char pridebugfilename [1024] = ""
static struct dahdi_pri pris [NUM_SPANS]
static char progzone [10] = ""
static ast_mutex_t restart_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static int ringt_base = DEFAULT_RINGT
 Configured ring timeout base.
struct 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)
#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 330 of file chan_dahdi.c.

Referenced by dahdi_callwait().

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

300 ms

Definition at line 329 of file chan_dahdi.c.

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

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

Referenced by dahdi_handle_event(), and dahdi_new().

#define CHAN_PSEUDO   -2
#define CHANNEL_PSEUDO   -12

Definition at line 151 of file chan_dahdi.c.

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

500 ms

Definition at line 331 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 511 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 512 of file chan_dahdi.c.

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

Definition at line 218 of file chan_dahdi.c.

Referenced by process_dahdi(), and start_pri().

#define DAHDI_OVERLAPDIAL_INCOMING   2
#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(), pri_dchannel(), 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.

Referenced by build_status(), and pri_dchannel().

#define DEFAULT_CIDRINGS   1

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

Note:
Define ZHONE_HACK to cause us to go off hook and then back on hook when the user hangs up to reset the state machine so ring works properly. This is used to be able to support kewlstart by putting the zhone in groundstart mode since their forward disconnect supervision is entirely broken even though their documentation says it isn't and their support is entirely unwilling to provide any assistance with their channel banks even though their web site says they support their products for life.
Define if you want to check the hook state for an FXO (FXS signalled) interface before dialing on it. Certain FXO interfaces always think they're out of service with this method however.

Definition at line 149 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default().

#define DEFAULT_PRI_DEBUG   0

Definition at line 452 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

Definition at line 333 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

#define FORMAT   "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2   "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
#define FORMAT2   "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define GET_CHANNEL (  )     ((p)->bearer ? (p)->bearer->channel : p->channel)

Definition at line 1219 of file chan_dahdi.c.

Referenced by update_conf().

#define HANGUP   1

Definition at line 13350 of file chan_dahdi.c.

Referenced by action_transferhangup(), and dahdi_fake_event().

#define HEADER_LEN   ((HEADER_MS + TRAILER_MS) * 8)
#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 1291 of file chan_dahdi.c.

Referenced by dahdi_indicate(), and ss_thread().

#define LINKSET_FLAG_EXPLICITACM   (1 << 0)

Definition at line 352 of file chan_dahdi.c.

Referenced by process_dahdi(), and ss7_start_call().

#define LINKSTATE_DOWN   (1 << 3)

Definition at line 348 of file chan_dahdi.c.

Referenced by linkset_addsigchan(), and ss7_linkset().

#define LINKSTATE_INALARM   (1 << 0)

Definition at line 345 of file chan_dahdi.c.

Referenced by linkset_addsigchan(), and ss7_linkset().

#define LINKSTATE_STARTING   (1 << 1)

Definition at line 346 of file chan_dahdi.c.

Referenced by ss7_linkset().

#define LINKSTATE_UP   (1 << 2)

Definition at line 347 of file chan_dahdi.c.

Referenced by ss7_linkset().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 326 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

Definition at line 327 of file chan_dahdi.c.

#define MAX_CHANLIST_LEN   80

The length of the parameters list of 'dahdichan'.

Todo:
Move definition of MAX_CHANLIST_LEN to a proper place.

Definition at line 14209 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
#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

Definition at line 332 of file chan_dahdi.c.

Referenced by dahdi_handle_event().

#define NEED_MFDETECT (  )     (((p)->sig == SIG_FEATDMF) || ((p)->sig == SIG_FEATDMF_TA) || ((p)->sig == SIG_E911) || ((p)->sig == SIG_FGC_CAMA) || ((p)->sig == SIG_FGC_CAMAMF) || ((p)->sig == SIG_FEATB))

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

Definition at line 157 of file chan_dahdi.c.

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 1266 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_DCHANS   4

No more than 4 d-channels

Definition at line 203 of file chan_dahdi.c.

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

#define NUM_SPANS   32
#define POLARITY_IDLE   0

Definition at line 470 of file chan_dahdi.c.

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

#define POLARITY_REV   1

Definition at line 471 of file chan_dahdi.c.

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

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

Definition at line 391 of file chan_dahdi.c.

Referenced by pri_dchannel(), and pri_find_principle().

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

Definition at line 393 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 392 of file chan_dahdi.c.

Referenced by pri_dchannel(), and pri_find_principle().

#define PROC_DAHDI_OPT_NOCHAN   (1 << 0)

process_dahdi() - ignore keyword 'channel' and similar

Definition at line 14263 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi().

#define PROC_DAHDI_OPT_NOWARN   (1 << 1)

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

Definition at line 14265 of file chan_dahdi.c.

Referenced by process_dahdi(), and setup_dahdi().

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

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

Definition at line 324 of file chan_dahdi.c.

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

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

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

Definition at line 104 of file chan_dahdi.c.

Referenced by ss_thread().

#define SS7_NAI_DYNAMIC   -1

Definition at line 350 of file chan_dahdi.c.

Referenced by dahdi_call(), and process_dahdi().

#define SUB_CALLWAIT   1
#define SUB_REAL   0
#define SUB_THREEWAY   2
#define tdesc   "DAHDI Telephony w/PRI & SS7"

Definition at line 15499 of file chan_dahdi.c.

#define TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Enumeration Type Documentation

Enumerator:
MWI_SEND_SA 
MWI_SEND_SA_WAIT 
MWI_SEND_PAUSE 
MWI_SEND_SPILL 
MWI_SEND_CLEANUP 
MWI_SEND_DONE 

Definition at line 7915 of file chan_dahdi.c.

07915                     {
07916    MWI_SEND_SA,
07917  MWI_SEND_SA_WAIT,
07918  MWI_SEND_PAUSE,
07919  MWI_SEND_SPILL,
07920  MWI_SEND_CLEANUP,
07921  MWI_SEND_DONE
07922 };


Function Documentation

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

Definition at line 5552 of file chan_dahdi.c.

References ast_channel::_state, 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::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cidcwexpire, 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, dahdi_subchannel::dfd, dahdi_pvt::dialing, event2str(), dahdi_subchannel::f, f, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, dahdi_subchannel::needanswer, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, ast_frame::ptr, dahdi_pvt::radio, ast_frame::samples, ast_frame::src, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

Referenced by dahdi_exception(), and dahdi_read().

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

static void __reg_module ( void   )  [static]

Definition at line 15515 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 14026 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_close_pri_fd(), dahdi_close_ss7_fd(), destroy_all_channels(), iflist, iflock, linksets, master, monlock, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::owner, and pris.

Referenced by load_module(), and unload_module().

14027 {
14028    struct dahdi_pvt *p;
14029 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14030    int i, j;
14031 #endif
14032 
14033 #ifdef HAVE_PRI
14034    for (i = 0; i < NUM_SPANS; i++) {
14035       if (pris[i].master != AST_PTHREADT_NULL) 
14036          pthread_cancel(pris[i].master);
14037    }
14038    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14039    ast_unregister_application(dahdi_send_keypad_facility_app);
14040 #endif
14041 #if defined(HAVE_SS7)
14042    for (i = 0; i < NUM_SPANS; i++) {
14043       if (linksets[i].master != AST_PTHREADT_NULL)
14044          pthread_cancel(linksets[i].master);
14045       }
14046    ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14047 #endif
14048 
14049    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14050    ast_manager_unregister( "DAHDIDialOffhook" );
14051    ast_manager_unregister( "DAHDIHangup" );
14052    ast_manager_unregister( "DAHDITransfer" );
14053    ast_manager_unregister( "DAHDIDNDoff" );
14054    ast_manager_unregister( "DAHDIDNDon" );
14055    ast_manager_unregister("DAHDIShowChannels");
14056    ast_manager_unregister("DAHDIRestart");
14057    ast_channel_unregister(&dahdi_tech);
14058    ast_mutex_lock(&iflock);
14059    /* Hangup all interfaces if they have an owner */
14060    p = iflist;
14061    while (p) {
14062       if (p->owner)
14063          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14064       p = p->next;
14065    }
14066    ast_mutex_unlock(&iflock);
14067    ast_mutex_lock(&monlock);
14068    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14069       pthread_cancel(monitor_thread);
14070       pthread_kill(monitor_thread, SIGURG);
14071       pthread_join(monitor_thread, NULL);
14072    }
14073    monitor_thread = AST_PTHREADT_STOP;
14074    ast_mutex_unlock(&monlock);
14075 
14076    destroy_all_channels();
14077 
14078 #if defined(HAVE_PRI)
14079    for (i = 0; i < NUM_SPANS; i++) {
14080       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14081          pthread_join(pris[i].master, NULL);
14082       for (j = 0; j < NUM_DCHANS; j++) {
14083          dahdi_close_pri_fd(&(pris[i]), j);
14084       }
14085    }
14086 #endif
14087 
14088 #if defined(HAVE_SS7)
14089    for (i = 0; i < NUM_SPANS; i++) {
14090       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14091          pthread_join(linksets[i].master, NULL);
14092       for (j = 0; j < NUM_DCHANS; j++) {
14093          dahdi_close_ss7_fd(&(linksets[i]), j);
14094       }
14095    }
14096 #endif
14097 
14098    ast_cond_destroy(&mwi_thread_complete);
14099    ast_cond_destroy(&ss_thread_complete);
14100    return 0;
14101 }

static void __unreg_module ( void   )  [static]

Definition at line 15515 of file chan_dahdi.c.

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

Definition at line 13456 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(), find_channel(), and dahdi_pvt::owner.

Referenced by load_module().

13457 {
13458    struct dahdi_pvt *p = NULL;
13459    const char *channel = astman_get_header(m, "DAHDIChannel");
13460    const char *number = astman_get_header(m, "Number");
13461    int i;
13462 
13463    if (ast_strlen_zero(channel)) {
13464       astman_send_error(s, m, "No channel specified");
13465       return 0;
13466    }
13467    if (ast_strlen_zero(number)) {
13468       astman_send_error(s, m, "No number specified");
13469       return 0;
13470    }
13471    p = find_channel(atoi(channel));
13472    if (!p) {
13473       astman_send_error(s, m, "No such channel");
13474       return 0;
13475    }
13476    if (!p->owner) {
13477       astman_send_error(s, m, "Channel does not have it's owner");
13478       return 0;
13479    }
13480    for (i = 0; i < strlen(number); i++) {
13481       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13482       dahdi_queue_frame(p, &f, NULL); 
13483    }
13484    astman_send_ack(s, m, "DAHDIDialOffhook");
13485    return 0;
13486 }

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

Definition at line 13399 of file chan_dahdi.c.

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

Referenced by load_module().

13400 {
13401    struct dahdi_pvt *p = NULL;
13402    const char *channel = astman_get_header(m, "DAHDIChannel");
13403 
13404    if (ast_strlen_zero(channel)) {
13405       astman_send_error(s, m, "No channel specified");
13406       return 0;
13407    }
13408    p = find_channel(atoi(channel));
13409    if (!p) {
13410       astman_send_error(s, m, "No such channel");
13411       return 0;
13412    }
13413    p->dnd = 0;
13414    astman_send_ack(s, m, "DND Disabled");
13415    return 0;
13416 }

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

Definition at line 13380 of file chan_dahdi.c.

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

Referenced by load_module().

13381 {
13382    struct dahdi_pvt *p = NULL;
13383    const char *channel = astman_get_header(m, "DAHDIChannel");
13384 
13385    if (ast_strlen_zero(channel)) {
13386       astman_send_error(s, m, "No channel specified");
13387       return 0;
13388    }
13389    p = find_channel(atoi(channel));
13390    if (!p) {
13391       astman_send_error(s, m, "No such channel");
13392       return 0;
13393    }
13394    p->dnd = 1;
13395    astman_send_ack(s, m, "DND Enabled");
13396    return 0;
13397 }

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

Definition at line 12673 of file chan_dahdi.c.

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

Referenced by load_module().

12674 {
12675    if (dahdi_restart() != 0) {
12676       astman_send_error(s, m, "Failed rereading DAHDI configuration");
12677       return 1;
12678    }
12679    astman_send_ack(s, m, "DAHDIRestart: Success");
12680    return 0;
12681 }

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

Definition at line 13488 of file chan_dahdi.c.

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

Referenced by load_module().

13489 {
13490    struct dahdi_pvt *tmp = NULL;
13491    const char *id = astman_get_header(m, "ActionID");
13492    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13493    char idText[256] = "";
13494    int channels = 0;
13495    int dahdichanquery = -1;
13496    if (!ast_strlen_zero(dahdichannel)) {
13497       dahdichanquery = atoi(dahdichannel);
13498    }
13499 
13500    astman_send_ack(s, m, "DAHDI channel status will follow");
13501    if (!ast_strlen_zero(id))
13502       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13503 
13504    ast_mutex_lock(&iflock);
13505    
13506    tmp = iflist;
13507    while (tmp) {
13508       if (tmp->channel > 0) {
13509          int alm = get_alarms(tmp);
13510 
13511          /* If a specific channel is queried for, only deliver status for that channel */
13512          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13513             continue;
13514 
13515          channels++;
13516          if (tmp->owner) {
13517             /* Add data if we have a current call */
13518             astman_append(s,
13519                "Event: DAHDIShowChannels\r\n"
13520                "DAHDIChannel: %d\r\n"
13521                "Channel: %s\r\n"
13522                "Uniqueid: %s\r\n"
13523                "AccountCode: %s\r\n"
13524                "Signalling: %s\r\n"
13525                "SignallingCode: %d\r\n"
13526                "Context: %s\r\n"
13527                "DND: %s\r\n"
13528                "Alarm: %s\r\n"
13529                "%s"
13530                "\r\n",
13531                tmp->channel, 
13532                tmp->owner->name,
13533                tmp->owner->uniqueid,
13534                tmp->owner->accountcode,
13535                sig2str(tmp->sig), 
13536                tmp->sig,
13537                tmp->context, 
13538                tmp->dnd ? "Enabled" : "Disabled",
13539                alarm2str(alm), idText);
13540          } else {
13541             astman_append(s,
13542                "Event: DAHDIShowChannels\r\n"
13543                "DAHDIChannel: %d\r\n"
13544                "Signalling: %s\r\n"
13545                "SignallingCode: %d\r\n"
13546                "Context: %s\r\n"
13547                "DND: %s\r\n"
13548                "Alarm: %s\r\n"
13549                "%s"
13550                "\r\n",
13551                tmp->channel, sig2str(tmp->sig), tmp->sig, 
13552                tmp->context, 
13553                tmp->dnd ? "Enabled" : "Disabled",
13554                alarm2str(alm), idText);
13555          }
13556       } 
13557 
13558       tmp = tmp->next;
13559    }
13560 
13561    ast_mutex_unlock(&iflock);
13562    
13563    astman_append(s, 
13564       "Event: DAHDIShowChannelsComplete\r\n"
13565       "%s"
13566       "Items: %d\r\n"
13567       "\r\n", 
13568       idText,
13569       channels);
13570    return 0;
13571 }

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

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

Referenced by load_module().

13419 {
13420    struct dahdi_pvt *p = NULL;
13421    const char *channel = astman_get_header(m, "DAHDIChannel");
13422 
13423    if (ast_strlen_zero(channel)) {
13424       astman_send_error(s, m, "No channel specified");
13425       return 0;
13426    }
13427    p = find_channel(atoi(channel));
13428    if (!p) {
13429       astman_send_error(s, m, "No such channel");
13430       return 0;
13431    }
13432    dahdi_fake_event(p,TRANSFER);
13433    astman_send_ack(s, m, "DAHDITransfer");
13434    return 0;
13435 }

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

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

Referenced by load_module().

13438 {
13439    struct dahdi_pvt *p = NULL;
13440    const char *channel = astman_get_header(m, "DAHDIChannel");
13441 
13442    if (ast_strlen_zero(channel)) {
13443       astman_send_error(s, m, "No channel specified");
13444       return 0;
13445    }
13446    p = find_channel(atoi(channel));
13447    if (!p) {
13448       astman_send_error(s, m, "No such channel");
13449       return 0;
13450    }
13451    dahdi_fake_event(p,HANGUP);
13452    astman_send_ack(s, m, "DAHDIHangup");
13453    return 0;
13454 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 1725 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

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

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

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

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

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

Referenced by pri_dchannel().

10854 {
10855    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10856       snprintf(buf, size, "%s", number);
10857       return;
10858    }
10859    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10860       if (size) {
10861          *buf = '\0';
10862       }
10863       return;
10864    }
10865    switch (plan) {
10866    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10867       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10868       break;
10869    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10870       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10871       break;
10872    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10873       snprintf(buf, size, "%s%s", pri->localprefix, number);
10874       break;
10875    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10876       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10877       break;
10878    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10879       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10880       break;
10881    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10882       snprintf(buf, size, "%s", number);
10883       break;
10884    }
10885 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

Definition at line 4499 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, LOG_WARNING, dahdi_subchannel::owner, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and unalloc_sub().

Referenced by dahdi_handle_event().

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

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

Definition at line 9284 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_subchannel::dfd, dahdi_pvt::dnd, errno, dahdi_pvt::group, dahdi_pvt::guardtime, dahdi_subchannel::inthreeway, dahdi_pvt::locallyblocked, LOG_WARNING, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_subchannel::owner, 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, dahdi_pvt::ss7, dahdi_pvt::ss7call, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, and dahdi_pvt::subs.

Referenced by __ast_string_field_ptr_build_va(), and dahdi_request().

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

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

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

Referenced by process_dahdi().

14120 {
14121    char *c, *chan;
14122    int x, start, finish;
14123    struct dahdi_pvt *tmp;
14124 #ifdef HAVE_PRI
14125    struct dahdi_pri *pri;
14126    int trunkgroup, y;
14127 #endif
14128    
14129    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14130       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14131       return -1;
14132    }
14133 
14134    c = ast_strdupa(value);
14135 
14136 #ifdef HAVE_PRI
14137    pri = NULL;
14138    if (iscrv) {
14139       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14140          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14141          return -1;
14142       }
14143       if (trunkgroup < 1) {
14144          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14145          return -1;
14146       }
14147       c += y;
14148       for (y = 0; y < NUM_SPANS; y++) {
14149          if (pris[y].trunkgroup == trunkgroup) {
14150             pri = pris + y;
14151             break;
14152          }
14153       }
14154       if (!pri) {
14155          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14156          return -1;
14157       }
14158    }
14159 #endif         
14160 
14161    while ((chan = strsep(&c, ","))) {
14162       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14163          /* Range */
14164       } else if (sscanf(chan, "%30d", &start)) {
14165          /* Just one */
14166          finish = start;
14167       } else if (!strcasecmp(chan, "pseudo")) {
14168          finish = start = CHAN_PSEUDO;
14169          if (found_pseudo)
14170             *found_pseudo = 1;
14171       } else {
14172          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14173          return -1;
14174       }
14175       if (finish < start) {
14176          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14177          x = finish;
14178          finish = start;
14179          start = x;
14180       }
14181 
14182       for (x = start; x <= finish; x++) {
14183 #ifdef HAVE_PRI
14184          tmp = mkintf(x, conf, pri, reload);
14185 #else       
14186          tmp = mkintf(x, conf, NULL, reload);
14187 #endif         
14188 
14189          if (tmp) {
14190 #ifdef HAVE_PRI
14191                if (pri)
14192                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14193                else
14194 #endif
14195                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14196          } else {
14197             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14198                (reload == 1) ? "reconfigure" : "register", value);
14199             return -1;
14200          }
14201       }
14202    }
14203 
14204    return 0;
14205 }

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

Definition at line 12304 of file chan_dahdi.c.

References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

12305 {
12306    if (!s || len < 1) {
12307       return;
12308    }
12309    s[0] = '\0';
12310    if (status & DCHAN_PROVISIONED)
12311       strncat(s, "Provisioned, ", len - strlen(s) - 1);
12312    if (!(status & DCHAN_NOTINALARM))
12313       strncat(s, "In Alarm, ", len - strlen(s) - 1);
12314    if (status & DCHAN_UP)
12315       strncat(s, "Up", len - strlen(s) - 1);
12316    else
12317       strncat(s, "Down", len - strlen(s) - 1);
12318    if (active)
12319       strncat(s, ", Active", len - strlen(s) - 1);
12320    else
12321       strncat(s, ", Standby", len - strlen(s) - 1);
12322    s[len - 1] = '\0';
12323 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 2180 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::cid_rxgain, dahdi_subchannel::dfd, 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().

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

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

Definition at line 7767 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

07768 {
07769    int x;
07770    int sum = 0;
07771 
07772    if (!len)
07773       return 0;
07774 
07775    for (x = 0; x < len; x++)
07776       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07777 
07778    return sum / len;
07779 }

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

Definition at line 9401 of file chan_dahdi.c.

References ast_log(), ast_malloc, ast_mutex_init(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_open(), dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, errno, iflist, dahdi_pvt::lock, LOG_ERROR, LOG_WARNING, dahdi_pvt::next, dahdi_pvt::prev, SUB_REAL, and dahdi_pvt::subs.

Referenced by dahdi_request().

09402 {
09403    struct dahdi_pvt *p;
09404    struct dahdi_bufferinfo bi;
09405    int res;
09406    
09407    if ((p = ast_malloc(sizeof(*p)))) {
09408       memcpy(p, src, sizeof(struct dahdi_pvt));
09409       ast_mutex_init(&p->lock);
09410       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09411       /* Allocate a dahdi structure */
09412       if (p->subs[SUB_REAL].dfd < 0) {
09413          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09414          destroy_dahdi_pvt(&p);
09415          return NULL;
09416       }
09417       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09418       if (!res) {
09419          bi.txbufpolicy = src->buf_policy;
09420          bi.rxbufpolicy = src->buf_policy;
09421          bi.numbufs = src->buf_no;
09422          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09423          if (res < 0) {
09424             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09425          }
09426       } else
09427          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09428    }
09429    p->destroy = 1;
09430    p->next = iflist;
09431    p->prev = NULL;
09432    iflist = p;
09433    if (iflist->next)
09434       iflist->next->prev = p;
09435    return p;
09436 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

Definition at line 4551 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event().

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

static unsigned char cid_pres2ss7pres ( int  cid_pres  )  [static]

Definition at line 2432 of file chan_dahdi.c.

Referenced by dahdi_call().

02433 {
02434     return (cid_pres >> 5) & 0x03;
02435 }

static unsigned char cid_pres2ss7screen ( int  cid_pres  )  [static]

Definition at line 2437 of file chan_dahdi.c.

Referenced by dahdi_call().

02438 {
02439    return cid_pres & 0x03;
02440 }

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

Definition at line 12129 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

12130 {
12131    return complete_span_helper(line,word,pos,state,3);
12132 }

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

Definition at line 12134 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_no_debug(), and handle_pri_really_debug().

12135 {
12136    return complete_span_helper(line,word,pos,state,4);
12137 }

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

Definition at line 12110 of file chan_dahdi.c.

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

Referenced by complete_span_4(), and complete_span_5().

12111 {
12112    int which, span;
12113    char *ret = NULL;
12114 
12115    if (pos != rpos)
12116       return ret;
12117 
12118    for (which = span = 0; span < NUM_SPANS; span++) {
12119       if (pris[span].pri && ++which > state) {
12120          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
12121             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12122          }
12123          break;
12124       }
12125    }
12126    return ret;
12127 }

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

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

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

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

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

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

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 3739 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_subchannel::inthreeway, dahdi_pvt::lock, LOG_WARNING, 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, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), and ast_channel::tech_pvt.

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

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

References ast_channel::_state, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_frfree, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), AST_STATE_RINGING, ast_verb, ast_waitfor_n(), ast_write(), dahdi_pvt::call, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, dahdi_disable_ec(), dahdi_enable_ec(), dahdi_get_index(), dahdi_link(), dahdi_unlink(), dahdi_subchannel::dfd, disable_dtmf_detect(), dahdi_pvt::echocanbridged, enable_dtmf_detect(), f, ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, master, 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().

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

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

Definition at line 2443 of file chan_dahdi.c.

References ast_channel::_state, dahdi_pvt::answeronpolarityswitch, 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_tvnow(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::call_ref_pc, dahdi_ss7::called_nai, dahdi_ss7::calling_nai, dahdi_pvt::callwait_name, dahdi_pvt::callwait_num, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitrings, dahdi_pvt::channel, dahdi_pvt::cic, ast_channel::cid, ast_callerid::cid_ani2, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_pres, cid_pres2ss7pres(), cid_pres2ss7screen(), 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::dpc, dahdi_pvt::echobreak, dahdi_pvt::echorest, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::finaldial, dahdi_pvt::gen_add_nai, dahdi_pvt::gen_add_num_plan, dahdi_pvt::gen_add_pres_ind, dahdi_pvt::gen_add_type, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hidecallerid, dahdi_pvt::hidecalleridname, dahdi_pri::internationalprefix, dahdi_ss7::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, dahdi_pvt::lspi_ident, MAX_CALLERID_SIZE, dahdi_pri::nationalprefix, dahdi_ss7::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_pvt::polaritydelaytv, 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_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), SS7_NAI_DYNAMIC, ss7_rel(), dahdi_pvt::ss7call, 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.

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

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

static struct dahdi_chan_conf dahdi_chan_conf_default ( void   )  [static, read]

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

Definition at line 1093 of file chan_dahdi.c.

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

Referenced by process_dahdi(), and setup_dahdi().

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

static void dahdi_close ( int  fd  )  [static]

Definition at line 1483 of file chan_dahdi.c.

Referenced by dahdi_close_pri_fd(), dahdi_close_ss7_fd(), and dahdi_close_sub().

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

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

Definition at line 1496 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

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

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

static void dahdi_close_ss7_fd ( struct dahdi_ss7 ss7,
int  fd_num 
) [static]

Definition at line 1504 of file chan_dahdi.c.

References dahdi_close(), and dahdi_ss7::fds.

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

01505 {
01506    dahdi_close(ss7->fds[fd_num]);
01507    ss7->fds[fd_num] = -1;
01508 }

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

Definition at line 1489 of file chan_dahdi.c.

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

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

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

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

Definition at line 2224 of file chan_dahdi.c.

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

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

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

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

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

12482 {
12483    int channel;
12484    int ret;
12485    switch (cmd) {
12486    case CLI_INIT:
12487       e->command = "dahdi destroy channel";
12488       e->usage = 
12489          "Usage: dahdi destroy channel <chan num>\n"
12490          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12491       return NULL;
12492    case CLI_GENERATE:
12493       return NULL;   
12494    }
12495    if (a->argc != 4)
12496       return CLI_SHOWUSAGE;
12497    
12498    channel = atoi(a->argv[3]);
12499    ret = dahdi_destroy_channel_bynum(channel);
12500    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12501 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

Definition at line 8077 of file chan_dahdi.c.

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

Referenced by dahdi_destroy_channel(), and do_monitor().

08078 {
08079    struct dahdi_pvt *tmp = NULL;
08080    struct dahdi_pvt *prev = NULL;
08081 
08082    tmp = iflist;
08083    while (tmp) {
08084       if (tmp->channel == channel) {
08085          int x = DAHDI_FLASH;
08086          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 */
08087          destroy_channel(prev, tmp, 1);
08088          ast_module_unref(ast_module_info->self);
08089          return RESULT_SUCCESS;
08090       }
08091       prev = tmp;
08092       tmp = tmp->next;
08093    }
08094    return RESULT_FAILURE;
08095 }

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

Definition at line 1591 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, dahdi_get_index(), dahdi_subchannel::dfd, 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.

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

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

Definition at line 1653 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::begindigit, dahdi_get_index(), dahdi_subchannel::dfd, 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.

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

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2053 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, 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().

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

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

06541 {
06542    /* Do not disturb */
06543    dahdichan->dnd = on;
06544    ast_verb(3, "%s DND on channel %d\n", 
06545          on? "Enabled" : "Disabled",
06546          dahdichan->channel);
06547    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
06548          "Channel: DAHDI/%d\r\n"
06549          "Status: %s\r\n", dahdichan->channel,
06550          on? "enabled" : "disabled");
06551 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2004 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, dahdi_subchannel::dfd, 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(), pri_dchannel(), ss7_linkset(), ss7_start_call(), and ss_thread().

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

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

Definition at line 5658 of file chan_dahdi.c.

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

05659 {
05660    struct dahdi_pvt *p = ast->tech_pvt;
05661    struct ast_frame *f;
05662    ast_mutex_lock(&p->lock);
05663    f = __dahdi_exception(ast);
05664    ast_mutex_unlock(&p->lock);
05665    return f;
05666 }

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

Definition at line 13352 of file chan_dahdi.c.

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

Referenced by action_transfer(), and action_transferhangup().

13353 {
13354    if (p) {
13355       switch (mode) {
13356          case TRANSFER:
13357             p->fake_event = DAHDI_EVENT_WINKFLASH;
13358             break;
13359          case HANGUP:
13360             p->fake_event = DAHDI_EVENT_ONHOOK;
13361             break;
13362          default:
13363             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
13364       }
13365    }
13366    return 0;
13367 }

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

Definition at line 4443 of file chan_dahdi.c.

References ast_channel::_state, AST_CONTROL_RINGING, ast_debug, ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RINGING, dahdi_pvt::channel, dahdi_indicate(), dahdi_unlink(), dahdi_pvt::lock, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

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

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

Definition at line 4020 of file chan_dahdi.c.

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

04021 {
04022    struct dahdi_pvt *p = chan->tech_pvt;
04023    
04024    if (!strcasecmp(data, "rxgain")) {
04025       ast_mutex_lock(&p->lock);
04026       snprintf(buf, len, "%f", p->rxgain);
04027       ast_mutex_unlock(&p->lock);   
04028    } else if (!strcasecmp(data, "txgain")) {
04029       ast_mutex_lock(&p->lock);
04030       snprintf(buf, len, "%f", p->txgain);
04031       ast_mutex_unlock(&p->lock);   
04032    } else {
04033       ast_copy_string(buf, "", len);
04034    }
04035    return 0;
04036 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 303 of file chan_dahdi.c.

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

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

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

Definition at line 1297 of file chan_dahdi.c.

References ast_log(), LOG_WARNING, dahdi_subchannel::owner, 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().

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

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

Definition at line 4604 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, LOG_WARNING, ast_channel::macrocontext, 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().

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

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

< Digits (or equivalent) have been dialed

< Remote end is ringing

< Line is up

< Line is ringing

< Channel is down and available

< Channel is down, but reserved

< Channel is off hook

< Line is busy

< Digits (or equivalent) have been dialed while offhook

< Channel has detected an incoming call and is waiting for ring

< Digits (or equivalent) have been dialed

< Remote end is ringing

< Line is up

< Line is ringing

Definition at line 4681 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, alloc_sub(), dahdi_pvt::answeronpolarityswitch, ast_bridged_channel(), AST_CAUSE_NO_ANSWER, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_NULL, ast_free, ast_hangup(), ast_log(), ast_pthread_create_detached, ast_queue_control(), ast_queue_control_data(), ast_queue_hangup_with_cause(), ast_setstate(), ast_softhangup(), AST_SOFTHANGUP_DEV, AST_SOFTHANGUP_EXPLICIT, AST_STATE_BUSY, AST_STATE_DIALING, AST_STATE_DIALING_OFFHOOK, AST_STATE_DOWN, AST_STATE_OFFHOOK, 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, dahdi_pvt::callprogress, CALLPROGRESS_PROGRESS, dahdi_pvt::callwaitcas, dahdi_pvt::callwaitingrepeat, CANPROGRESSDETECT, ast_channel::cdr, chan, dahdi_pvt::channel, CHANNEL_DEADLOCK_AVOIDANCE, check_for_conference(), ast_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_ani2, dahdi_pvt::cid_name, ast_callerid::cid_name, cid_name, dahdi_pvt::cid_num, ast_callerid::cid_num, cid_num, dahdi_pvt::cidcwexpire, 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::dialednone, dahdi_pvt::dialing, DLA_LOCK, DLA_UNLOCK, dahdi_pvt::dop, dahdi_pvt::dsp, 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, LOG_WARNING, ast_frame::mallocd, manager_event, MIN_MS_SINCE_FLASH, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, dahdi_subchannel::needanswer, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, option_debug, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_subchannel::owner, dahdi_pvt::owner, ast_channel::pbx, dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::polaritydelaytv, dahdi_pvt::polarityonanswerdelay, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, dahdi_pvt::ringt_base, S_OR, ast_frame::samples, save_conference(), dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, ast_frame::src, ss_thread(), SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, ast_frame::subclass, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, dahdi_pvt::threewaycalling, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, unalloc_sub(), update_conf(), and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 3379 of file chan_dahdi.c.

References ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, ast_bridged_channel(), ast_channel_setoption(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_free(), ast_dsp_set_digitmode(), ast_free, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_AUDIO_MODE, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_queue_control(), ast_queue_control_data(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingrepeat, dahdi_pvt::channel, dahdi_pvt::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidcwexpire, dahdi_pvt::cidrings, dahdi_pvt::cidspill, dahdi_pvt::confirmanswer, dahdi_confmute(), dahdi_disable_ec(), dahdi_get_index(), dahdi_set_hook(), dahdi_setlinear(), dahdi_pvt::destroy, destroy_channel(), dahdi_subchannel::dfd, dahdi_pvt::dialing, dahdi_pvt::didtdd, dahdi_pvt::digital, dahdi_pvt::distinctivering, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, errno, dahdi_pvt::exten, dahdi_pvt::faxhandled, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_pvt::muting, 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, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, swap_subs(), ast_channel::tech_pvt, unalloc_sub(), and update_conf().

Referenced by pri_dchannel().

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

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

Definition at line 6075 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, 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, LOG_WARNING, dahdi_pvt::mohinterpret, 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, dahdi_ss7::ss7, dahdi_pvt::ss7, ss7_grab(), ss7_rel(), dahdi_pvt::ss7call, SUB_REAL, dahdi_pvt::subs, and ast_channel::tech_pvt.

Referenced by dahdi_fixup().

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

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

Definition at line 4095 of file chan_dahdi.c.

References ast_debug, ast_log(), dahdi_pvt::channel, LOG_WARNING, dahdi_pvt::master, MAX_SLAVES, and dahdi_pvt::slaves.

Referenced by dahdi_bridge().

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

static void dahdi_loopback ( struct dahdi_pvt p,
int  enable 
) [static]

Definition at line 9816 of file chan_dahdi.c.

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

Referenced by ss7_linkset().

09817 {
09818    if (p->loopedback != enable) {
09819       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09820          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09821          return;
09822       }
09823       p->loopedback = enable;
09824    }
09825 }

static struct ast_channel * dahdi_new ( struct dahdi_pvt i,
int  state,
int  startpbx,
int  idx,
int  law,
int  transfercapability 
) [static, read]

Definition at line 6302 of file chan_dahdi.c.

References accountcode, dahdi_pvt::accountcode, dahdi_pvt::adsi, ast_channel::adsicpe, dahdi_pvt::alreadyhungup, ast_channel::amaflags, dahdi_pvt::amaflags, AST_ADSI_UNAVAILABLE, ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), ast_debug, ast_devstate_changed_literal(), ast_dsp_new(), ast_dsp_set_busy_count(), ast_dsp_set_busy_pattern(), ast_dsp_set_call_progress_zone(), ast_dsp_set_digitmode(), ast_dsp_set_features(), AST_FORMAT_ALAW, AST_FORMAT_ULAW, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), ast_random(), ast_state_chan2dev(), AST_STATE_RING, ast_str_alloca, ast_str_set(), ast_strdup, ast_string_field_set, ast_strlen_zero(), AST_TRANS_CAP_DIGITAL, ast_transfercapability2str(), dahdi_pvt::bearer, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, 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_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_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::dnid, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, DSP_FEATURE_BUSY_DETECT, DSP_FEATURE_CALL_PROGRESS, DSP_FEATURE_DIGIT_DETECT, DSP_FEATURE_FAX_DETECT, dahdi_pvt::dsp_features, DSP_PROGRESS_TALK, dahdi_pvt::dtmfrelax, errno, ast_channel::exten, dahdi_pvt::exten, dahdi_pvt::fake_event, global_jbconf, dahdi_pvt::hardwaredtmf, dahdi_pvt::isidlecall, language, dahdi_pvt::language, dahdi_subchannel::linear, LOG_WARNING, dahdi_pvt::muting, ast_variable::name, ast_channel::nativeformats, NEED_MFDETECT, ast_variable::next, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, dahdi_pvt::parkinglot, pbx_builtin_setvar_helper(), dahdi_pvt::pickupgroup, ast_channel::pickupgroup, dahdi_pvt::pri, ast_channel::rawreadformat, ast_channel::rawwriteformat, dahdi_pvt::rdnis, ast_channel::readformat, ast_channel::rings, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSKS, SIG_PRI, SIG_SS7, 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(), pri_dchannel(), and ss7_start_call().

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1436 of file chan_dahdi.c.

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

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

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

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

Definition at line 10755 of file chan_dahdi.c.

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

Referenced by dahdi_restart(), and load_module().

10756 {
10757    int x, y;
10758    int dchan = -1, span = -1;
10759    int dchancount = 0;
10760 
10761    if (pri) {
10762       for (x = 0; x < NUM_SPANS; x++) {
10763          for (y = 0; y < NUM_DCHANS; y++) {
10764             if (pris[x].dchans[y])
10765                dchancount++;
10766 
10767             if (pris[x].dchans[y] == pri)
10768                dchan = y;
10769          }
10770          if (dchan >= 0) {
10771             span = x;
10772             break;
10773          }
10774          dchancount = 0;
10775       }
10776       if ((dchancount > 1) && (span > -1))
10777          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10778       else
10779          ast_log(LOG_ERROR, "%s", s);
10780    } else
10781       ast_log(LOG_ERROR, "%s", s);
10782 
10783    ast_mutex_lock(&pridebugfdlock);
10784 
10785    if (pridebugfd >= 0) {
10786       if (write(pridebugfd, s, strlen(s)) < 0) {
10787          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10788       }
10789    }
10790 
10791    ast_mutex_unlock(&pridebugfdlock);
10792 }

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

Definition at line 10716 of file chan_dahdi.c.

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

Referenced by dahdi_restart(), and load_module().

10717 {
10718    int x, y;
10719    int dchan = -1, span = -1;
10720    int dchancount = 0;
10721 
10722    if (pri) {
10723       for (x = 0; x < NUM_SPANS; x++) {
10724          for (y = 0; y < NUM_DCHANS; y++) {
10725             if (pris[x].dchans[y])
10726                dchancount++;
10727 
10728             if (pris[x].dchans[y] == pri)
10729                dchan = y;
10730          }
10731          if (dchan >= 0) {
10732             span = x;
10733             break;
10734          }
10735          dchancount = 0;
10736       }
10737       if (dchancount > 1 && (span > -1))
10738          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
10739       else
10740          ast_verbose("%s", s);
10741    } else
10742       ast_verbose("%s", s);
10743 
10744    ast_mutex_lock(&pridebugfdlock);
10745 
10746    if (pridebugfd >= 0) {
10747       if (write(pridebugfd, s, strlen(s)) < 0) {
10748          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10749       }
10750    }
10751 
10752    ast_mutex_unlock(&pridebugfdlock);
10753 }

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

Definition at line 1342 of file chan_dahdi.c.

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

Referenced by action_dahdidialoffhook(), pri_dchannel(), and ss7_linkset().

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

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

Definition at line 5668 of file chan_dahdi.c.

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

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

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

Definition at line 9466 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_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::distinctivering, iflist, iflock, dahdi_pvt::inalarm, dahdi_pri::lock, lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), 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().

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

static int dahdi_restart ( void   )  [static]

Definition at line 12532 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_close_ss7_fd(), dahdi_pri_error(), dahdi_pri_message(), dahdi_softhangup_all(), dahdi_ss7_error(), dahdi_ss7_message(), destroy_all_channels(), dahdi_subchannel::dfd, iflist, linksets, lock, LOG_WARNING, dahdi_ss7::master, dahdi_pri::master, master, monlock, mwi_thread_lock, dahdi_pvt::next, NUM_SPANS, dahdi_pri::offset, dahdi_pvt::owner, pris, restart_lock, setup_dahdi(), ss_thread_lock, SUB_REAL, and dahdi_pvt::subs.

Referenced by action_dahdirestart(), and dahdi_restart_cmd().

12533 {
12534 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12535    int i, j;
12536 #endif
12537    int cancel_code;
12538    struct dahdi_pvt *p;
12539 
12540    ast_mutex_lock(&restart_lock);
12541 
12542    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12543    dahdi_softhangup_all();
12544    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12545 
12546 #if defined(HAVE_PRI)
12547    for (i = 0; i < NUM_SPANS; i++) {
12548       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12549          cancel_code = pthread_cancel(pris[i].master);
12550          pthread_kill(pris[i].master, SIGURG);
12551          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12552          pthread_join(pris[i].master, NULL);
12553          ast_debug(4, "Joined thread of span %d\n", i);
12554       }
12555    }
12556 #endif
12557 
12558 #if defined(HAVE_SS7)
12559    for (i = 0; i < NUM_SPANS; i++) {
12560       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12561          cancel_code = pthread_cancel(linksets[i].master);
12562          pthread_kill(linksets[i].master, SIGURG);
12563          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12564          pthread_join(linksets[i].master, NULL);
12565          ast_debug(4, "Joined thread of span %d\n", i);
12566       }
12567     }
12568 #endif
12569 
12570    ast_mutex_lock(&monlock);
12571    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12572       cancel_code = pthread_cancel(monitor_thread);
12573       pthread_kill(monitor_thread, SIGURG);
12574       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12575       pthread_join(monitor_thread, NULL);
12576       ast_debug(4, "Joined monitor thread\n");
12577    }
12578    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12579 
12580    ast_mutex_lock(&mwi_thread_lock);
12581    while (mwi_thread_count > 0) {
12582       ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12583       ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12584    }
12585    ast_mutex_unlock(&mwi_thread_lock);
12586    ast_mutex_lock(&ss_thread_lock);
12587    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12588       int x = DAHDI_FLASH;
12589       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12590 
12591       for (p = iflist; p; p = p->next) {
12592          if (p->owner)
12593             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 */      
12594          }
12595          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12596       }
12597 
12598    /* ensure any created channels before monitor threads were stopped are hungup */
12599    dahdi_softhangup_all();
12600    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12601    destroy_all_channels();
12602    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12603 
12604    ast_mutex_unlock(&monlock);
12605 
12606 #ifdef HAVE_PRI
12607    for (i = 0; i < NUM_SPANS; i++) {
12608       for (j = 0; j < NUM_DCHANS; j++)
12609          dahdi_close_pri_fd(&(pris[i]), j);
12610    }
12611 
12612    memset(pris, 0, sizeof(pris));
12613    for (i = 0; i < NUM_SPANS; i++) {
12614       ast_mutex_init(&pris[i].lock);
12615       pris[i].offset = -1;
12616       pris[i].master = AST_PTHREADT_NULL;
12617       for (j = 0; j < NUM_DCHANS; j++)
12618          pris[i].fds[j] = -1;
12619       }
12620    pri_set_error(dahdi_pri_error);
12621    pri_set_message(dahdi_pri_message);
12622 #endif
12623 #ifdef HAVE_SS7
12624    for (i = 0; i < NUM_SPANS; i++) {
12625       for (j = 0; j < NUM_DCHANS; j++)
12626          dahdi_close_ss7_fd(&(linksets[i]), j);
12627    }
12628 
12629    memset(linksets, 0, sizeof(linksets));
12630    for (i = 0; i < NUM_SPANS; i++) {
12631       ast_mutex_init(&linksets[i].lock);
12632       linksets[i].master = AST_PTHREADT_NULL;
12633       for (j = 0; j < NUM_DCHANS; j++)
12634          linksets[i].fds[j] = -1;
12635    }
12636    ss7_set_error(dahdi_ss7_error);
12637    ss7_set_message(dahdi_ss7_message);
12638 #endif
12639 
12640    if (setup_dahdi(2) != 0) {
12641       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12642       ast_mutex_unlock(&ss_thread_lock);
12643       return 1;
12644    }
12645    ast_mutex_unlock(&ss_thread_lock);
12646    ast_mutex_unlock(&restart_lock);
12647    return 0;
12648 }

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

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

12651 {
12652    switch (cmd) {
12653    case CLI_INIT:
12654       e->command = "dahdi restart";
12655       e->usage = 
12656          "Usage: dahdi restart\n"
12657          "  Restarts the DAHDI channels: destroys them all and then\n"
12658          "  re-reads them from chan_dahdi.conf.\n"
12659          "  Note that this will STOP any running CALL on DAHDI channels.\n"
12660          "";
12661       return NULL;
12662    case CLI_GENERATE:
12663       return NULL;
12664    }
12665    if (a->argc != 2)
12666       return CLI_SHOWUSAGE;
12667 
12668    if (dahdi_restart() != 0)
12669       return CLI_FAILURE;
12670    return CLI_SUCCESS;
12671 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

Definition at line 4465 of file chan_dahdi.c.

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

Referenced by __dahdi_exception(), and dahdi_handle_event().

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

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

Definition at line 3260 of file chan_dahdi.c.

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

Referenced by load_module().

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

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

Definition at line 15381 of file chan_dahdi.c.

References ASCII_BYTES_PER_CHAR, ast_check_hangup(), ast_debug, ast_free, AST_LAW, ast_log(), ast_malloc, buf, dahdi_pvt::channel, dahdi_get_index(), dahdi_subchannel::dfd, END_SILENCE_LEN, errno, HEADER_LEN, HEADER_MS, len(), LOG_ERROR, LOG_WARNING, 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.

15382 {
15383 #define  END_SILENCE_LEN 400
15384 #define  HEADER_MS 50
15385 #define  TRAILER_MS 5
15386 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15387 #define  ASCII_BYTES_PER_CHAR 80
15388 
15389    unsigned char *buf,*mybuf;
15390    struct dahdi_pvt *p = c->tech_pvt;
15391    struct pollfd fds[1];
15392    int size,res,fd,len,x;
15393    int bytes=0;
15394    /* Initial carrier (imaginary) */
15395    float cr = 1.0;
15396    float ci = 0.0;
15397    float scont = 0.0;
15398    int idx;
15399 
15400    idx = dahdi_get_index(c, p, 0);
15401    if (idx < 0) {
15402       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
15403       return -1;
15404    }
15405    if (!text[0]) return(0); /* if nothing to send, dont */
15406    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
15407    if (p->mate) 
15408       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15409    else
15410       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15411    if (!buf)
15412       return -1;
15413    mybuf = buf;
15414    if (p->mate) {
15415       int codec = AST_LAW(p);
15416       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
15417          PUT_CLID_MARKMS;
15418       }
15419       /* Put actual message */
15420       for (x = 0; text[x]; x++) {
15421          PUT_CLID(text[x]);
15422       }
15423       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
15424          PUT_CLID_MARKMS;
15425       }
15426       len = bytes;
15427       buf = mybuf;
15428    } else {
15429       len = tdd_generate(p->tdd, buf, text);
15430       if (len < 1) {
15431          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15432          ast_free(mybuf);
15433          return -1;
15434       }
15435    }
15436    memset(buf + len, 0x7f, END_SILENCE_LEN);
15437    len += END_SILENCE_LEN;
15438    fd = p->subs[idx].dfd;
15439    while (len) {
15440       if (ast_check_hangup(c)) {
15441          ast_free(mybuf);
15442          return -1;
15443       }
15444       size = len;
15445       if (size > READ_SIZE)
15446          size = READ_SIZE;
15447       fds[0].fd = fd;
15448       fds[0].events = POLLOUT | POLLPRI;
15449       fds[0].revents = 0;
15450       res = poll(fds, 1, -1);
15451       if (!res) {
15452          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15453          continue;
15454       }
15455         /* if got exception */
15456       if (fds[0].revents & POLLPRI) {
15457          ast_free(mybuf);
15458          return -1;
15459       }
15460       if (!(fds[0].revents & POLLOUT)) {
15461          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15462          continue;
15463       }
15464       res = write(fd, buf, size);
15465       if (res != size) {
15466          if (res == -1) {
15467             ast_free(mybuf);
15468             return -1;
15469          }
15470          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15471          break;
15472       }
15473       len -= size;
15474       buf += size;
15475    }
15476    ast_free(mybuf);
15477    return(0);
15478 }

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

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

13280 {
13281    int channel;
13282    int on;
13283    struct dahdi_pvt *dahdi_chan = NULL;
13284 
13285    switch (cmd) {
13286    case CLI_INIT:
13287       e->command = "dahdi set dnd";
13288       e->usage = 
13289          "Usage: dahdi set dnd <chan#> <on|off>\n"
13290          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13291          "  Changes take effect immediately.\n"
13292          "  <chan num> is the channel number\n"
13293          "  <on|off> Enable or disable DND mode?\n"
13294          ;
13295       return NULL;
13296    case CLI_GENERATE:
13297       return NULL;   
13298    }
13299 
13300    if (a->argc != 5)
13301       return CLI_SHOWUSAGE;
13302 
13303    if ((channel = atoi(a->argv[3])) <= 0) {
13304       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13305       return CLI_SHOWUSAGE;
13306    }
13307    
13308    if (ast_true(a->argv[4]))
13309       on = 1;
13310    else if (ast_false(a->argv[4]))
13311       on = 0;
13312    else {
13313       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13314       return CLI_SHOWUSAGE;
13315    }
13316 
13317    ast_mutex_lock(&iflock);
13318    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13319       if (dahdi_chan->channel != channel)
13320          continue;
13321 
13322       /* Found the channel. Actually set it */
13323       dahdi_dnd(dahdi_chan, on);
13324       break;
13325    }
13326    ast_mutex_unlock(&iflock);
13327 
13328    if (!dahdi_chan) {
13329       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13330       return CLI_FAILURE;
13331    }
13332 
13333    return CLI_SUCCESS;
13334 }

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

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

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

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

Definition at line 13136 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, errno, ast_cli_args::fd, iflist, iflock, dahdi_pvt::next, SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.

13137 {
13138    int channel;
13139    int gain;
13140    int tx;
13141    struct dahdi_hwgain hwgain;
13142    struct dahdi_pvt *tmp = NULL;
13143 
13144    switch (cmd) {
13145    case CLI_INIT:
13146       e->command = "dahdi set hwgain";
13147       e->usage = 
13148          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
13149          "  Sets the hardware gain on a a given channel, overriding the\n"
13150          "   value provided at module loadtime, whether the channel is in\n"
13151          "   use or not.  Changes take effect immediately.\n"
13152          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13153          "   <chan num> is the channel number relative to the device\n"
13154          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13155       return NULL;
13156    case CLI_GENERATE:
13157       return NULL;   
13158    }
13159 
13160    if (a->argc != 6)
13161       return CLI_SHOWUSAGE;
13162    
13163    if (!strcasecmp("rx", a->argv[3]))
13164       tx = 0; /* rx */
13165    else if (!strcasecmp("tx", a->argv[3]))
13166       tx = 1; /* tx */
13167    else
13168       return CLI_SHOWUSAGE;
13169 
13170    channel = atoi(a->argv[4]);
13171    gain = atof(a->argv[5])*10.0;
13172 
13173    ast_mutex_lock(&iflock);
13174 
13175    for (tmp = iflist; tmp; tmp = tmp->next) {
13176 
13177       if (tmp->channel != channel)
13178          continue;
13179 
13180       if (tmp->subs[SUB_REAL].dfd == -1)
13181          break;
13182 
13183       hwgain.newgain = gain;
13184       hwgain.tx = tx;
13185       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
13186          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
13187          ast_mutex_unlock(&iflock);
13188          return CLI_FAILURE;
13189       }
13190       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
13191          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
13192       break;
13193    }
13194 
13195    ast_mutex_unlock(&iflock);
13196 
13197    if (tmp)
13198       return CLI_SUCCESS;
13199 
13200    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13201    return CLI_FAILURE;
13202 
13203 }

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

Definition at line 13205 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(), SUB_REAL, dahdi_pvt::subs, and ast_cli_entry::usage.

13206 {
13207    int channel;
13208    float gain;
13209    int tx;
13210    int res;
13211    ast_mutex_t *lock;
13212    struct dahdi_pvt *tmp = NULL;
13213 
13214    switch (cmd) {
13215    case CLI_INIT:
13216       e->command = "dahdi set swgain";
13217       e->usage = 
13218          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13219          "  Sets the software gain on a a given channel, overriding the\n"
13220          "   value provided at module loadtime, whether the channel is in\n"
13221          "   use or not.  Changes take effect immediately.\n"
13222          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13223          "   <chan num> is the channel number relative to the device\n"
13224          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13225       return NULL;
13226    case CLI_GENERATE:
13227       return NULL;   
13228    }
13229 
13230    lock = &iflock;
13231 
13232    if (a->argc != 6)
13233       return CLI_SHOWUSAGE;
13234    
13235    if (!strcasecmp("rx", a->argv[3]))
13236       tx = 0; /* rx */
13237    else if (!strcasecmp("tx", a->argv[3]))
13238       tx = 1; /* tx */
13239    else
13240       return CLI_SHOWUSAGE;
13241 
13242    channel = atoi(a->argv[4]);
13243    gain = atof(a->argv[5]);
13244 
13245    ast_mutex_lock(lock);
13246    for (tmp = iflist; tmp; tmp = tmp->next) {
13247 
13248       if (tmp->channel != channel)
13249          continue;
13250 
13251       if (tmp->subs[SUB_REAL].dfd == -1)
13252          break;
13253 
13254       if (tx)
13255          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13256       else
13257          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13258 
13259       if (res) {
13260          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13261          ast_mutex_unlock(lock);
13262          return CLI_FAILURE;
13263       }
13264 
13265       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13266          tx ? "tx" : "rx", gain, channel);
13267       break;
13268    }
13269    ast_mutex_unlock(lock);
13270 
13271    if (tmp)
13272       return CLI_SUCCESS;
13273 
13274    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13275    return CLI_FAILURE;
13276 
13277 }

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

Definition at line 9710 of file chan_dahdi.c.

Referenced by pri_dchannel(), and ss7_start_call().

09711 {
09712    return ioctl(dfd, DAHDI_SETLAW, &law);
09713 }

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

Definition at line 1511 of file chan_dahdi.c.

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

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

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

Todo:
XXX This is an abuse of the stack!!

Definition at line 3839 of file chan_dahdi.c.

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

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

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

Definition at line 12807 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::bearer, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call, dahdi_pvt::callwaitcas, dahdi_pvt::channel, dahdi_pvt::cic, 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_pri::crvs, 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, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pri::lock, lock, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::mailbox, dahdi_pvt::master, MAX_SLAVES, ast_variable::name, dahdi_pvt::next, ast_variable::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::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, dahdi_pvt::ss7, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, ast_cli_entry::usage, ast_variable::value, and dahdi_pvt::vars.

12808 {
12809    int channel;
12810    struct dahdi_pvt *tmp = NULL;
12811    struct dahdi_confinfo ci;
12812    struct dahdi_params ps;
12813    int x;
12814    ast_mutex_t *lock;
12815    struct dahdi_pvt *start;
12816 #ifdef HAVE_PRI
12817    char *c;
12818    int trunkgroup;
12819    struct dahdi_pri *pri=NULL;
12820 #endif
12821    switch (cmd) {
12822    case CLI_INIT:
12823       e->command = "dahdi show channel";
12824       e->usage = 
12825          "Usage: dahdi show channel <chan num>\n"
12826          "  Detailed information about a given channel\n";
12827       return NULL;
12828    case CLI_GENERATE:
12829       return NULL;   
12830    }
12831 
12832    lock = &iflock;
12833    start = iflist;
12834 
12835    if (a->argc != 4)
12836       return CLI_SHOWUSAGE;
12837 #ifdef HAVE_PRI
12838    if ((c = strchr(a->argv[3], ':'))) {
12839       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
12840          return CLI_SHOWUSAGE;
12841       if ((trunkgroup < 1) || (channel < 1))
12842          return CLI_SHOWUSAGE;
12843       for (x = 0; x < NUM_SPANS; x++) {
12844          if (pris[x].trunkgroup == trunkgroup) {
12845             pri = pris + x;
12846             break;
12847          }
12848       }
12849       if (pri) {
12850          start = pri->crvs;
12851          lock = &pri->lock;
12852       } else {
12853          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12854          return CLI_FAILURE;
12855       }
12856    } else
12857 #endif
12858       channel = atoi(a->argv[3]);
12859 
12860    ast_mutex_lock(lock);
12861    tmp = start;
12862    while (tmp) {
12863       if (tmp->channel == channel) {
12864 #ifdef HAVE_PRI
12865          if (pri) 
12866             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
12867          else
12868 #endif         
12869          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
12870          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
12871          ast_cli(a->fd, "Span: %d\n", tmp->span);
12872          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
12873          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
12874          ast_cli(a->fd, "Context: %s\n", tmp->context);
12875          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
12876          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
12877          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
12878          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
12879          if (tmp->vars) {
12880             struct ast_variable *v;
12881             ast_cli(a->fd, "Variables:\n");
12882             for (v = tmp->vars ; v ; v = v->next)
12883                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
12884          }
12885          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
12886          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
12887          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
12888          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
12889          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
12890          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)" : "");
12891          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)" : "");
12892          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)" : "");
12893          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
12894          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
12895          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
12896          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
12897          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
12898          if (tmp->busydetect) {
12899 #if defined(BUSYDETECT_TONEONLY)
12900             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
12901 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
12902             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
12903 #endif
12904 #ifdef BUSYDETECT_DEBUG
12905             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
12906 #endif
12907             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
12908             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
12909          }
12910          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
12911          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
12912          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
12913          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
12914          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
12915          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
12916          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
12917          ast_cli(a->fd, "Echo Cancellation:\n");
12918 
12919          if (tmp->echocancel.head.tap_length) {
12920             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
12921             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
12922                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
12923             }
12924             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
12925          } else {
12926             ast_cli(a->fd, "\tnone\n");
12927          }
12928          if (tmp->master)
12929             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
12930          for (x = 0; x < MAX_SLAVES; x++) {
12931             if (tmp->slaves[x])
12932                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
12933          }
12934 #ifdef HAVE_SS7
12935          if (tmp->ss7) {
12936             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
12937          }
12938 #endif
12939 #ifdef HAVE_PRI
12940          if (tmp->pri) {
12941             ast_cli(a->fd, "PRI Flags: ");
12942             if (tmp->resetting)
12943                ast_cli(a->fd, "Resetting ");
12944             if (tmp->call)
12945                ast_cli(a->fd, "Call ");
12946             if (tmp->bearer)
12947                ast_cli(a->fd, "Bearer ");
12948             ast_cli(a->fd, "\n");
12949             if (tmp->logicalspan) 
12950                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
12951             else
12952                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
12953          }
12954             
12955 #endif
12956          memset(&ci, 0, sizeof(ci));
12957          ps.channo = tmp->channel;
12958          if (tmp->subs[SUB_REAL].dfd > -1) {
12959             memset(&ci, 0, sizeof(ci));
12960             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
12961                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
12962             }
12963             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
12964                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
12965             }
12966             memset(&ps, 0, sizeof(ps));
12967             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
12968                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
12969             } else {
12970                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
12971             }
12972          }
12973          ast_mutex_unlock(lock);
12974          return CLI_SUCCESS;
12975       }
12976       tmp = tmp->next;
12977    }
12978    
12979    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
12980    ast_mutex_unlock(lock);
12981    return CLI_FAILURE;
12982 }

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

Definition at line 12683 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_pri::crvs, dahdi_pvt::exten, ast_cli_args::fd, FORMAT, FORMAT2, dahdi_pvt::group, iflist, iflock, dahdi_pvt::language, dahdi_pvt::locallyblocked, dahdi_pri::lock, lock, dahdi_pvt::mohinterpret, dahdi_pvt::next, NUM_SPANS, pris, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.

12684 {
12685 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12686 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12687    unsigned int targetnum = 0;
12688    int filtertype = 0;
12689    struct dahdi_pvt *tmp = NULL;
12690    char tmps[20] = "";
12691    char statestr[20] = "";
12692    char blockstr[20] = "";
12693    ast_mutex_t *lock;
12694    struct dahdi_pvt *start;
12695 #ifdef HAVE_PRI
12696    int trunkgroup;
12697    struct dahdi_pri *pri = NULL;
12698    int x;
12699 #endif
12700    switch (cmd) {
12701    case CLI_INIT:
12702       e->command = "dahdi show channels [trunkgroup|group|context]";
12703       e->usage = 
12704          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12705          "  Shows a list of available channels with optional filtering\n"
12706          "  <group> must be a number between 0 and 63\n";
12707       return NULL;
12708    case CLI_GENERATE:
12709       return NULL;   
12710    }
12711 
12712    lock = &iflock;
12713    start = iflist;
12714 
12715    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12716 
12717    if (!((a->argc == 3) || (a->argc == 5)))
12718       return CLI_SHOWUSAGE;
12719 
12720    if (a->argc == 5) {
12721 #ifdef HAVE_PRI
12722       if (!strcasecmp(a->argv[3], "trunkgroup")) {
12723          /* this option requires no special handling, so leave filtertype to zero */
12724          if ((trunkgroup = atoi(a->argv[4])) < 1)
12725             return CLI_SHOWUSAGE;
12726          for (x = 0; x < NUM_SPANS; x++) {
12727             if (pris[x].trunkgroup == trunkgroup) {
12728                pri = pris + x;
12729                break;
12730             }
12731          }
12732          if (pri) {
12733             start = pri->crvs;
12734             lock = &pri->lock;
12735          } else {
12736             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12737             return CLI_FAILURE;
12738          }
12739       } else
12740 #endif   
12741       if (!strcasecmp(a->argv[3], "group")) {
12742          targetnum = atoi(a->argv[4]);
12743          if ((targetnum < 0) || (targetnum > 63))
12744             return CLI_SHOWUSAGE;
12745          targetnum = 1 << targetnum;
12746          filtertype = 1;
12747       } else if (!strcasecmp(a->argv[3], "context")) {
12748          filtertype = 2;
12749       }
12750    }
12751 
12752    ast_mutex_lock(lock);
12753 #ifdef HAVE_PRI
12754    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12755 #else
12756    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12757 #endif   
12758    
12759    tmp = start;
12760    while (tmp) {
12761       if (filtertype) {
12762          switch(filtertype) {
12763          case 1: /* dahdi show channels group <group> */
12764             if (!(tmp->group & targetnum)) {
12765                tmp = tmp->next;
12766                continue;
12767             }
12768             break;
12769          case 2: /* dahdi show channels context <context> */
12770             if (strcasecmp(tmp->context, a->argv[4])) {
12771                tmp = tmp->next;
12772                continue;
12773             }
12774             break;
12775          default:
12776             ;
12777          }
12778       }
12779       if (tmp->channel > 0) {
12780          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12781       } else
12782          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12783 
12784       if (tmp->locallyblocked)
12785          blockstr[0] = 'L';
12786       else
12787          blockstr[0] = ' ';
12788 
12789       if (tmp->remotelyblocked)
12790          blockstr[1] = 'R';
12791       else
12792          blockstr[1] = ' ';
12793 
12794       blockstr[2] = '\0';
12795 
12796       snprintf(statestr, sizeof(statestr), "%s", "In Service");
12797 
12798       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12799       tmp = tmp->next;
12800    }
12801    ast_mutex_unlock(lock);
12802    return CLI_SUCCESS;
12803 #undef FORMAT
12804 #undef FORMAT2
12805 }

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

Definition at line 13021 of file chan_dahdi.c.

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

13022 {
13023    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
13024    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
13025    int span;
13026    int res;
13027    char alarmstr[50];
13028 
13029    int ctl;
13030    struct dahdi_spaninfo s;
13031 
13032    switch (cmd) {
13033    case CLI_INIT:
13034       e->command = "dahdi show status";
13035       e->usage = 
13036          "Usage: dahdi show status\n"
13037          "       Shows a list of DAHDI cards with status\n";
13038       return NULL;
13039    case CLI_GENERATE:
13040       return NULL;   
13041    }
13042    ctl = open("/dev/dahdi/ctl", O_RDWR);
13043    if (ctl < 0) {
13044       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13045       return CLI_FAILURE;
13046    }
13047    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13048 
13049    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13050       s.spanno = span;
13051       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13052       if (res) {
13053          continue;
13054       }
13055       alarmstr[0] = '\0';
13056       if (s.alarms > 0) {
13057          if (s.alarms & DAHDI_ALARM_BLUE)
13058             strcat(alarmstr, "BLU/");
13059          if (s.alarms & DAHDI_ALARM_YELLOW)
13060             strcat(alarmstr, "YEL/");
13061          if (s.alarms & DAHDI_ALARM_RED)
13062             strcat(alarmstr, "RED/");
13063          if (s.alarms & DAHDI_ALARM_LOOPBACK)
13064             strcat(alarmstr, "LB/");
13065          if (s.alarms & DAHDI_ALARM_RECOVER)
13066             strcat(alarmstr, "REC/");
13067          if (s.alarms & DAHDI_ALARM_NOTOPEN)
13068             strcat(alarmstr, "NOP/");
13069          if (!strlen(alarmstr))
13070             strcat(alarmstr, "UUU/");
13071          if (strlen(alarmstr)) {
13072             /* Strip trailing / */
13073             alarmstr[strlen(alarmstr) - 1] = '\0';
13074          }
13075       } else {
13076          if (s.numchans)
13077             strcpy(alarmstr, "OK");
13078          else
13079             strcpy(alarmstr, "UNCONFIGURED");
13080       }
13081 
13082       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13083             , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13084               s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13085               s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13086               "CAS"
13087             , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13088               s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13089               s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13090               "Unk"
13091             , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13092               s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13093             , lbostr[s.lbo]
13094          );
13095    }
13096    close(ctl);
13097 
13098    return CLI_SUCCESS;
13099 #undef FORMAT
13100 #undef FORMAT2
13101 }

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

Definition at line 13103 of file chan_dahdi.c.

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

13104 {
13105    int pseudo_fd = -1;
13106    struct dahdi_versioninfo vi;
13107 
13108    switch (cmd) {
13109    case CLI_INIT:
13110       e->command = "dahdi show version";
13111       e->usage = 
13112          "Usage: dahdi show version\n"
13113          "       Shows the DAHDI version in use\n";
13114       return NULL;
13115    case CLI_GENERATE:
13116       return NULL;
13117    }
13118    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13119       ast_cli(a->fd, "Failed to open control file to get version.\n");
13120       return CLI_SUCCESS;
13121    }
13122 
13123    strcpy(vi.version, "Unknown");
13124    strcpy(vi.echo_canceller, "Unknown");
13125 
13126    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13127       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13128    else
13129       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13130 
13131    close(pseudo_fd);
13132 
13133    return CLI_SUCCESS;
13134 }

static char* dahdi_sig2str ( int  sig  )  [static]

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

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

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 12503 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, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

12504 {
12505    struct dahdi_pvt *p;
12506 retry:
12507    ast_mutex_lock(&iflock);
12508     for (p = iflist; p; p = p->next) {
12509       ast_mutex_lock(&p->lock);
12510         if (p->owner && !p->restartpending) {
12511          if (ast_channel_trylock(p->owner)) {
12512             if (option_debug > 2)
12513                ast_verbose("Avoiding deadlock\n");
12514             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
12515             ast_mutex_unlock(&p->lock);
12516             ast_mutex_unlock(&iflock);
12517             goto retry;
12518          }
12519          if (option_debug > 2)
12520             ast_verbose("Softhanging up on %s\n", p->owner->name);
12521          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12522          p->restartpending = 1;
12523          num_restart_pending++;
12524          ast_channel_unlock(p->owner);
12525       }
12526       ast_mutex_unlock(&p->lock);
12527     }
12528    ast_mutex_unlock(&iflock);
12529 }

static void dahdi_ss7_error ( struct ss7 *  ss7,
char *  s 
) [static]

Definition at line 10524 of file chan_dahdi.c.

References ast_log(), linksets, LOG_ERROR, and NUM_SPANS.

Referenced by dahdi_restart(), and load_module().

10525 {
10526 #if 0
10527    int i;
10528 
10529    for (i = 0; i < NUM_SPANS; i++)
10530       if (linksets[i].ss7 == ss7)
10531          break;
10532 
10533 #else
10534    ast_log(LOG_ERROR, "%s", s);
10535 #endif
10536 }

static void dahdi_ss7_message ( struct ss7 *  ss7,
char *  s 
) [static]

Definition at line 10509 of file chan_dahdi.c.

References ast_verbose, linksets, and NUM_SPANS.

Referenced by dahdi_restart(), and load_module().

10510 {
10511 #if 0
10512    int i;
10513 
10514    for (i = 0; i < NUM_SPANS; i++)
10515       if (linksets[i].ss7 == ss7)
10516          break;
10517 
10518    ast_verbose("[%d] %s", i+1, s);
10519 #else
10520    ast_verbose("%s", s);
10521 #endif
10522 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2036 of file chan_dahdi.c.

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

Referenced by dahdi_answer(), and dahdi_handle_event().

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

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

Definition at line 4039 of file chan_dahdi.c.

References ast_debug, ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), dahdi_pvt::channel, conf_del(), DEADLOCK_AVOIDANCE, dahdi_pvt::inconference, dahdi_pvt::lock, dahdi_pvt::master, MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, dahdi_pvt::subs, and update_conf().

Referenced by dahdi_bridge(), and dahdi_fixup().

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

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 312 of file chan_dahdi.c.

Referenced by ss_thread().

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

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

Definition at line 6513 of file chan_dahdi.c.

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

Referenced by ss_thread().

06514 {
06515    int j;
06516    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
06517    for (;;)
06518    {
06519          /* set bits of interest */
06520       j = DAHDI_IOMUX_SIGEVENT;
06521           /* wait for some happening */
06522       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
06523          /* exit loop if we have it */
06524       if (j & DAHDI_IOMUX_SIGEVENT) break;
06525    }
06526      /* get the event info */
06527    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
06528    return 0;
06529 }

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

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

05996 {
05997    struct dahdi_pvt *p = ast->tech_pvt;
05998    int res;
05999    int idx;
06000    idx = dahdi_get_index(ast, p, 0);
06001    if (idx < 0) {
06002       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
06003       return -1;
06004    }
06005 
06006 #if 0
06007 #ifdef HAVE_PRI
06008    ast_mutex_lock(&p->lock);
06009    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
06010       if (p->pri->pri) {      
06011          if (!pri_grab(p, p->pri)) {
06012                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
06013                pri_rel(p->pri);
06014          } else
06015                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
06016       }
06017       p->proceeding=1;
06018    }
06019    ast_mutex_unlock(&p->lock);
06020 #endif
06021 #endif
06022    /* Write a frame of (presumably voice) data */
06023    if (frame->frametype != AST_FRAME_VOICE) {
06024       if (frame->frametype != AST_FRAME_IMAGE)
06025          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
06026       return 0;
06027    }
06028    if ((frame->subclass != AST_FORMAT_SLINEAR) && 
06029        (frame->subclass != AST_FORMAT_ULAW) &&
06030        (frame->subclass != AST_FORMAT_ALAW)) {
06031       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
06032       return -1;
06033    }
06034    if (p->dialing) {
06035       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
06036       return 0;
06037    }
06038    if (!p->owner) {
06039       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
06040       return 0;
06041    }
06042    if (p->cidspill) {
06043       ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
06044       return 0;
06045    }
06046    /* Return if it's not valid data */
06047    if (!frame->data.ptr || !frame->datalen)
06048       return 0;
06049 
06050    if (frame->subclass == AST_FORMAT_SLINEAR) {
06051       if (!p->subs[idx].linear) {
06052          p->subs[idx].linear = 1;
06053          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06054          if (res)
06055             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
06056       }
06057       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
06058    } else {
06059       /* x-law already */
06060       if (p->subs[idx].linear) {
06061          p->subs[idx].linear = 0;
06062          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06063          if (res)
06064             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
06065       }
06066       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
06067    }
06068    if (res < 0) {
06069       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
06070       return -1;
06071    } 
06072    return 0;
06073 }

static void destroy_all_channels ( void   )  [static]

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

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

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

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

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

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

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

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

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 1745 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

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

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1575 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

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

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4118 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

04119 {
04120    int val;
04121 
04122    p->ignoredtmf = 1;
04123 
04124    val = 0;
04125    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04126 
04127    if (!p->hardwaredtmf && p->dsp) {
04128       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
04129       ast_dsp_set_features(p->dsp, p->dsp_features);
04130    }
04131 }

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

Definition at line 10665 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, ast_frame::frametype, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, LOG_WARNING, dahdi_pvt::pri, ast_channel::priority, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by pri_dchannel().

10666 {
10667    struct ast_channel *chan = vchan;
10668    struct dahdi_pvt *pvt = chan->tech_pvt;
10669    struct ast_frame *f;
10670    char ex[80];
10671    /* Wait up to 30 seconds for an answer */
10672    int newms, ms = 30000;
10673    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10674    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10675    if (ast_call(chan, ex, 0)) {
10676       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10677       ast_hangup(chan);
10678       return NULL;
10679    }
10680    while ((newms = ast_waitfor(chan, ms)) > 0) {
10681       f = ast_read(chan);
10682       if (!f) {
10683          /* Got hangup */
10684          break;
10685       }
10686       if (f->frametype == AST_FRAME_CONTROL) {
10687          switch (f->subclass) {
10688          case AST_CONTROL_ANSWER:
10689             /* Launch the PBX */
10690             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10691             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10692             chan->priority = 1;
10693             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10694             ast_pbx_run(chan);
10695             /* It's already hungup, return immediately */
10696             return NULL;
10697          case AST_CONTROL_BUSY:
10698             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10699             break;
10700          case AST_CONTROL_CONGESTION:
10701             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10702             break;
10703          };
10704       }
10705       ast_frfree(f);
10706       ms = newms;
10707    }
10708    /* Hangup the channel since nothing happend */
10709    ast_hangup(chan);
10710    return NULL;
10711 }

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

Definition at line 8320 of file chan_dahdi.c.

References ast_calloc, ast_debug, ast_fdisset(), ast_free, AST_LAW, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, mwi_thread_data::buf, buf, calc_energy(), dahdi_pvt::channel, dahdi_pvt::cidspill, dahdi_destroy_channel_bynum(), dahdi_get_event(), dahdi_subchannel::dfd, errno, event2str(), handle_init_event(), has_voicemail(), iflist, iflock, last, mwi_thread_data::len, LOG_DEBUG, LOG_WARNING, dahdi_pvt::msgstate, mwi_send_thread(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, mwi_thread_data::pvt, dahdi_pvt::radio, dahdi_pvt::sig, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

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

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

Definition at line 4133 of file chan_dahdi.c.

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

Referenced by dahdi_bridge().

04134 {
04135    int val;
04136 
04137    if (p->channel == CHAN_PSEUDO)
04138       return;
04139 
04140    p->ignoredtmf = 0;
04141 
04142    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
04143    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
04144 
04145    if (!p->hardwaredtmf && p->dsp) {
04146       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
04147       ast_dsp_set_features(p->dsp, p->dsp_features);
04148    }
04149 }

static char* event2str ( int  event  )  [static]

Definition at line 1735 of file chan_dahdi.c.

References ARRAY_LEN, and buf.

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

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

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

Definition at line 2105 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

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

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

Definition at line 2071 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

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

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

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

13369 {
13370    struct dahdi_pvt *p = iflist;
13371    while (p) {
13372       if (p->channel == channel) {
13373          break;
13374       }
13375       p = p->next;
13376    }
13377    return p;
13378 }

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

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

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

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

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

Definition at line 4670 of file chan_dahdi.c.

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

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

04671 {
04672    const char *alarm_str = alarm2str(alms);
04673 
04674    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
04675    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
04676             "Alarm: %s\r\n"
04677             "Channel: %d\r\n",
04678             alarm_str, p->channel);
04679 }

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

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

12985 {
12986    int i, j;
12987    switch (cmd) {
12988    case CLI_INIT:
12989       e->command = "dahdi show cadences";
12990       e->usage = 
12991          "Usage: dahdi show cadences\n"
12992          "       Shows all cadences currently defined\n";
12993       return NULL;
12994    case CLI_GENERATE:
12995       return NULL;   
12996    }
12997    for (i = 0; i < num_cadence; i++) {
12998       char output[1024];
12999       char tmp[16], tmp2[64];
13000       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13001       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13002 
13003       for (j = 0; j < 16; j++) {
13004          if (cadences[i].ringcadence[j] == 0)
13005             break;
13006          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13007          if (cidrings[i] * 2 - 1 == j)
13008             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13009          else
13010             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13011          if (j != 0)
13012             strncat(output, ",", sizeof(output) - strlen(output) - 1);
13013          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13014       }
13015       ast_cli(a->fd,"%s\n",output);
13016    }
13017    return CLI_SUCCESS;
13018 }

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

Definition at line 8097 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_disable_ec(), dahdi_enable_ec(), dahdi_new(), dahdi_set_hook(), dahdi_subchannel::dfd, errno, EVENT_FLAG_SYSTEM, get_alarms(), handle_alarms(), dahdi_pvt::hanguponpolarityswitch, has_voicemail(), dahdi_pvt::immediate, dahdi_pvt::inalarm, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitor_neon, notify_message(), dahdi_pvt::polarity, POLARITY_REV, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::ringt_base, dahdi_pvt::sig, sig2str, SIG_BRI, SIG_BRI_PTMP, SIG_E911, SIG_EM, SIG_EM_E1, SIG_EMWINK, SIG_FEATB, SIG_FEATD, SIG_FEATDMF, SIG_FEATDMF_TA, SIG_FGC_CAMA, SIG_FGC_CAMAMF, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, ss_thread(), SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor(), and mwi_send_thread().

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

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

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

12197 {
12198    int span;
12199    int x;
12200    switch (cmd) {
12201    case CLI_INIT: 
12202       e->command = "pri debug span";
12203       e->usage = 
12204          "Usage: pri debug span <span>\n"
12205          "       Enables debugging on a given PRI span\n";
12206       return NULL;
12207    case CLI_GENERATE:   
12208       return complete_span_4(a->line, a->word, a->pos, a->n);
12209    }
12210    if (a->argc < 4) {
12211       return CLI_SHOWUSAGE;
12212    }
12213    span = atoi(a->argv[3]);
12214    if ((span < 1) || (span > NUM_SPANS)) {
12215       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
12216       return CLI_SUCCESS;
12217    }
12218    if (!pris[span-1].pri) {
12219       ast_cli(a->fd, "No PRI running on span %d\n", span);
12220       return CLI_SUCCESS;
12221    }
12222    for (x = 0; x < NUM_DCHANS; x++) {
12223       if (pris[span-1].dchans[x])
12224          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12225                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12226                                                PRI_DEBUG_Q921_STATE);
12227    }
12228    ast_cli(a->fd, "Enabled debugging on span %d\n", span);
12229    return CLI_SUCCESS;
12230 }

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

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

12235 {
12236    int span;
12237    int x;
12238    switch (cmd) {
12239    case CLI_INIT:
12240       e->command = "pri no debug span";
12241       e->usage = 
12242          "Usage: pri no debug span <span>\n"
12243          "       Disables debugging on a given PRI span\n";
12244       return NULL;
12245    case CLI_GENERATE:
12246       return complete_span_5(a->line, a->word, a->pos, a->n);
12247    }
12248    if (a->argc < 5)
12249       return CLI_SHOWUSAGE;
12250 
12251    span = atoi(a->argv[4]);
12252    if ((span < 1) || (span > NUM_SPANS)) {
12253       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12254       return CLI_SUCCESS;
12255    }
12256    if (!pris[span-1].pri) {
12257       ast_cli(a->fd, "No PRI running on span %d\n", span);
12258       return CLI_SUCCESS;
12259    }
12260    for (x = 0; x < NUM_DCHANS; x++) {
12261       if (pris[span-1].dchans[x])
12262          pri_set_debug(pris[span-1].dchans[x], 0);
12263    }
12264    ast_cli(a->fd, "Disabled debugging on span %d\n", span);
12265    return CLI_SUCCESS;
12266 }

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

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

12269 {
12270    int span;
12271    int x;
12272    switch (cmd) {
12273    case CLI_INIT:
12274       e->command = "pri intensive debug span";
12275       e->usage = 
12276          "Usage: pri intensive debug span <span>\n"
12277          "       Enables debugging down to the Q.921 level\n";
12278       return NULL;
12279    case CLI_GENERATE:
12280       return complete_span_5(a->line, a->word, a->pos, a->n);
12281    }
12282 
12283    if (a->argc < 5)
12284       return CLI_SHOWUSAGE;
12285    span = atoi(a->argv[4]);
12286    if ((span < 1) || (span > NUM_SPANS)) {
12287       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12288       return CLI_SUCCESS;
12289    }
12290    if (!pris[span-1].pri) {
12291       ast_cli(a->fd, "No PRI running on span %d\n", span);
12292       return CLI_SUCCESS;
12293    }
12294    for (x = 0; x < NUM_DCHANS; x++) {
12295       if (pris[span-1].dchans[x])
12296          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12297                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12298                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12299    }
12300    ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12301    return CLI_SUCCESS;
12302 }

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

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

12161 {
12162    int myfd;
12163    switch (cmd) {
12164    case CLI_INIT:
12165       e->command = "pri set debug file";
12166       e->usage = "Usage: pri set debug file [output-file]\n"
12167             "       Sends PRI debug output to the specified output file\n";
12168       return NULL;
12169    case CLI_GENERATE:
12170       return NULL;   
12171    }
12172    if (a->argc < 5)
12173       return CLI_SHOWUSAGE;
12174 
12175    if (ast_strlen_zero(a->argv[4]))
12176       return CLI_SHOWUSAGE;
12177 
12178    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12179    if (myfd < 0) {
12180       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12181       return CLI_SUCCESS;
12182    }
12183 
12184    ast_mutex_lock(&pridebugfdlock);
12185 
12186    if (pridebugfd >= 0)
12187       close(pridebugfd);
12188 
12189    pridebugfd = myfd;
12190    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12191    ast_mutex_unlock(&pridebugfdlock);
12192    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12193    return CLI_SUCCESS;
12194 }

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

Definition at line 12408 of file chan_dahdi.c.

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

12409 {
12410    int x;
12411    int span;
12412    int count=0;
12413    int debug=0;
12414 
12415    switch (cmd) {
12416    case CLI_INIT: 
12417       e->command = "pri show debug";
12418       e->usage = 
12419          "Usage: pri show debug\n"
12420          "  Show the debug state of pri spans\n";
12421       return NULL;
12422    case CLI_GENERATE:
12423       return NULL;   
12424    }
12425 
12426    for (span = 0; span < NUM_SPANS; span++) {
12427            if (pris[span].pri) {
12428          for (x = 0; x < NUM_DCHANS; x++) {
12429             debug = 0;
12430                if (pris[span].dchans[x]) {
12431                   debug = pri_get_debug(pris[span].dchans[x]);
12432                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" );
12433                count++;
12434             }
12435          }
12436       }
12437 
12438    }
12439    ast_mutex_lock(&pridebugfdlock);
12440    if (pridebugfd >= 0) 
12441       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12442    ast_mutex_unlock(&pridebugfdlock);
12443        
12444    if (!count) 
12445       ast_cli(a->fd, "No debug set or no PRI running\n");
12446    return CLI_SUCCESS;
12447 }

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

Definition at line 12358 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, status, ast_cli_entry::usage, and ast_cli_args::word.

12359 {
12360    int span;
12361    int x;
12362    char status[256];
12363    switch (cmd) {
12364    case CLI_INIT: 
12365       e->command = "pri show span";
12366       e->usage = 
12367          "Usage: pri show span <span>\n"
12368          "       Displays PRI Information on a given PRI span\n";
12369       return NULL;
12370    case CLI_GENERATE:
12371       return complete_span_4(a->line, a->word, a->pos, a->n);
12372    }
12373 
12374    if (a->argc < 4)
12375       return CLI_SHOWUSAGE;
12376    span = atoi(a->argv[3]);
12377    if ((span < 1) || (span > NUM_SPANS)) {
12378       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12379       return CLI_SUCCESS;
12380    }
12381    if (!pris[span-1].pri) {
12382       ast_cli(a->fd, "No PRI running on span %d\n", span);
12383       return CLI_SUCCESS;
12384    }
12385    for (x = 0; x < NUM_DCHANS; x++) {
12386       if (pris[span-1].dchannels[x]) {
12387 #ifdef PRI_DUMP_INFO_STR
12388          char *info_str = NULL;
12389 #endif
12390          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12391          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12392          ast_cli(a->fd, "Status: %s\n", status);
12393 #ifdef PRI_DUMP_INFO_STR
12394          info_str = pri_dump_info_str(pris[span-1].pri);
12395          if (info_str) {
12396             ast_cli(a->fd, "%s", info_str);
12397             ast_free(info_str);
12398          }
12399 #else
12400          pri_dump_info(pris[span-1].pri);
12401 #endif
12402          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12403       }
12404    }
12405    return CLI_SUCCESS;
12406 }

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

Definition at line 12325 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, status, and ast_cli_entry::usage.

12326 {
12327    int span;
12328    int x;
12329    char status[256];
12330 
12331    switch (cmd) {
12332    case CLI_INIT:
12333       e->command = "pri show spans";
12334       e->usage = 
12335          "Usage: pri show spans\n"
12336          "       Displays PRI Information\n";
12337       return NULL;
12338    case CLI_GENERATE:
12339       return NULL;   
12340    }
12341 
12342    if (a->argc != 3)
12343       return CLI_SHOWUSAGE;
12344 
12345    for (span = 0; span < NUM_SPANS; span++) {
12346       if (pris[span].pri) {
12347          for (x = 0; x < NUM_DCHANS; x++) {
12348             if (pris[span].dchannels[x]) {
12349                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12350                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12351             }
12352          }
12353       }
12354    }
12355    return CLI_SUCCESS;
12356 }

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

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

12140 {
12141    switch (cmd) {
12142    case CLI_INIT:
12143       e->command = "pri unset debug file";
12144       e->usage = "Usage: pri unset debug file\n"
12145             "       Stop sending debug output to the previously \n"
12146                  "       specified file\n";
12147       return NULL;
12148    case CLI_GENERATE:
12149       return NULL;   
12150    }
12151    /* Assume it is unset */
12152    ast_mutex_lock(&pridebugfdlock);
12153    close(pridebugfd);
12154    pridebugfd = -1;
12155    ast_cli(a->fd, "PRI debug output to file disabled\n");
12156    ast_mutex_unlock(&pridebugfdlock);
12157    return CLI_SUCCESS;
12158 }

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

Definition at line 12449 of file chan_dahdi.c.

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

12450 {
12451    switch (cmd) {
12452    case CLI_INIT:
12453       e->command = "pri show version";
12454       e->usage = 
12455          "Usage: pri show version\n"
12456          "Show libpri version information\n";
12457       return NULL;
12458    case CLI_GENERATE:
12459       return NULL;
12460    }
12461 
12462    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12463 
12464    return CLI_SUCCESS;
12465 }

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

Definition at line 13757 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, linksets, dahdi_pvt::locallyblocked, lock, master, NUM_SPANS, dahdi_ss7::numchans, dahdi_ss7::pvts, pvts, and ast_cli_entry::usage.

13758 {
13759    int linkset, cic;
13760    int blocked = -1, i;
13761    switch (cmd) {
13762    case CLI_INIT:
13763       e->command = "ss7 block cic";
13764       e->usage = 
13765          "Usage: ss7 block cic <linkset> <CIC>\n"
13766          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
13767       return NULL;
13768    case CLI_GENERATE:
13769       return NULL;
13770    }
13771    if (a->argc == 5)
13772       linkset = atoi(a->argv[3]);
13773    else
13774       return CLI_SHOWUSAGE;
13775 
13776    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13777       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13778       return CLI_SUCCESS;
13779    }
13780 
13781    if (!linksets[linkset-1].ss7) {
13782       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13783       return CLI_SUCCESS;
13784    }
13785 
13786    cic = atoi(a->argv[4]);
13787 
13788    if (cic < 1) {
13789       ast_cli(a->fd, "Invalid CIC specified!\n");
13790       return CLI_SUCCESS;
13791    }
13792 
13793    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13794       if (linksets[linkset-1].pvts[i]->cic == cic) {
13795          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13796          if (!blocked) {
13797             ast_mutex_lock(&linksets[linkset-1].lock);
13798             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13799             ast_mutex_unlock(&linksets[linkset-1].lock);
13800          }
13801       }
13802    }
13803 
13804    if (blocked < 0) {
13805       ast_cli(a->fd, "Invalid CIC specified!\n");
13806       return CLI_SUCCESS;
13807    }
13808 
13809    if (!blocked)
13810       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13811    else
13812       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13813 
13814    /* Break poll on the linkset so it sends our messages */
13815    pthread_kill(linksets[linkset-1].master, SIGURG);
13816 
13817    return CLI_SUCCESS;
13818 }

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

Definition at line 13820 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cic, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, linksets, lock, master, NUM_SPANS, dahdi_ss7::numchans, pvts, dahdi_ss7::pvts, and ast_cli_entry::usage.

13821 {
13822    int linkset;
13823    int i;
13824    switch (cmd) {
13825    case CLI_INIT:
13826       e->command = "ss7 block linkset";
13827       e->usage = 
13828          "Usage: ss7 block linkset <linkset number>\n"
13829          "       Sends a remote blocking request for all CICs on the given linkset\n";
13830       return NULL;
13831    case CLI_GENERATE:
13832       return NULL;
13833    }
13834    if (a->argc == 4)
13835       linkset = atoi(a->argv[3]);
13836    else
13837       return CLI_SHOWUSAGE;
13838 
13839    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13840       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13841       return CLI_SUCCESS;
13842    }
13843 
13844    if (!linksets[linkset-1].ss7) {
13845       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13846       return CLI_SUCCESS;
13847    }
13848 
13849    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13850       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13851       ast_mutex_lock(&linksets[linkset-1].lock);
13852       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13853       ast_mutex_unlock(&linksets[linkset-1].lock);
13854    }
13855 
13856    /* Break poll on the linkset so it sends our messages */
13857    pthread_kill(linksets[linkset-1].master, SIGURG);
13858 
13859    return CLI_SUCCESS;
13860 }

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

Definition at line 13726 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, ast_cli_args::fd, linksets, NUM_SPANS, and ast_cli_entry::usage.

13727 {
13728    int span;
13729    switch (cmd) {
13730    case CLI_INIT:
13731       e->command = "ss7 debug linkset";
13732       e->usage = 
13733          "Usage: ss7 debug linkset <linkset>\n"
13734          "       Enables debugging on a given SS7 linkset\n";
13735       return NULL;
13736    case CLI_GENERATE:
13737       return NULL;
13738    }
13739    if (a->argc < 4)
13740       return CLI_SHOWUSAGE;
13741    span = atoi(a->argv[3]);
13742    if ((span < 1) || (span > NUM_SPANS)) {
13743       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13744       return CLI_SUCCESS;
13745    }
13746    if (!linksets[span-1].ss7) {
13747       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13748       return CLI_SUCCESS;
13749    }
13750    if (linksets[span-1].ss7)
13751       ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13752 
13753    ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13754    return CLI_SUCCESS;
13755 }

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

Definition at line 13695 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, ast_cli_args::fd, linksets, NUM_SPANS, and ast_cli_entry::usage.

13696 {
13697    int span;
13698    switch (cmd) {
13699    case CLI_INIT:
13700       e->command = "ss7 no debug linkset";
13701       e->usage = 
13702          "Usage: ss7 no debug linkset <span>\n"
13703          "       Disables debugging on a given SS7 linkset\n";
13704       return NULL;
13705    case CLI_GENERATE:
13706       return NULL;
13707    }
13708    if (a->argc < 5)
13709       return CLI_SHOWUSAGE;
13710    span = atoi(a->argv[4]);
13711    if ((span < 1) || (span > NUM_SPANS)) {
13712       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[4], 1, NUM_SPANS);
13713       return CLI_SUCCESS;
13714    }
13715    if (!linksets[span-1].ss7) {
13716       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13717       return CLI_SUCCESS;
13718    }
13719    if (linksets[span-1].ss7)
13720       ss7_set_debug(linksets[span-1].ss7, 0);
13721 
13722    ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
13723    return CLI_SUCCESS;
13724 }

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

Definition at line 13962 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, ast_cli_args::fd, dahdi_ss7::LINKSET_STATE_UP, linksets, NUM_SPANS, dahdi_ss7::ss7, dahdi_ss7::state, and ast_cli_entry::usage.

13963 {
13964    int linkset;
13965    struct dahdi_ss7 *ss7;
13966    switch (cmd) {
13967    case CLI_INIT:
13968       e->command = "ss7 show linkset";
13969       e->usage = 
13970          "Usage: ss7 show linkset <span>\n"
13971          "       Shows the status of an SS7 linkset.\n";
13972       return NULL;
13973    case CLI_GENERATE:
13974       return NULL;
13975    }
13976 
13977    if (a->argc < 4)
13978       return CLI_SHOWUSAGE;
13979    linkset = atoi(a->argv[3]);
13980    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13981       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13982       return CLI_SUCCESS;
13983    }
13984    if (!linksets[linkset-1].ss7) {
13985       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13986       return CLI_SUCCESS;
13987    }
13988    if (linksets[linkset-1].ss7)
13989       ss7 = &linksets[linkset-1];
13990 
13991    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
13992 
13993    return CLI_SUCCESS;
13994 }

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

Definition at line 13862 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, linksets, dahdi_pvt::locallyblocked, lock, master, NUM_SPANS, dahdi_ss7::numchans, dahdi_ss7::pvts, pvts, and ast_cli_entry::usage.

13863 {
13864    int linkset, cic;
13865    int i, blocked = -1;
13866    switch (cmd) {
13867    case CLI_INIT:
13868       e->command = "ss7 unblock cic";
13869       e->usage = 
13870          "Usage: ss7 unblock cic <linkset> <CIC>\n"
13871          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
13872       return NULL;
13873    case CLI_GENERATE:
13874       return NULL;
13875    }
13876 
13877    if (a->argc == 5)
13878       linkset = atoi(a->argv[3]);
13879    else
13880       return CLI_SHOWUSAGE;
13881 
13882    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13883       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13884       return CLI_SUCCESS;
13885    }
13886 
13887    if (!linksets[linkset-1].ss7) {
13888       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13889       return CLI_SUCCESS;
13890    }
13891 
13892    cic = atoi(a->argv[4]);
13893 
13894    if (cic < 1) {
13895       ast_cli(a->fd, "Invalid CIC specified!\n");
13896       return CLI_SUCCESS;
13897    }
13898 
13899    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13900       if (linksets[linkset-1].pvts[i]->cic == cic) {
13901          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13902          if (blocked) {
13903             ast_mutex_lock(&linksets[linkset-1].lock);
13904             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13905             ast_mutex_unlock(&linksets[linkset-1].lock);
13906          }
13907       }
13908    }
13909 
13910    if (blocked > 0)
13911       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13912 
13913    /* Break poll on the linkset so it sends our messages */
13914    pthread_kill(linksets[linkset-1].master, SIGURG);
13915 
13916    return CLI_SUCCESS;
13917 }

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

Definition at line 13919 of file chan_dahdi.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dahdi_pvt::cic, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, linksets, lock, master, NUM_SPANS, dahdi_ss7::numchans, pvts, dahdi_ss7::pvts, and ast_cli_entry::usage.

13920 {
13921    int linkset;
13922    int i;
13923    switch (cmd) {
13924    case CLI_INIT:
13925       e->command = "ss7 unblock linkset";
13926       e->usage = 
13927          "Usage: ss7 unblock linkset <linkset number>\n"
13928          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
13929       return NULL;
13930    case CLI_GENERATE:
13931       return NULL;
13932    }
13933 
13934    if (a->argc == 4)
13935       linkset = atoi(a->argv[3]);
13936    else
13937       return CLI_SHOWUSAGE;
13938 
13939    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13940       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13941       return CLI_SUCCESS;
13942    }
13943 
13944    if (!linksets[linkset-1].ss7) {
13945       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13946       return CLI_SUCCESS;
13947    }
13948 
13949    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13950       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13951       ast_mutex_lock(&linksets[linkset-1].lock);
13952       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13953       ast_mutex_unlock(&linksets[linkset-1].lock);
13954    }
13955 
13956    /* Break poll on the linkset so it sends our messages */
13957    pthread_kill(linksets[linkset-1].master, SIGURG);
13958 
13959    return CLI_SUCCESS;
13960 }

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

Definition at line 13996 of file chan_dahdi.c.

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

13997 {
13998    switch (cmd) {
13999    case CLI_INIT:
14000       e->command = "ss7 show version";
14001       e->usage = 
14002          "Usage: ss7 show version\n"
14003          "  Show the libss7 version\n";
14004       return NULL;
14005    case CLI_GENERATE:
14006       return NULL;
14007    }
14008 
14009    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
14010 
14011    return CLI_SUCCESS;
14012 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 2345 of file chan_dahdi.c.

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

Referenced by dahdi_handle_event(), do_monitor(), handle_init_event(), and mwi_send_thread().

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

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

Definition at line 1860 of file chan_dahdi.c.

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

Referenced by conf_del().

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

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

Definition at line 1890 of file chan_dahdi.c.

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

Referenced by update_conf().

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

static int linkset_addsigchan ( int  sigchan  )  [static]

Definition at line 13574 of file chan_dahdi.c.

References ast_log(), dahdi_close_ss7_fd(), errno, LINKSTATE_DOWN, LINKSTATE_INALARM, LOG_ERROR, NUM_SPANS, and ss7_resolve_linkset().

Referenced by process_dahdi().

13575 {
13576    struct dahdi_ss7 *link;
13577    int res;
13578    int curfd;
13579    struct dahdi_params p;
13580    struct dahdi_bufferinfo bi;
13581    struct dahdi_spaninfo si;
13582 
13583 
13584    link = ss7_resolve_linkset(cur_linkset);
13585    if (!link) {
13586       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
13587       return -1;
13588    }
13589 
13590    if (cur_ss7type < 0) {
13591       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13592       return -1;
13593    }
13594 
13595    if (!link->ss7)
13596       link->ss7 = ss7_new(cur_ss7type);
13597 
13598    if (!link->ss7) {
13599       ast_log(LOG_ERROR, "Can't create new SS7!\n");
13600       return -1;
13601    }
13602 
13603    link->type = cur_ss7type;
13604 
13605    if (cur_pointcode < 0) {
13606       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13607       return -1;
13608    } else
13609       ss7_set_pc(link->ss7, cur_pointcode);
13610 
13611    if (sigchan < 0) {
13612       ast_log(LOG_ERROR, "Invalid sigchan!\n");
13613       return -1;
13614    } else {
13615       if (link->numsigchans >= NUM_DCHANS) {
13616          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13617          return -1;
13618       }
13619       curfd = link->numsigchans;
13620 
13621       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13622       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13623          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13624          return -1;
13625       }
13626       memset(&p, 0, sizeof(p));
13627       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13628       if (res) {
13629          dahdi_close_ss7_fd(link, curfd);
13630          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13631          return -1;
13632       }
13633       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13634          dahdi_close_ss7_fd(link, curfd);
13635          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13636          return -1;
13637       }
13638 
13639       memset(&bi, 0, sizeof(bi));
13640       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13641       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13642       bi.numbufs = 32;
13643       bi.bufsize = 512;
13644 
13645       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13646          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13647          dahdi_close_ss7_fd(link, curfd);
13648          return -1;
13649       }
13650 
13651       if (p.sigtype == DAHDI_SIG_MTP2)
13652          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13653       else
13654          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13655 
13656       link->numsigchans++;
13657 
13658       memset(&si, 0, sizeof(si));
13659       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13660       if (res) {
13661          dahdi_close_ss7_fd(link, curfd);
13662          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13663       }
13664 
13665       if (!si.alarms) {
13666          link->linkstate[curfd] = LINKSTATE_DOWN;
13667          ss7_link_noalarm(link->ss7, link->fds[curfd]);
13668       } else {
13669          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13670          ss7_link_alarm(link->ss7, link->fds[curfd]);
13671       }
13672    }
13673 
13674    if (cur_adjpointcode < 0) {
13675       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13676       return -1;
13677    } else {
13678       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13679    }
13680 
13681    if (cur_defaultdpc < 0) {
13682       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13683       return -1;
13684    }
13685 
13686    if (cur_networkindicator < 0) {
13687       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13688       return -1;
13689    } else
13690       ss7_set_network_ind(link->ss7, cur_networkindicator);
13691 
13692    return 0;
13693 }

static int load_module ( void   )  [static]

Definition at line 15314 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_pri_error(), dahdi_pri_message(), dahdi_send_keypad_facility_exec(), dahdi_ss7_error(), dahdi_ss7_message(), inuse, linksets, lock, LOG_ERROR, dahdi_ss7::master, dahdi_pri::master, name, NUM_SPANS, dahdi_pri::offset, pris, and setup_dahdi().

15315 {
15316    int res;
15317 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15318    int y, i;
15319 #endif
15320 
15321 #ifdef HAVE_PRI
15322    memset(pris, 0, sizeof(pris));
15323    for (y = 0; y < NUM_SPANS; y++) {
15324       ast_mutex_init(&pris[y].lock);
15325       pris[y].offset = -1;
15326       pris[y].master = AST_PTHREADT_NULL;
15327       for (i = 0; i < NUM_DCHANS; i++)
15328          pris[y].fds[i] = -1;
15329    }
15330    pri_set_error(dahdi_pri_error);
15331    pri_set_message(dahdi_pri_message);
15332    ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15333          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15334 #endif
15335 #ifdef HAVE_SS7
15336    memset(linksets, 0, sizeof(linksets));
15337    for (y = 0; y < NUM_SPANS; y++) {
15338       ast_mutex_init(&linksets[y].lock);
15339       linksets[y].master = AST_PTHREADT_NULL;
15340       for (i = 0; i < NUM_DCHANS; i++)
15341          linksets[y].fds[i] = -1;
15342    }
15343    ss7_set_error(dahdi_ss7_error);
15344    ss7_set_message(dahdi_ss7_message);
15345 #endif /* HAVE_SS7 */
15346    res = setup_dahdi(0);
15347    /* Make sure we can register our DAHDI channel type */
15348    if (res)
15349       return AST_MODULE_LOAD_DECLINE;
15350    if (ast_channel_register(&dahdi_tech)) {
15351       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15352       __unload_module();
15353       return AST_MODULE_LOAD_FAILURE;
15354    }
15355 #ifdef HAVE_PRI
15356    ast_string_field_init(&inuse, 16);
15357    ast_string_field_set(&inuse, name, "GR-303InUse");
15358    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15359 #endif   
15360 #ifdef HAVE_SS7
15361    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15362 #endif
15363 
15364    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15365    
15366    memset(round_robin, 0, sizeof(round_robin));
15367    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15368    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15369    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15370    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15371    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15372    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15373    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15374 
15375    ast_cond_init(&mwi_thread_complete, NULL);
15376    ast_cond_init(&ss_thread_complete, NULL);
15377 
15378    return res;
15379 }

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

Definition at line 8718 of file chan_dahdi.c.

References dahdi_pvt::accountcode, dahdi_pvt::adsi, dahdi_pvt::amaflags, dahdi_pvt::answeronpolarityswitch, ast_calloc, ast_copy_string(), ast_dsp_set_digitmode(), 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_event_subscribe(), ast_log(), ast_mutex_init(), ast_smdi_interface_find(), ast_strdupa, ast_strlen_zero(), ast_variable_new(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_pvt::call, dahdi_ss7::called_nai, dahdi_pvt::callgroup, dahdi_ss7::calling_nai, dahdi_pvt::callprogress, dahdi_pvt::callreturn, dahdi_pvt::callwaiting, dahdi_pvt::callwaitingcallerid, dahdi_pvt::cancallforward, dahdi_pvt::canpark, dahdi_chan_conf::chan, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::cic, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_rxgain, CID_SIG_SMDI, dahdi_pvt::cid_signalling, dahdi_pvt::cid_start, dahdi_pvt::cid_ton, dahdi_pvt::confno, context, dahdi_pvt::context, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_open(), dahdi_set_hook(), dahdi_pvt::dahditrcallerid, dahdi_pvt::defcontext, dahdi_pvt::destroy, destroy_dahdi_pvt(), dahdi_subchannel::dfd, dahdi_pri::dialplan, dialplan2str(), dahdi_pvt::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::firstradio, free, get_alarms(), dahdi_pvt::group, handle_alarms(), dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::head, dahdi_pvt::hidecallerid, dahdi_pri::idledial, dahdi_pri::idleext, iflist, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pri::inbanddisconnect, dahdi_pvt::inservice, dahdi_pri::internationalprefix, dahdi_ss7::internationalprefix, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, dahdi_pvt::law, dahdi_pri::localdialplan, dahdi_pvt::locallyblocked, dahdi_pri::localprefix, dahdi_pvt::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, mailbox, dahdi_pvt::mailbox, MAX_CHANNELS, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::msgstate, mwi_event_cb(), dahdi_pvt::mwi_event_sub, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_pri::nationalprefix, dahdi_ss7::nationalprefix, dahdi_pvt::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_DCHANS, NUM_SPANS, dahdi_pri::numchans, dahdi_ss7::numchans, dahdi_pvt::onhooktime, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::parkinglot, dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_chan_conf::pri, pri_is_up(), pri_resolve_span(), dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::prilogicalspan, dahdi_pvt::prioffset, pris, dahdi_pri::privateprefix, dahdi_pvt::propconfno, dahdi_pvt::pulse, dahdi_pri::pvts, dahdi_ss7::pvts, dahdi_pvt::radio, distRingData::range, dahdi_pvt::remotelyblocked, dahdi_pri::resetinterval, dahdi_pvt::restrictcid, dahdi_distRings::ringnum, dahdi_pvt::ringt_base, dahdi_pvt::rxgain, dahdi_pvt::sendcalleridafter, set_actual_gain(), dahdi_pri::sig, 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_FXSKS, SIG_FXSLS, SIG_GR303FXOKS, SIG_GR303FXSKS, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, SIG_SS7, sigtype_to_signalling(), dahdi_pvt::smdi_iface, dahdi_chan_conf::smdi_port, dahdi_pvt::span, dahdi_chan_conf::ss7, dahdi_pvt::ss7, dahdi_ss7::ss7, ss7_resolve_linkset(), dahdi_pvt::ss7call, dahdi_pvt::stripmsd, strsep(), SUB_REAL, dahdi_pvt::subs, dahdi_ss7::subscriberprefix, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_pri::unknownprefix, dahdi_ss7::unknownprefix, update_conf(), dahdi_pvt::use_callerid, dahdi_pvt::use_callingpres, dahdi_pvt::use_smdi, dahdi_pvt::usedistinctiveringdetection, ast_variable::value, and dahdi_pvt::vars.

Referenced by build_channels(), and process_dahdi().

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

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

Definition at line 294 of file chan_dahdi.c.

Referenced by mkintf().

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

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

Definition at line 7924 of file chan_dahdi.c.

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

Referenced by do_monitor().

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

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

Definition at line 7781 of file chan_dahdi.c.

References ast_free, 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_get(), callerid_new(), chan, dahdi_pvt::channel, CID_MSGWAITING, CID_NOMSGWAITING, dahdi_pvt::cid_signalling, dahdi_get_event(), dahdi_new(), dahdi_subchannel::dfd, errno, event2str(), EVENT_FLAG_SYSTEM, callerid_state::flags, get_alarms(), handle_alarms(), dahdi_pvt::inalarm, mwi_thread_data::len, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, manager_event, dahdi_pvt::mwimonitoractive, name, notify_message(), mwi_thread_data::pvt, quit, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::ringt_base, ss_thread(), SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

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

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

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

05974 {
05975    int sent=0;
05976    int size;
05977    int res;
05978    int fd;
05979    fd = p->subs[idx].dfd;
05980    while (len) {
05981       size = len;
05982       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
05983          size = (linear ? READ_SIZE * 2 : READ_SIZE);
05984       res = write(fd, buf, size);
05985       if (res != size) {
05986          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
05987          return sent;
05988       }
05989       len -= size;
05990       buf += size;
05991    }
05992    return sent;
05993 }

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

Definition at line 6494 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

06495 {
06496    char c;
06497 
06498    *str = 0; /* start with empty output buffer */
06499    for (;;)
06500    {
06501       /* Wait for the first digit (up to specified ms). */
06502       c = ast_waitfordigit(chan, ms);
06503       /* if timeout, hangup or error, return as such */
06504       if (c < 1)
06505          return c;
06506       *str++ = c;
06507       *str = 0;
06508       if (strchr(term, c))
06509          return 1;
06510    }
06511 }

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

Send MWI state change.

  • mailbox_full This is the mailbox associated with the FXO line that the MWI state has changed on.
  • thereornot This argument should simply be set to 1 or 0, to indicate whether there are messages waiting or not.
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 2284 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(), mwi_thread(), and ss_thread().

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

static unsigned int parse_pointcode ( const char *  pcstring  )  [static]

Definition at line 8685 of file chan_dahdi.c.

Referenced by process_dahdi().

08686 {
08687    unsigned int code1, code2, code3;
08688    int numvals;
08689 
08690    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08691    if (numvals == 1)
08692       return code1;
08693    if (numvals == 3)
08694       return (code1 << 16) | (code2 << 8) | code3;
08695 
08696    return 0;
08697 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

Definition at line 3340 of file chan_dahdi.c.

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

Referenced by pri_find_principle().

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

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

Definition at line 3310 of file chan_dahdi.c.

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

Referenced by dahdi_request(), pri_dchannel(), and pri_fixup_principle().

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

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

Definition at line 10794 of file chan_dahdi.c.

References dahdi_pvt::call, 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().

10795 {
10796    do {
10797       pri->resetpos++;
10798    } while ((pri->resetpos < pri->numchans) &&
10799        (!pri->pvts[pri->resetpos] ||
10800         pri->pvts[pri->resetpos]->call ||
10801         pri->pvts[pri->resetpos]->resetting));
10802    if (pri->resetpos < pri->numchans) {
10803       /* Mark the channel as resetting and restart it */
10804       pri->pvts[pri->resetpos]->resetting = 1;
10805       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10806    } else {
10807       pri->resetting = 0;
10808       time(&pri->lastreset);
10809    }
10810    return 0;
10811 }

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

Definition at line 8670 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08671 {
08672    if (pris[span].mastertrunkgroup) {
08673       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);
08674       return -1;
08675    }
08676    pris[span].mastertrunkgroup = trunkgroup;
08677    pris[span].prilogicalspan = logicalspan;
08678    return 0;
08679 }

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

Definition at line 8607 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08608 {
08609    struct dahdi_spaninfo si;
08610    struct dahdi_params p;
08611    int fd;
08612    int span;
08613    int ospan=0;
08614    int x,y;
08615    for (x = 0; x < NUM_SPANS; x++) {
08616       if (pris[x].trunkgroup == trunkgroup) {
08617          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08618          return -1;
08619       }
08620    }
08621    for (y = 0; y < NUM_DCHANS; y++) {
08622       if (!channels[y]) 
08623          break;
08624       memset(&si, 0, sizeof(si));
08625       memset(&p, 0, sizeof(p));
08626       fd = open("/dev/dahdi/channel", O_RDWR);
08627       if (fd < 0) {
08628          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08629          return -1;
08630       }
08631       x = channels[y];
08632       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08633          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08634          close(fd);
08635          return -1;
08636       }
08637       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08638          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08639          return -1;
08640       }
08641       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08642          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08643          close(fd);
08644          return -1;
08645       }
08646       span = p.spanno - 1;
08647       if (pris[span].trunkgroup) {
08648          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08649          close(fd);
08650          return -1;
08651       }
08652       if (pris[span].pvts[0]) {
08653          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08654          close(fd);
08655          return -1;
08656       }
08657       if (!y) {
08658          pris[span].trunkgroup = trunkgroup;
08659          pris[span].offset = channels[y] - p.chanpos;
08660          ospan = span;
08661       }
08662       pris[ospan].dchannels[y] = channels[y];
08663       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08664       pris[span].span = span + 1;
08665       close(fd);
08666    }
08667    return 0;   
08668 }

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

Definition at line 10888 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_channel::_state, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, apply_plan_to_number(), ast_canmatch_extension(), AST_CAUSE_USER_BUSY, AST_CONTROL_BUSY, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_UNHOLD, ast_copy_string(), ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FORMAT_ULAW, AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_hangup(), ast_log(), ast_matchmore_extension(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_pthread_create_background, ast_pthread_create_detached, ast_shrink_phone_number(), AST_SOFTHANGUP_DEV, AST_STATE_BUSY, AST_STATE_RESERVED, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvsub(), ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::callingpres, dahdi_pvt::channel, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::confirmanswer, dahdi_pvt::context, dahdi_enable_ec(), dahdi_hangup(), dahdi_new(), DAHDI_OVERLAPDIAL_INCOMING, dahdi_queue_frame(), dahdi_request(), dahdi_setlaw(), DCHAN_NOTINALARM, DCHAN_UP, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, dahdi_pri::debug, dahdi_subchannel::dfd, dahdi_pvt::dialdest, dahdi_pvt::dialing, dahdi_pvt::dnid, do_idle_thread(), dahdi_pvt::dop, dahdi_pvt::dsp, dahdi_pvt::dsp_features, DSP_PROGRESS_RINGING, errno, event2str(), EVENT_FLAG_SYSTEM, dahdi_pvt::exten, dahdi_pri::fds, ast_channel::hangupcause, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::inservice, inuse, dahdi_pvt::isidlecall, dahdi_pvt::lastcid_name, dahdi_pvt::lastcid_num, dahdi_pri::lastreset, dahdi_pvt::lock, dahdi_pri::lock, LOG_NOTICE, LOG_WARNING, dahdi_pvt::logicalspan, manager_event, dahdi_pri::minidle, dahdi_pri::minunused, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needringing, dahdi_pri::numchans, dahdi_pri::overlapdial, dahdi_pvt::owner, pbx_builtin_setvar_helper(), dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), PRI_CHANNEL, pri_check_restart(), pri_find_crv(), pri_find_dchan(), pri_find_empty_chan(), pri_find_principle(), pri_fixup_principle(), pri_hangup_all(), pri_is_up(), pri_order(), PRI_SPAN, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pri::pvts, dahdi_pvt::rdnis, dahdi_pvt::realcall, redirectingreason2str(), dahdi_pri::resetinterval, dahdi_pri::resetpos, dahdi_pvt::resetting, dahdi_pri::resetting, dahdi_pvt::rxgain, S_OR, set_actual_gain(), dahdi_pvt::setup_ack, dahdi_pvt::sig, dahdi_pri::sig, SIG_BRI_PTMP, SIG_FXSKS, dahdi_pri::span, ss_thread(), SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pri::switchtype, dahdi_pri::trunkgroup, dahdi_pvt::txgain, and dahdi_pvt::use_callerid.

Referenced by start_pri().

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

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

Definition at line 10541 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

10542 {
10543    struct dahdi_pvt *p;
10544    p = pri->crvs;
10545    while (p) {
10546       if (p->channel == crv)
10547          return p;
10548       p = p->next;
10549    }
10550    return NULL;
10551 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 3352 of file chan_dahdi.c.

References ast_log(), DCHAN_AVAILABLE, dahdi_pri::dchanavail, dahdi_pri::dchannels, dahdi_pri::dchans, LOG_NOTICE, LOG_WARNING, NUM_DCHANS, and dahdi_pri::pri.

Referenced by pri_dchannel().

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

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

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

09441 {
09442    int x;
09443    if (backwards)
09444       x = pri->numchans;
09445    else
09446       x = 0;
09447    for (;;) {
09448       if (backwards && (x < 0))
09449          break;
09450       if (!backwards && (x >= pri->numchans))
09451          break;
09452       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09453          ast_debug(1, "Found empty available channel %d/%d\n", 
09454             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09455          return x;
09456       }
09457       if (backwards)
09458          x--;
09459       else
09460          x++;
09461    }
09462    return -1;
09463 }

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

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

Referenced by pri_dchannel().

10555 {
10556    int x;
10557    int span = PRI_SPAN(channel);
10558    int spanfd;
10559    struct dahdi_params param;
10560    int principle = -1;
10561    int explicit = PRI_EXPLICIT(channel);
10562    channel = PRI_CHANNEL(channel);
10563 
10564    if (!explicit) {
10565       spanfd = pri_active_dchan_fd(pri);
10566       memset(&param, 0, sizeof(param));
10567       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10568          return -1;
10569       span = pris[param.spanno - 1].prilogicalspan;
10570    }
10571 
10572    for (x = 0; x < pri->numchans; x++) {
10573       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10574          principle = x;
10575          break;
10576       }
10577    }
10578    
10579    return principle;
10580 }

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

Definition at line 10582 of file chan_dahdi.c.

References ast_channel_set_fd(), ast_debug, ast_log(), ast_string_field_build, ast_verb, dahdi_pvt::bearer, dahdi_pvt::call, dahdi_pvt::channel, dahdi_pri::crvs, dahdi_close_sub(), LOG_WARNING, dahdi_pvt::logicalspan, name, dahdi_pvt::next, dahdi_pri::numchans, dahdi_pvt::owner, pri_assign_bearer(), dahdi_pvt::prioffset, dahdi_pri::pvts, SUB_REAL, dahdi_pri::trunkgroup, and wakeup_sub().

Referenced by pri_dchannel().

10583 {
10584    int x;
10585    struct dahdi_pvt *crv;
10586    if (!c) {
10587       if (principle < 0)
10588          return -1;
10589       return principle;
10590    }
10591    if ((principle > -1) && 
10592       (principle < pri->numchans) && 
10593       (pri->pvts[principle]) && 
10594       (pri->pvts[principle]->call == c))
10595       return principle;
10596    /* First, check for other bearers */
10597    for (x = 0; x < pri->numchans; x++) {
10598       if (!pri->pvts[x])
10599          continue;
10600       if (pri->pvts[x]->call == c) {
10601          /* Found our call */
10602          if (principle != x) {
10603             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10604 
10605             ast_verb(3, "Moving call from channel %d to channel %d\n",
10606                 old->channel, new->channel);
10607             if (new->owner) {
10608                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10609                   old->channel, new->channel, new->channel);
10610                return -1;
10611             }
10612             /* Fix it all up now */
10613             new->owner = old->owner;
10614             old->owner = NULL;
10615             if (new->owner) {
10616                ast_string_field_build(new->owner, name, 
10617                             "DAHDI/%d:%d-%d", pri->trunkgroup,
10618                             new->channel, 1);
10619                new->owner->tech_pvt = new;
10620                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10621                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10622                old->subs[SUB_REAL].owner = NULL;
10623             } else
10624                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);
10625             new->call = old->call;
10626             old->call = NULL;
10627 
10628             /* Copy any DSP that may be present */
10629             new->dsp = old->dsp;
10630             new->dsp_features = old->dsp_features;
10631             old->dsp = NULL;
10632             old->dsp_features = 0;
10633          }
10634          return principle;
10635       }
10636    }
10637    /* Now check for a CRV with no bearer */
10638    crv = pri->crvs;
10639    while (crv) {
10640       if (crv->call == c) {
10641          /* This is our match...  Perform some basic checks */
10642          if (crv->bearer)
10643             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10644          else if (pri->pvts[principle]->owner) 
10645             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10646          else {
10647             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
10648                wakeup the potential sleeper */
10649             dahdi_close_sub(crv, SUB_REAL);
10650             pri->pvts[principle]->call = crv->call;
10651             pri_assign_bearer(crv, pri, pri->pvts[principle]);
10652             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10653                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10654                pri->trunkgroup, crv->channel);
10655             wakeup_sub(crv, SUB_REAL, pri);
10656          }
10657          return principle;
10658       }
10659       crv = crv->next;
10660    }
10661    ast_log(LOG_WARNING, "Call specified, but not found?\n");
10662    return -1;
10663 }

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

Definition at line 1227 of file chan_dahdi.c.

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

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

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

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

Definition at line 10813 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

10814 {
10815    int x;
10816    int redo;
10817    ast_mutex_unlock(&pri->lock);
10818    ast_mutex_lock(&p->lock);
10819    do {
10820       redo = 0;
10821       for (x = 0; x < 3; x++) {
10822          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10823             redo++;
10824             DEADLOCK_AVOIDANCE(&p->lock);
10825          }
10826          if (p->subs[x].owner) {
10827             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10828             ast_channel_unlock(p->subs[x].owner);
10829          }
10830       }
10831    } while (redo);
10832    ast_mutex_unlock(&p->lock);
10833    ast_mutex_lock(&pri->lock);
10834    return 0;
10835 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3300 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.

Referenced by mkintf(), and pri_dchannel().

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

static char* pri_order ( int  level  )  [static]

Definition at line 3323 of file chan_dahdi.c.

Referenced by handle_pri_show_span(), and pri_dchannel().

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

static void pri_rel ( struct dahdi_pri pri  )  [inline, static]
static int pri_resolve_span ( int *  span,
int  channel,
int  offset,
struct dahdi_spaninfo *  si 
) [static]

Definition at line 8561 of file chan_dahdi.c.

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

Referenced by mkintf().

08562 {
08563    int x;
08564    int trunkgroup;
08565    /* Get appropriate trunk group if there is one */
08566    trunkgroup = pris[*span].mastertrunkgroup;
08567    if (trunkgroup) {
08568       /* Select a specific trunk group */
08569       for (x = 0; x < NUM_SPANS; x++) {
08570          if (pris[x].trunkgroup == trunkgroup) {
08571             *span = x;
08572             return 0;
08573          }
08574       }
08575       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08576       *span = -1;
08577    } else {
08578       if (pris[*span].trunkgroup) {
08579          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08580          *span = -1;
08581       } else if (pris[*span].mastertrunkgroup) {
08582          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08583          *span = -1;
08584       } else {
08585          if (si->totalchans == 31) {
08586             /* E1 */
08587             pris[*span].dchannels[0] = 16 + offset;
08588          } else if (si->totalchans == 24) {
08589             /* T1 or J1 */
08590             pris[*span].dchannels[0] = 24 + offset;
08591          } else if (si->totalchans == 3) {
08592             /* BRI */
08593             pris[*span].dchannels[0] = 3 + offset;
08594          } else {
08595             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);
08596             *span = -1;
08597             return 0;
08598          }
08599          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08600          pris[*span].offset = offset;
08601          pris[*span].span = *span + 1;
08602       }
08603    }
08604    return 0;
08605 }

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

Definition at line 14267 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_strlen_zero(), ast_true(), ast_variable_new(), ast_verb, dahdi_pvt::buf_no, dahdi_pvt::buf_policy, build_channels(), dahdi_pvt::busy_quietlength, dahdi_pvt::busy_tonelength, dahdi_pvt::busycount, dahdi_pvt::busydetect, dahdi_ss7::called_nai, dahdi_pvt::callgroup, dahdi_ss7::calling_nai, 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, CHAN_PSEUDO, 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_chan_conf_default(), 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, errno, dahdi_pri::facilityenable, dahdi_ss7::flags, 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_ss7::internationalprefix, dahdi_pri::internationalprefix, dahdi_chan_conf::is_sig_auto, dahdi_pvt::language, ast_variable::lineno, linkset_addsigchan(), LINKSET_FLAG_EXPLICITACM, dahdi_pri::localdialplan, dahdi_pri::localprefix, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, MAX_CHANLIST_LEN, dahdi_pri::minidle, dahdi_pri::minunused, mkintf(), dahdi_pvt::mohinterpret, dahdi_pvt::mohsuggest, dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitor_neon, dahdi_pvt::mwimonitor_rpas, ast_variable::name, dahdi_ss7::nationalprefix, dahdi_pri::nationalprefix, ast_variable::next, dahdi_pri::nodetype, dahdi_pri::nsf, NUM_CADENCE_MAX, NUM_SPANS, dahdi_pvt::outsigmod, dahdi_pri::overlapdial, dahdi_pvt::parkinglot, parse_pointcode(), dahdi_pvt::pickupgroup, dahdi_pvt::polarityonanswerdelay, dahdi_chan_conf::pri, dahdi_pvt::priexclusive, dahdi_pvt::priindication_oob, dahdi_pri::privateprefix, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, 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_chan_conf::smdi_port, dahdi_chan_conf::ss7, SS7_NAI_DYNAMIC, ss7_resolve_linkset(), strcasestr(), dahdi_pvt::stripmsd, strsep(), dahdi_ss7::subscriberprefix, dahdi_pri::switchtype, dahdi_pvt::threewaycalling, timer, dahdi_chan_conf::timing, dahdi_pvt::tonezone, dahdi_pvt::transfer, dahdi_pvt::transfertobusy, dahdi_pvt::txgain, dahdi_ss7::unknownprefix, 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().

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

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

Definition at line 14211 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, LOG_WARNING, name, dahdi_pvt::params, and parse().

Referenced by process_dahdi().

14212 {
14213    char *parse = ast_strdupa(data);
14214    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14215    unsigned int param_count;
14216    unsigned int x;
14217 
14218    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14219       return;
14220 
14221    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14222 
14223    /* first parameter is tap length, process it here */
14224 
14225    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14226    
14227    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14228       confp->chan.echocancel.head.tap_length = x;
14229    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14230       confp->chan.echocancel.head.tap_length = 128;
14231 
14232    /* now process any remaining parameters */
14233 
14234    for (x = 1; x < param_count; x++) {
14235       struct {
14236          char *name;
14237          char *value;
14238       } param;
14239 
14240       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
14241          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14242          continue;
14243       }
14244 
14245       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14246          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14247          continue;
14248       }
14249 
14250       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14251 
14252       if (param.value) {
14253          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14254             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14255             continue;
14256          }
14257       }
14258       confp->chan.echocancel.head.param_count++;
14259    }
14260 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 10837 of file chan_dahdi.c.

Referenced by pri_dchannel().

10838 {
10839    switch (redirectingreason) {
10840    case 0:
10841       return "UNKNOWN";
10842    case 1:
10843       return "BUSY";
10844    case 2:
10845       return "NO_REPLY";
10846    case 0xF:
10847       return "UNCONDITIONAL";
10848    default:
10849       return "NOREDIRECT";
10850    }
10851 }

static int reload ( void   )  [static]

Definition at line 15481 of file chan_dahdi.c.

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

15482 {
15483    int res = 0;
15484 
15485    res = setup_dahdi(1);
15486    if (res) {
15487       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15488       return -1;
15489    }
15490    return 0;
15491 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1934 of file chan_dahdi.c.

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

Referenced by dahdi_hangup().

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

static int restart_monitor ( void   )  [static]

Definition at line 8534 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, LOG_WARNING, and monlock.

Referenced by dahdi_hangup(), dahdi_request(), and setup_dahdi().

08535 {
08536    /* If we're supposed to be stopped -- stay stopped */
08537    if (monitor_thread == AST_PTHREADT_STOP)
08538       return 0;
08539    ast_mutex_lock(&monlock);
08540    if (monitor_thread == pthread_self()) {
08541       ast_mutex_unlock(&monlock);
08542       ast_log(LOG_WARNING, "Cannot kill myself\n");
08543       return -1;
08544    }
08545    if (monitor_thread != AST_PTHREADT_NULL) {
08546       /* Wake up the thread */
08547       pthread_kill(monitor_thread, SIGURG);
08548    } else {
08549       /* Start a new monitor */
08550       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08551          ast_mutex_unlock(&monlock);
08552          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08553          return -1;
08554       }
08555    }
08556    ast_mutex_unlock(&monlock);
08557    return 0;
08558 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2313 of file chan_dahdi.c.

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

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

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

static int restore_gains ( struct dahdi_pvt p  )  [static]

Definition at line 2194 of file chan_dahdi.c.

References ast_log(), dahdi_subchannel::dfd, 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().

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

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2240 of file chan_dahdi.c.

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

Referenced by dahdi_callwait(), and dahdi_handle_event().

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

static int send_callerid ( struct dahdi_pvt p  )  [static]

Definition at line 2370 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(), dahdi_subchannel::dfd, 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().

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

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 2175 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

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

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

Definition at line 2157 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

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

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

Definition at line 2139 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

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

static int setup_dahdi ( int  reload  )  [static]

Definition at line 15113 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(), global_jbconf, iflock, ast_variable::lineno, linksets, LOG_ERROR, LOG_NOTICE, LOG_WARNING, master, ast_variable::name, ast_variable::next, NUM_SPANS, pri_create_spanmap(), pri_create_trunkgroup(), pris, PROC_DAHDI_OPT_NOCHAN, PROC_DAHDI_OPT_NOWARN, process_dahdi(), pvts, restart_monitor(), ss7_linkset(), start_pri(), and ast_variable::value.

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

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

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 8713 of file chan_dahdi.c.

Referenced by mkintf().

08714 {
08715         return sigtype;
08716 }

static void ss7_apply_plan_to_number ( char *  buf,
size_t  size,
const struct dahdi_ss7 ss7,
const char *  number,
const unsigned  nai 
) [static]

Definition at line 9944 of file chan_dahdi.c.

References ast_strlen_zero(), dahdi_ss7::internationalprefix, dahdi_ss7::nationalprefix, dahdi_ss7::subscriberprefix, and dahdi_ss7::unknownprefix.

Referenced by ss7_linkset().

09945 {
09946    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
09947       if (size) {
09948          *buf = '\0';
09949       }
09950       return;
09951    }
09952    switch (nai) {
09953    case SS7_NAI_INTERNATIONAL:
09954       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09955       break;
09956    case SS7_NAI_NATIONAL:
09957       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09958       break;
09959    case SS7_NAI_SUBSCRIBER:
09960       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09961       break;
09962    case SS7_NAI_UNKNOWN:
09963       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09964       break;
09965    default:
09966       snprintf(buf, size, "%s", number);
09967       break;
09968    }
09969 }

static void ss7_block_cics ( struct dahdi_ss7 linkset,
int  startcic,
int  endcic,
unsigned int  dpc,
unsigned char  state[],
int  block 
) [inline, static]

Definition at line 9763 of file chan_dahdi.c.

References dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_ss7::numchans, dahdi_ss7::pvts, and dahdi_pvt::remotelyblocked.

Referenced by ss7_linkset().

09764 {
09765    int i;
09766 
09767    for (i = 0; i < linkset->numchans; i++) {
09768       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09769          if (state) {
09770             if (state[i])
09771                linkset->pvts[i]->remotelyblocked = block;
09772          } else
09773             linkset->pvts[i]->remotelyblocked = block;
09774       }
09775    }
09776 }

static int ss7_find_cic ( struct dahdi_ss7 linkset,
int  cic,
unsigned int  dpc 
) [static]

Definition at line 9718 of file chan_dahdi.c.

References dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_ss7::numchans, and dahdi_ss7::pvts.

Referenced by ss7_linkset().

09719 {
09720    int i;
09721    int winner = -1;
09722    for (i = 0; i < linkset->numchans; i++) {
09723       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09724          winner = i;
09725          break;
09726       }
09727    }
09728    return winner;
09729 }

static int ss7_grab ( struct dahdi_pvt pvt,
struct dahdi_ss7 pri 
) [inline, static]

Definition at line 1250 of file chan_dahdi.c.

References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_ss7::lock, and dahdi_ss7::master.

Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().

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

static void ss7_handle_cqm ( struct dahdi_ss7 linkset,
int  startcic,
int  endcic,
unsigned int  dpc 
) [static]

Definition at line 9731 of file chan_dahdi.c.

References ast_log(), dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_pvt::locallyblocked, LOG_WARNING, dahdi_ss7::numchans, dahdi_pvt::outgoing, dahdi_ss7::pvts, dahdi_pvt::remotelyblocked, dahdi_ss7::ss7, dahdi_pvt::ss7call, and status.

Referenced by ss7_linkset().

09732 {
09733    unsigned char status[32];
09734    struct dahdi_pvt *p = NULL;
09735    int i, offset;
09736 
09737    for (i = 0; i < linkset->numchans; i++) {
09738       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09739          p = linkset->pvts[i];
09740          offset = p->cic - startcic;
09741          status[offset] = 0;
09742          if (p->locallyblocked)
09743             status[offset] |= (1 << 0) | (1 << 4);
09744          if (p->remotelyblocked)
09745             status[offset] |= (1 << 1) | (1 << 5);
09746          if (p->ss7call) {
09747             if (p->outgoing)
09748                status[offset] |= (1 << 3);
09749             else
09750                status[offset] |= (1 << 2);
09751          } else
09752             status[offset] |= 0x3 << 2;
09753       }
09754    }
09755 
09756    if (p)
09757       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09758    else
09759       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09760    
09761 }

static void ss7_inservice ( struct dahdi_ss7 linkset,
int  startcic,
int  endcic,
unsigned int  dpc 
) [static]

Definition at line 9778 of file chan_dahdi.c.

References dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_pvt::inservice, dahdi_ss7::numchans, and dahdi_ss7::pvts.

Referenced by ss7_linkset().

09779 {
09780    int i;
09781 
09782    for (i = 0; i < linkset->numchans; i++) {
09783       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09784          linkset->pvts[i]->inservice = 1;
09785    }
09786 }

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

Definition at line 9975 of file chan_dahdi.c.

References ast_channel::_softhangup, dahdi_pvt::alerting, dahdi_pvt::alreadyhungup, AST_CAUSE_UNALLOCATED, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, ast_copy_string(), ast_debug, ast_dsp_set_features(), ast_exists_extension(), AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, ast_strlen_zero(), ast_tvnow(), ast_verbose, dahdi_ss7::called_nai, dahdi_ss7::calling_nai, dahdi_pvt::calling_party_cat, dahdi_pvt::callingpres, dahdi_pvt::charge_number, dahdi_pvt::cic, dahdi_pvt::cid_ani, dahdi_pvt::cid_ani2, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cid_ton, dahdi_pvt::context, dahdi_enable_ec(), dahdi_loopback(), dahdi_queue_frame(), dahdi_pvt::dialing, dahdi_pvt::dnid, dahdi_pvt::dpc, dahdi_pvt::dsp, dahdi_pvt::dsp_features, errno, dahdi_pvt::exten, dahdi_ss7::fds, dahdi_pvt::gen_add_nai, dahdi_pvt::gen_add_num_plan, dahdi_pvt::gen_add_number, dahdi_pvt::gen_add_pres_ind, dahdi_pvt::gen_add_type, dahdi_pvt::gen_dig_number, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::generic_name, ast_channel::hangupcause, dahdi_pvt::immediate, dahdi_pvt::inalarm, dahdi_pvt::inservice, dahdi_pvt::jip_number, dahdi_ss7::linkstate, LINKSTATE_DOWN, LINKSTATE_INALARM, LINKSTATE_STARTING, LINKSTATE_UP, dahdi_pvt::locallyblocked, dahdi_pvt::lock, dahdi_ss7::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, dahdi_pvt::loopedback, dahdi_subchannel::needanswer, dahdi_subchannel::needringing, dahdi_ss7::numchans, dahdi_ss7::numsigchans, dahdi_pvt::orig_called_num, dahdi_pvt::owner, dahdi_pvt::proceeding, dahdi_pvt::progress, dahdi_ss7::pvts, dahdi_pvt::redirecting_num, dahdi_pvt::remotelyblocked, dahdi_pvt::restartpending, dahdi_pvt::rlt, dahdi_ss7::ss7, ss7_apply_plan_to_number(), ss7_block_cics(), ss7_find_cic(), ss7_handle_cqm(), ss7_inservice(), ss7_pres_scr2cid_pres(), ss7_reset_linkset(), ss7_start_call(), dahdi_pvt::ss7call, dahdi_ss7::state, SUB_REAL, dahdi_pvt::subs, tv, and dahdi_pvt::use_callerid.

Referenced by setup_dahdi().

09976 {
09977    int res, i;
09978    struct timeval *next = NULL, tv;
09979    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
09980    struct ss7 *ss7 = linkset->ss7;
09981    ss7_event *e = NULL;
09982    struct dahdi_pvt *p;
09983    int chanpos;
09984    struct pollfd pollers[NUM_DCHANS];
09985    int cic;
09986    unsigned int dpc;
09987    int nextms = 0;
09988 
09989    ss7_start(ss7);
09990 
09991    while(1) {
09992       ast_mutex_lock(&linkset->lock);
09993       if ((next = ss7_schedule_next(ss7))) {
09994          tv = ast_tvnow();
09995          tv.tv_sec = next->tv_sec - tv.tv_sec;
09996          tv.tv_usec = next->tv_usec - tv.tv_usec;
09997          if (tv.tv_usec < 0) {
09998             tv.tv_usec += 1000000;
09999             tv.tv_sec -= 1;
10000          }
10001          if (tv.tv_sec < 0) {
10002             tv.tv_sec = 0;
10003             tv.tv_usec = 0;
10004          }
10005          nextms = tv.tv_sec * 1000;
10006          nextms += tv.tv_usec / 1000;
10007       }
10008       ast_mutex_unlock(&linkset->lock);
10009 
10010       for (i = 0; i < linkset->numsigchans; i++) {
10011          pollers[i].fd = linkset->fds[i];
10012          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
10013          pollers[i].revents = 0;
10014       }
10015 
10016       res = poll(pollers, linkset->numsigchans, nextms);
10017       if ((res < 0) && (errno != EINTR)) {
10018          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
10019       } else if (!res) {
10020          ast_mutex_lock(&linkset->lock);
10021          ss7_schedule_run(ss7);
10022          ast_mutex_unlock(&linkset->lock);
10023          continue;
10024       }
10025 
10026       ast_mutex_lock(&linkset->lock);
10027       for (i = 0; i < linkset->numsigchans; i++) {
10028          if (pollers[i].revents & POLLPRI) {
10029             int x;
10030             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
10031                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
10032             }
10033             switch (x) {
10034             case DAHDI_EVENT_OVERRUN:
10035                ast_debug(1, "Overrun detected!\n");
10036                break;
10037             case DAHDI_EVENT_BADFCS:
10038                ast_debug(1, "Bad FCS\n");
10039                break;
10040             case DAHDI_EVENT_ABORT:
10041                ast_debug(1, "HDLC Abort\n");
10042                break;
10043             case DAHDI_EVENT_ALARM:
10044                ast_log(LOG_ERROR, "Alarm on link!\n");
10045                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
10046                linkset->linkstate[i] &= ~LINKSTATE_UP;
10047                ss7_link_alarm(ss7, pollers[i].fd);
10048                break;
10049             case DAHDI_EVENT_NOALARM:
10050                ast_log(LOG_ERROR, "Alarm cleared on link\n");
10051                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
10052                linkset->linkstate[i] |= LINKSTATE_STARTING;
10053                ss7_link_noalarm(ss7, pollers[i].fd);
10054                break;
10055             default:
10056                ast_log(LOG_ERROR, "Got exception %d!\n", x);
10057                break;
10058             }
10059          }
10060 
10061          if (pollers[i].revents & POLLIN) {
10062             ast_mutex_lock(&linkset->lock);
10063             res = ss7_read(ss7, pollers[i].fd);
10064             ast_mutex_unlock(&linkset->lock);
10065          }
10066 
10067          if (pollers[i].revents & POLLOUT) {
10068             ast_mutex_lock(&linkset->lock);
10069             res = ss7_write(ss7, pollers[i].fd);
10070             ast_mutex_unlock(&linkset->lock);
10071             if (res < 0) {
10072                ast_debug(1, "Error in write %s\n", strerror(errno));
10073             }
10074          }
10075       }
10076 
10077       while ((e = ss7_check_event(ss7))) {
10078          switch (e->e) {
10079          case SS7_EVENT_UP:
10080             if (linkset->state != LINKSET_STATE_UP) {
10081                ast_verbose("--- SS7 Up ---\n");
10082                ss7_reset_linkset(linkset);
10083             }
10084             linkset->state = LINKSET_STATE_UP;
10085             break;
10086          case SS7_EVENT_DOWN:
10087             ast_verbose("--- SS7 Down ---\n");
10088             linkset->state = LINKSET_STATE_DOWN;
10089             for (i = 0; i < linkset->numchans; i++) {
10090                struct dahdi_pvt *p = linkset->pvts[i];
10091                if (p)
10092                   p->inalarm = 1;
10093             }
10094             break;
10095          case MTP2_LINK_UP:
10096             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
10097             break;
10098          case MTP2_LINK_DOWN:
10099             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
10100             break;
10101          case ISUP_EVENT_CPG:
10102             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
10103             if (chanpos < 0) {
10104                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
10105                break;
10106             }
10107             p = linkset->pvts[chanpos];
10108             ast_mutex_lock(&p->lock);
10109             switch (e->cpg.event) {
10110             case CPG_EVENT_ALERTING:
10111                p->alerting = 1;
10112                p->subs[SUB_REAL].needringing = 1;
10113                break;
10114             case CPG_EVENT_PROGRESS:
10115             case CPG_EVENT_INBANDINFO:
10116                {
10117                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
10118                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
10119                   dahdi_queue_frame(p, &f, linkset);
10120                   p->progress = 1;
10121                   p->dialing = 0;
10122                   if (p->dsp && p->dsp_features) {
10123                           ast_dsp_set_features(p->dsp, p->dsp_features);
10124                           p->dsp_features = 0;
10125                   }
10126                }
10127                break;
10128             default:
10129                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
10130             }
10131 
10132             ast_mutex_unlock(&p->lock);
10133             break;
10134          case ISUP_EVENT_RSC:
10135             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
10136             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
10137             if (chanpos < 0) {
10138                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
10139                break;
10140             }
10141             p = linkset->pvts[chanpos];
10142             ast_mutex_lock(&p->lock);
10143             p->inservice = 1;
10144             p->remotelyblocked = 0;
10145             dpc = p->dpc;
10146             isup_set_call_dpc(e->rsc.call, dpc);
10147             if (p->ss7call)
10148                p->ss7call = NULL;
10149             if (p->owner)
10150                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10151             ast_mutex_unlock(&p->lock);
10152             isup_rlc(ss7, e->rsc.call);
10153             break;
10154          case ISUP_EVENT_GRS:
10155             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
10156             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
10157             if (chanpos < 0) {
10158                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
10159                break;
10160             }
10161             p = linkset->pvts[chanpos];
10162             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
10163             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
10164             break;
10165          case ISUP_EVENT_CQM:
10166             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
10167             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
10168             break;
10169          case ISUP_EVENT_GRA:
10170             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
10171             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
10172             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
10173             break;
10174          case ISUP_EVENT_IAM:
10175             ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
10176             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
10177             if (chanpos < 0) {
10178                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
10179                isup_rel(ss7, e->iam.call, -1);
10180                break;
10181             }
10182             p = linkset->pvts[chanpos];
10183             ast_mutex_lock(&p->lock);
10184             if (p->owner) {
10185                if (p->ss7call == e->iam.call) {
10186                   ast_mutex_unlock(&p->lock);
10187                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
10188                   break;
10189                } else {
10190                   ast_mutex_unlock(&p->lock);
10191                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
10192                   break;
10193                }
10194             }
10195 
10196             dpc = p->dpc;
10197             p->ss7call = e->iam.call;
10198             isup_set_call_dpc(p->ss7call, dpc);
10199 
10200             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
10201                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
10202                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
10203             } else
10204                p->cid_num[0] = 0;
10205 
10206             if (p->immediate) {
10207                p->exten[0] = 's';
10208                p->exten[1] = '\0';
10209             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
10210                char *st;
10211                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
10212                st = strchr(p->exten, '#');
10213                if (st)
10214                   *st = '\0';
10215                } else
10216                   p->exten[0] = '\0';
10217 
10218             p->cid_ani[0] = '\0';
10219             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
10220                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
10221             else
10222                p->cid_name[0] = '\0';
10223             
10224             p->cid_ani2 = e->iam.oli_ani2;
10225             p->cid_ton = 0;
10226             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
10227             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
10228             p->gen_add_type = e->iam.gen_add_type;
10229             p->gen_add_nai = e->iam.gen_add_nai;
10230             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
10231             p->gen_add_num_plan = e->iam.gen_add_num_plan;
10232             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
10233             p->gen_dig_type = e->iam.gen_dig_type;
10234             p->gen_dig_scheme = e->iam.gen_dig_scheme;
10235             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
10236             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
10237             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
10238             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
10239             p->calling_party_cat = e->iam.calling_party_cat;
10240                
10241             /* Set DNID */
10242             if (!ast_strlen_zero(e->iam.called_party_num))
10243                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
10244             
10245             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
10246 
10247                if (e->iam.cot_check_required) {
10248                   dahdi_loopback(p, 1);
10249                } else
10250                   ss7_start_call(p, linkset);
10251             } else {
10252                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
10253                p->alreadyhungup = 1;
10254                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
10255             }
10256             ast_mutex_unlock(&p->lock);
10257             break;
10258          case ISUP_EVENT_COT:
10259             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
10260             if (chanpos < 0) {
10261                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
10262                isup_rel(ss7, e->cot.call, -1);
10263                break;
10264             }
10265             p = linkset->pvts[chanpos];
10266 
10267             ast_mutex_lock(&p->lock);
10268 
10269             if (p->loopedback) {
10270                dahdi_loopback(p, 0);
10271                ss7_start_call(p, linkset);
10272             }
10273 
10274             ast_mutex_unlock(&p->lock);
10275 
10276             break;
10277          case ISUP_EVENT_CCR:
10278             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
10279             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
10280             if (chanpos < 0) {
10281                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
10282                break;
10283             }
10284 
10285             p = linkset->pvts[chanpos];
10286 
10287             ast_mutex_lock(&p->lock);
10288             dahdi_loopback(p, 1);
10289             ast_mutex_unlock(&p->lock);
10290 
10291             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
10292             break;
10293          case ISUP_EVENT_CVT:
10294             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
10295             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
10296             if (chanpos < 0) {
10297                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
10298                break;
10299             }
10300             
10301             p = linkset->pvts[chanpos];
10302             
10303             ast_mutex_lock(&p->lock);
10304             dahdi_loopback(p, 1);
10305             ast_mutex_unlock(&p->lock);
10306             
10307             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
10308             break;
10309          case ISUP_EVENT_REL:
10310             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
10311             if (chanpos < 0) {
10312                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
10313                break;
10314             }
10315             p = linkset->pvts[chanpos];
10316             ast_mutex_lock(&p->lock);
10317             if (p->owner) {
10318                p->owner->hangupcause = e->rel.cause;
10319                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
10320             } else if (!p->restartpending)
10321                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
10322 
10323             /* End the loopback if we have one */
10324             dahdi_loopback(p, 0);
10325 
10326             isup_rlc(ss7, e->rel.call);
10327             p->ss7call = NULL;
10328 
10329             ast_mutex_unlock(&p->lock);
10330             break;
10331          case ISUP_EVENT_ACM:
10332             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
10333             if (chanpos < 0) {
10334                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
10335                isup_rel(ss7, e->acm.call, -1);
10336                break;
10337             } else {
10338                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
10339 
10340                p = linkset->pvts[chanpos];
10341 
10342                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
10343                
10344                if (e->acm.call_ref_ident > 0) {
10345                   p->rlt = 1; /* Setting it but not using it here*/
10346                }
10347 
10348                ast_mutex_lock(&p->lock);
10349                dahdi_queue_frame(p, &f, linkset);
10350                p->proceeding = 1;
10351                p->dialing = 0;
10352                /* Send alerting if subscriber is free */
10353                if (e->acm.called_party_status_ind == 1) {
10354                   p->alerting = 1;
10355                   p->subs[SUB_REAL].needringing = 1;
10356                }
10357                ast_mutex_unlock(&p->lock);
10358             }
10359             break;
10360          case ISUP_EVENT_CGB:
10361             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
10362             if (chanpos < 0) {
10363                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
10364                break;
10365             }
10366             p = linkset->pvts[chanpos];
10367             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
10368             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
10369             break;
10370          case ISUP_EVENT_CGU:
10371             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
10372             if (chanpos < 0) {
10373                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
10374                break;
10375             }
10376             p = linkset->pvts[chanpos];
10377             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
10378             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
10379             break;
10380          case ISUP_EVENT_UCIC:
10381             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
10382             if (chanpos < 0) {
10383                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
10384                break;
10385             }
10386             p = linkset->pvts[chanpos];
10387             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
10388             ast_mutex_lock(&p->lock);
10389             p->remotelyblocked = 1;
10390             p->inservice = 0;
10391             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
10392             break;
10393          case ISUP_EVENT_BLO:
10394             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
10395             if (chanpos < 0) {
10396                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
10397                break;
10398             }
10399             p = linkset->pvts[chanpos];
10400             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
10401             ast_mutex_lock(&p->lock);
10402             p->remotelyblocked = 1;
10403             ast_mutex_unlock(&p->lock);
10404             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
10405             break;
10406          case ISUP_EVENT_BLA:
10407             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
10408             if (chanpos < 0) {
10409                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
10410                break;
10411             }
10412             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
10413             p = linkset->pvts[chanpos];
10414             ast_mutex_lock(&p->lock);
10415             p->locallyblocked = 1;
10416             ast_mutex_unlock(&p->lock);
10417             break;
10418          case ISUP_EVENT_UBL:
10419             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
10420             if (chanpos < 0) {
10421                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
10422                break;
10423             }
10424             p = linkset->pvts[chanpos];
10425             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
10426             ast_mutex_lock(&p->lock);
10427             p->remotelyblocked = 0;
10428             ast_mutex_unlock(&p->lock);
10429             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
10430             break;
10431          case ISUP_EVENT_UBA:
10432             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
10433             if (chanpos < 0) {
10434                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
10435                break;
10436             }
10437             p = linkset->pvts[chanpos];
10438             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
10439             ast_mutex_lock(&p->lock);
10440             p->locallyblocked = 0;
10441             ast_mutex_unlock(&p->lock);
10442             break;
10443          case ISUP_EVENT_CON:
10444          case ISUP_EVENT_ANM:
10445             if (e->e == ISUP_EVENT_CON)
10446                cic = e->con.cic;
10447             else
10448                cic = e->anm.cic;
10449 
10450             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
10451             if (chanpos < 0) {
10452                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
10453                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
10454                break;
10455             } else {
10456                p = linkset->pvts[chanpos];
10457                ast_mutex_lock(&p->lock);
10458                p->subs[SUB_REAL].needanswer = 1;
10459                if (p->dsp && p->dsp_features) {
10460                        ast_dsp_set_features(p->dsp, p->dsp_features);
10461                        p->dsp_features = 0;
10462                }
10463                dahdi_enable_ec(p);
10464                ast_mutex_unlock(&p->lock);
10465             }
10466             break;
10467          case ISUP_EVENT_RLC:
10468             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
10469             if (chanpos < 0) {
10470                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
10471                break;
10472             } else {
10473                p = linkset->pvts[chanpos];
10474                ast_mutex_lock(&p->lock);
10475                if (p->alreadyhungup)
10476                   p->ss7call = NULL;
10477                else
10478                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
10479                ast_mutex_unlock(&p->lock);
10480                }
10481                break;
10482          case ISUP_EVENT_FAA:
10483             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
10484             if (chanpos < 0) {
10485                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
10486                break;
10487             } else {
10488                p = linkset->pvts[chanpos];
10489                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
10490                ast_mutex_lock(&p->lock);
10491                if (p->alreadyhungup){
10492                   p->ss7call = NULL;
10493                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
10494                }
10495                ast_mutex_unlock(&p->lock);
10496             }
10497             break;
10498          default:
10499             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
10500             break;
10501          }
10502       }
10503       ast_mutex_unlock(&linkset->lock);
10504    }
10505 
10506    return 0;
10507 }

static int ss7_pres_scr2cid_pres ( char  presentation_ind,
char  screening_ind 
) [static]

Definition at line 9970 of file chan_dahdi.c.

Referenced by ss7_linkset().

09971 {
09972     return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
09973 }

static void ss7_rel ( struct dahdi_ss7 ss7  )  [inline, static]

Definition at line 1245 of file chan_dahdi.c.

References ast_mutex_unlock(), and dahdi_ss7::lock.

Referenced by dahdi_answer(), dahdi_call(), dahdi_hangup(), and dahdi_indicate().

01246 {
01247    ast_mutex_unlock(&ss7->lock);
01248 }

static void ss7_reset_linkset ( struct dahdi_ss7 linkset  )  [static]

Definition at line 9788 of file chan_dahdi.c.

References ast_verbose, dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_ss7::numchans, dahdi_ss7::pvts, and dahdi_ss7::ss7.

Referenced by ss7_linkset().

09789 {
09790    int i, startcic = -1, endcic, dpc;
09791 
09792    if (linkset->numchans <= 0)
09793       return;
09794 
09795    startcic = linkset->pvts[0]->cic;
09796    /* DB: CIC's DPC fix */
09797    dpc = linkset->pvts[0]->dpc;
09798 
09799    for (i = 0; i < linkset->numchans; i++) {
09800       if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
09801          continue;
09802       } else {
09803          endcic = linkset->pvts[i]->cic;
09804          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09805          isup_grs(linkset->ss7, startcic, endcic, dpc);
09806 
09807          /* DB: CIC's DPC fix */
09808          if (linkset->pvts[i+1]) {
09809             startcic = linkset->pvts[i+1]->cic;
09810             dpc = linkset->pvts[i+1]->dpc;
09811          }
09812       }
09813    }
09814 }

static struct dahdi_ss7* ss7_resolve_linkset ( int  linkset  )  [static, read]

Definition at line 8699 of file chan_dahdi.c.

References linksets, and NUM_SPANS.

Referenced by linkset_addsigchan(), mkintf(), and process_dahdi().

08700 {
08701    if ((linkset < 0) || (linkset >= NUM_SPANS))
08702       return NULL;
08703    else
08704       return &linksets[linkset - 1];
08705 }

static void ss7_start_call ( struct dahdi_pvt p,
struct dahdi_ss7 linkset 
) [static]

Definition at line 9828 of file chan_dahdi.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_RING, ast_strlen_zero(), ast_verb, dahdi_pvt::call_ref_ident, dahdi_pvt::call_ref_pc, dahdi_pvt::calling_party_cat, dahdi_pvt::channel, dahdi_pvt::charge_number, dahdi_pvt::cic, dahdi_enable_ec(), dahdi_new(), dahdi_setlaw(), dahdi_subchannel::dfd, errno, dahdi_pvt::exten, dahdi_ss7::flags, dahdi_pvt::gen_add_number, dahdi_pvt::gen_dig_number, dahdi_pvt::gen_dig_scheme, dahdi_pvt::gen_dig_type, dahdi_pvt::generic_name, dahdi_pvt::jip_number, LINKSET_FLAG_EXPLICITACM, dahdi_pvt::lock, dahdi_ss7::lock, LOG_WARNING, dahdi_pvt::lspi_ident, dahdi_pvt::orig_called_num, pbx_builtin_setvar_helper(), dahdi_pvt::proceeding, dahdi_pvt::redirecting_num, dahdi_ss7::ss7, dahdi_pvt::ss7call, SUB_REAL, dahdi_pvt::subs, and dahdi_ss7::type.

Referenced by ss7_linkset().

09829 {
09830    struct ss7 *ss7 = linkset->ss7;
09831    int res;
09832    int law = 1;
09833    struct ast_channel *c;
09834    char tmp[256];
09835 
09836    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09837       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09838    
09839    if (linkset->type == SS7_ITU)
09840       law = DAHDI_LAW_ALAW;
09841    else
09842       law = DAHDI_LAW_MULAW;
09843 
09844    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09845    if (res < 0) 
09846       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09847    
09848    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09849       p->proceeding = 1;
09850       isup_acm(ss7, p->ss7call);
09851    }
09852 
09853    ast_mutex_unlock(&linkset->lock);
09854    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09855 
09856    if (!c) {
09857       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09858       /* Holding this lock is assumed entering the function */
09859       ast_mutex_lock(&linkset->lock);
09860       return;
09861    } else
09862       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09863 
09864    dahdi_enable_ec(p);
09865 
09866    /* We only reference these variables in the context of the ss7_linkset function
09867     * when receiving either and IAM or a COT message.  Since they are only accessed
09868     * from this context, we should be safe to unlock around them */
09869 
09870    ast_mutex_unlock(&p->lock);
09871 
09872    if (!ast_strlen_zero(p->charge_number)) {
09873       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09874       /* Clear this after we set it */
09875       p->charge_number[0] = 0;
09876    }
09877    if (!ast_strlen_zero(p->gen_add_number)) {
09878       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09879       /* Clear this after we set it */
09880       p->gen_add_number[0] = 0;
09881    }
09882    if (!ast_strlen_zero(p->jip_number)) {
09883       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09884       /* Clear this after we set it */
09885       p->jip_number[0] = 0;
09886    }
09887    if (!ast_strlen_zero(p->gen_dig_number)) {
09888       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09889       /* Clear this after we set it */
09890       p->gen_dig_number[0] = 0;
09891    }
09892    if (!ast_strlen_zero(p->orig_called_num)) {
09893       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09894       /* Clear this after we set it */
09895       p->orig_called_num[0] = 0;
09896    }
09897 
09898    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09899    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09900    /* Clear this after we set it */
09901    p->gen_dig_type = 0;
09902 
09903    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09904    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09905    /* Clear this after we set it */
09906    p->gen_dig_scheme = 0;
09907 
09908    if (!ast_strlen_zero(p->lspi_ident)) {
09909       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09910       /* Clear this after we set it */
09911       p->lspi_ident[0] = 0;
09912    }
09913 
09914    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09915    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09916    /* Clear this after we set it */
09917    p->call_ref_ident = 0;
09918 
09919    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09920    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09921    /* Clear this after we set it */
09922    p->call_ref_pc = 0;
09923 
09924    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09925    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09926    /* Clear this after we set it */
09927    p->calling_party_cat = 0;
09928 
09929    if (!ast_strlen_zero(p->redirecting_num)) {
09930       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09931       /* Clear this after we set it */
09932       p->redirecting_num[0] = 0;
09933    }
09934    if (!ast_strlen_zero(p->generic_name)) {
09935       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09936       /* Clear this after we set it */
09937       p->generic_name[0] = 0;
09938    }
09939 
09940    ast_mutex_lock(&p->lock);
09941    ast_mutex_lock(&linkset->lock);
09942 }

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

Definition at line 6553 of file chan_dahdi.c.

References ast_channel::_state, alloc_sub(), ARRAY_LEN, ast_bridged_channel(), ast_canmatch_extension(), AST_CAUSE_UNALLOCATED, ast_cond_signal(), AST_CONTROL_RING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_db_put(), ast_debug, ast_dsp_digitreset(), ast_dsp_free(), ast_dsp_set_digitmode(), ast_exists_extension(), AST_FRAME_CONTROL, AST_FRAME_DTMF, ast_free, ast_frfree, ast_hangup(), ast_ignore_pattern(), AST_LAW, ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_queue_control(), ast_read(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), ast_shrink_phone_number(), ast_smdi_md_message_destroy(), 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(), ASTOBJ_UNREF, 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, CID_MSGWAITING, ast_callerid::cid_name, dahdi_pvt::cid_name, CID_NOMSGWAITING, 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, CID_START_RING, 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_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_frame::frametype, ast_smdi_md_message::fwd_st, ast_channel::hangupcause, dahdi_pvt::hanguponpolarityswitch, dahdi_pvt::hardwaredtmf, dahdi_pvt::hidecallerid, dahdi_pvt::immediate, ISTRUNK, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_rpas, my_getsigstr(), name, NEED_MFDETECT, notify_message(), dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pvt::pri, quit, distRingData::range, restore_gains(), distRingData::ring, dahdi_distRings::ringContext, dahdi_distRings::ringnum, ast_channel::rings, 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_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, ast_frame::subclass, 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(), mwi_thread(), and pri_dchannel().

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

static int start_pri ( struct dahdi_pri pri  )  [static]

Definition at line 12012 of file chan_dahdi.c.

References ast_log(), ast_pthread_create_background, 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::master, dahdi_pri::nodetype, dahdi_pri::nsf, dahdi_pri::overlapdial, dahdi_pri::pri, pri_dchannel(), dahdi_pri::resetpos, dahdi_pri::sig, SIG_BRI, SIG_BRI_PTMP, and dahdi_pri::switchtype.

Referenced by setup_dahdi().

12013 {
12014    int res, x;
12015    struct dahdi_params p;
12016    struct dahdi_bufferinfo bi;
12017    struct dahdi_spaninfo si;
12018    int i;
12019    
12020    for (i = 0; i < NUM_DCHANS; i++) {
12021       if (!pri->dchannels[i])
12022          break;
12023       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
12024       x = pri->dchannels[i];
12025       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12026          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12027          return -1;
12028       }
12029       memset(&p, 0, sizeof(p));
12030       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12031       if (res) {
12032          dahdi_close_pri_fd(pri, i);
12033          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12034          return -1;
12035       }
12036       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12037          dahdi_close_pri_fd(pri, i);
12038          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12039          return -1;
12040       }
12041       memset(&si, 0, sizeof(si));
12042       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12043       if (res) {
12044          dahdi_close_pri_fd(pri, i);
12045          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12046       }
12047       if (!si.alarms)
12048          pri->dchanavail[i] |= DCHAN_NOTINALARM;
12049       else
12050          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12051       memset(&bi, 0, sizeof(bi));
12052       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12053       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12054       bi.numbufs = 32;
12055       bi.bufsize = 1024;
12056       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12057          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12058          dahdi_close_pri_fd(pri, i);
12059          return -1;
12060       }
12061       switch (pri->sig) {
12062          case SIG_BRI:
12063             pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12064             break;
12065          case SIG_BRI_PTMP:
12066             pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12067             break;
12068          default:
12069             pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12070       }
12071       /* Force overlap dial if we're doing GR-303! */
12072       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12073          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12074       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12075 #ifdef HAVE_PRI_INBANDDISCONNECT
12076       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12077 #endif
12078       /* Enslave to master if appropriate */
12079       if (i)
12080          pri_enslave(pri->dchans[0], pri->dchans[i]);
12081       if (!pri->dchans[i]) {
12082          dahdi_close_pri_fd(pri, i);
12083          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12084          return -1;
12085       }
12086       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12087       pri_set_nsf(pri->dchans[i], pri->nsf);
12088 #ifdef PRI_GETSET_TIMERS
12089       for (x = 0; x < PRI_MAX_TIMERS; x++) {
12090          if (pritimers[x] != 0)
12091             pri_set_timer(pri->dchans[i], x, pritimers[x]);
12092       }
12093 #endif
12094    }
12095    /* Assume primary is the one we use */
12096    pri->pri = pri->dchans[0];
12097    pri->resetpos = -1;
12098    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12099       for (i = 0; i < NUM_DCHANS; i++) {
12100          if (!pri->dchannels[i])
12101             break;
12102          dahdi_close_pri_fd(pri, i);
12103       }
12104       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12105       return -1;
12106    }
12107    return 0;
12108 }

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 14103 of file chan_dahdi.c.

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

14104 {
14105 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14106    int y;
14107 #endif
14108 #ifdef HAVE_PRI
14109    for (y = 0; y < NUM_SPANS; y++)
14110       ast_mutex_destroy(&pris[y].lock);
14111 #endif
14112 #ifdef HAVE_SS7
14113    for (y = 0; y < NUM_SPANS; y++)
14114       ast_mutex_destroy(&linksets[y].lock);
14115 #endif /* HAVE_SS7 */
14116    return __unload_module();
14117 }

static int update_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1948 of file chan_dahdi.c.

References ast_debug, dahdi_pvt::channel, conf_add(), conf_del(), dahdi_pvt::confno, dahdi_subchannel::dfd, GET_CHANNEL, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, isslavenative(), dahdi_pvt::master, MAX_SLAVES, dahdi_pvt::slaves, SUB_REAL, and dahdi_pvt::subs.

Referenced by __dahdi_exception(), dahdi_bridge(), dahdi_fixup(), dahdi_handle_event(), dahdi_hangup(), dahdi_unlink(), and mkintf().

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

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

Definition at line 1315 of file chan_dahdi.c.

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

Referenced by pri_fixup_principle(), and swap_subs().

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


Variable Documentation

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

Definition at line 15515 of file chan_dahdi.c.

int alarm

Definition at line 1713 of file chan_dahdi.c.

Referenced by alarm2str().

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

Referenced by alarm2str().

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

Definition at line 1289 of file chan_dahdi.c.

Definition at line 15515 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

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

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

Definition at line 168 of file chan_dahdi.c.

int cur_adjpointcode = -1 [static]

Definition at line 383 of file chan_dahdi.c.

int cur_cicbeginswith = -1 [static]

Definition at line 382 of file chan_dahdi.c.

int cur_defaultdpc = -1 [static]

Definition at line 385 of file chan_dahdi.c.

int cur_linkset = -1 [static]

Definition at line 380 of file chan_dahdi.c.

int cur_networkindicator = -1 [static]

Definition at line 384 of file chan_dahdi.c.

int cur_pointcode = -1 [static]

Definition at line 381 of file chan_dahdi.c.

int cur_ss7type = -1 [static]

Definition at line 379 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 13336 of file chan_dahdi.c.

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 12467 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 3252 of file chan_dahdi.c.

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

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

Definition at line 3254 of file chan_dahdi.c.

struct ast_cli_entry dahdi_ss7_cli[] [static]

Definition at line 14014 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1197 of file chan_dahdi.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 118 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 226 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 227 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 238 of file chan_dahdi.c.

char* events[] [static]

Definition at line 1690 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

Definition at line 254 of file chan_dahdi.c.

Referenced by disa_exec().

int gendigittimeout = 8000 [static]

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

Definition at line 257 of file chan_dahdi.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 125 of file chan_dahdi.c.

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

int ifcount = 0 [static]

Definition at line 266 of file chan_dahdi.c.

struct dahdi_pvt * ifend [static]
struct dahdi_pvt * iflist [static]
ast_mutex_t iflock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]
struct ast_channel inuse [static]
const char* lbostr[] [static]

Definition at line 106 of file chan_dahdi.c.

struct dahdi_ss7 linksets[NUM_SPANS] [static]
int matchdigittimeout = 3000 [static]

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

Definition at line 260 of file chan_dahdi.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

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

Definition at line 278 of file chan_dahdi.c.

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

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

Definition at line 274 of file chan_dahdi.c.

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

Definition at line 279 of file chan_dahdi.c.

int mwi_thread_count = 0 [static]

Definition at line 284 of file chan_dahdi.c.

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

Definition at line 281 of file chan_dahdi.c.

Referenced by dahdi_restart(), and mwi_send_thread().

int mwilevel = 512 [static]

Definition at line 242 of file chan_dahdi.c.

char mwimonitornotify[PATH_MAX] = "" [static]

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

Definition at line 232 of file chan_dahdi.c.

int mwisend_rpas = 0 [static]

Definition at line 233 of file chan_dahdi.c.

char* name

Definition at line 1714 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1267 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 286 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 240 of file chan_dahdi.c.

char parkinglot[AST_MAX_EXTENSION] = "" [static]
int pridebugfd = -1 [static]

Definition at line 249 of file chan_dahdi.c.

ast_mutex_t pridebugfdlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]
char pridebugfilename[1024] = "" [static]

Definition at line 250 of file chan_dahdi.c.

struct dahdi_pri pris[NUM_SPANS] [static]
char progzone[10] = "" [static]

Definition at line 235 of file chan_dahdi.c.

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

Definition at line 283 of file chan_dahdi.c.

Referenced by dahdi_restart().

int ringt_base = DEFAULT_RINGT [static]

Configured ring timeout base.

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

Definition at line 341 of file chan_dahdi.c.

struct dahdi_pvt* round_robin[32]

Definition at line 1224 of file chan_dahdi.c.

Definition at line 280 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 285 of file chan_dahdi.c.

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

Definition at line 282 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

char* subnames[] [static]
Initial value:
 {
   "Real",
   "Callwait",
   "Threeway"
}

Definition at line 486 of file chan_dahdi.c.

const char tdesc[] [static]

Definition at line 159 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 237 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 1268 of file chan_dahdi.c.


Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1