Thu Apr 8 01:21:56 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 225 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmfup(), and process_dahdi().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 224 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 223 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

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

Referenced by dahdi_callwait().

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

300 ms

Definition at line 330 of file chan_dahdi.c.

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

Definition at line 1295 of file chan_dahdi.c.

Referenced by dahdi_new().

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

Definition at line 1296 of file chan_dahdi.c.

Referenced by dahdi_handle_event(), and dahdi_new().

#define CHAN_PSEUDO   -2
#define CHANNEL_PSEUDO   -12

Definition at line 152 of file chan_dahdi.c.

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

500 ms

Definition at line 332 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 512 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 513 of file chan_dahdi.c.

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

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

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_OUTGOING   1

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

Referenced by pri_find_dchan(), and pri_is_up().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 210 of file chan_dahdi.c.

Referenced by build_status(), pri_dchannel(), and start_pri().

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 209 of file chan_dahdi.c.

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

#define DCHAN_UP   (1 << 2)

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

Referenced by dahdi_chan_conf_default().

#define DEFAULT_PRI_DEBUG   0

Definition at line 453 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

Definition at line 334 of file chan_dahdi.c.

#define END_SILENCE_LEN   400

Referenced by dahdi_sendtext().

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

Definition at line 1220 of file chan_dahdi.c.

Referenced by update_conf().

#define HANGUP   1

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

Referenced by dahdi_indicate(), and ss_thread().

#define LINKSET_FLAG_EXPLICITACM   (1 << 0)

Definition at line 353 of file chan_dahdi.c.

Referenced by process_dahdi(), and ss7_start_call().

#define LINKSTATE_DOWN   (1 << 3)

Definition at line 349 of file chan_dahdi.c.

Referenced by linkset_addsigchan(), and ss7_linkset().

#define LINKSTATE_INALARM   (1 << 0)

Definition at line 346 of file chan_dahdi.c.

Referenced by linkset_addsigchan(), and ss7_linkset().

#define LINKSTATE_STARTING   (1 << 1)

Definition at line 347 of file chan_dahdi.c.

Referenced by ss7_linkset().

#define LINKSTATE_UP   (1 << 2)

Definition at line 348 of file chan_dahdi.c.

Referenced by ss7_linkset().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 327 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 205 of file chan_dahdi.c.

Referenced by mkintf().

#define MAX_SLAVES   4
#define MIN_MS_SINCE_FLASH   ( (2000) )

2000 ms

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

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 1267 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_DCHANS   4

No more than 4 d-channels

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

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

#define POLARITY_REV   1

Definition at line 472 of file chan_dahdi.c.

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

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

Definition at line 392 of file chan_dahdi.c.

Referenced by pri_dchannel(), and pri_find_principle().

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

Definition at line 394 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 393 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 14295 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 14297 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 325 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 196 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 197 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 351 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 15531 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 7941 of file chan_dahdi.c.

07941                     {
07942    MWI_SEND_SA,
07943  MWI_SEND_SA_WAIT,
07944  MWI_SEND_PAUSE,
07945  MWI_SEND_SPILL,
07946  MWI_SEND_CLEANUP,
07947  MWI_SEND_DONE
07948 };


Function Documentation

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

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

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

static void __reg_module ( void   )  [static]

Definition at line 15547 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

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

14059 {
14060    struct dahdi_pvt *p;
14061 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14062    int i, j;
14063 #endif
14064 
14065 #ifdef HAVE_PRI
14066    for (i = 0; i < NUM_SPANS; i++) {
14067       if (pris[i].master != AST_PTHREADT_NULL) 
14068          pthread_cancel(pris[i].master);
14069    }
14070    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
14071    ast_unregister_application(dahdi_send_keypad_facility_app);
14072 #endif
14073 #if defined(HAVE_SS7)
14074    for (i = 0; i < NUM_SPANS; i++) {
14075       if (linksets[i].master != AST_PTHREADT_NULL)
14076          pthread_cancel(linksets[i].master);
14077       }
14078    ast_cli_unregister_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(struct ast_cli_entry));
14079 #endif
14080 
14081    ast_cli_unregister_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
14082    ast_manager_unregister( "DAHDIDialOffhook" );
14083    ast_manager_unregister( "DAHDIHangup" );
14084    ast_manager_unregister( "DAHDITransfer" );
14085    ast_manager_unregister( "DAHDIDNDoff" );
14086    ast_manager_unregister( "DAHDIDNDon" );
14087    ast_manager_unregister("DAHDIShowChannels");
14088    ast_manager_unregister("DAHDIRestart");
14089    ast_channel_unregister(&dahdi_tech);
14090    ast_mutex_lock(&iflock);
14091    /* Hangup all interfaces if they have an owner */
14092    p = iflist;
14093    while (p) {
14094       if (p->owner)
14095          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
14096       p = p->next;
14097    }
14098    ast_mutex_unlock(&iflock);
14099    ast_mutex_lock(&monlock);
14100    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14101       pthread_cancel(monitor_thread);
14102       pthread_kill(monitor_thread, SIGURG);
14103       pthread_join(monitor_thread, NULL);
14104    }
14105    monitor_thread = AST_PTHREADT_STOP;
14106    ast_mutex_unlock(&monlock);
14107 
14108    destroy_all_channels();
14109 
14110 #if defined(HAVE_PRI)
14111    for (i = 0; i < NUM_SPANS; i++) {
14112       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
14113          pthread_join(pris[i].master, NULL);
14114       for (j = 0; j < NUM_DCHANS; j++) {
14115          dahdi_close_pri_fd(&(pris[i]), j);
14116       }
14117    }
14118 #endif
14119 
14120 #if defined(HAVE_SS7)
14121    for (i = 0; i < NUM_SPANS; i++) {
14122       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
14123          pthread_join(linksets[i].master, NULL);
14124       for (j = 0; j < NUM_DCHANS; j++) {
14125          dahdi_close_ss7_fd(&(linksets[i]), j);
14126       }
14127    }
14128 #endif
14129 
14130    ast_cond_destroy(&mwi_thread_complete);
14131    ast_cond_destroy(&ss_thread_complete);
14132    return 0;
14133 }

static void __unreg_module ( void   )  [static]

Definition at line 15547 of file chan_dahdi.c.

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

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

13489 {
13490    struct dahdi_pvt *p = NULL;
13491    const char *channel = astman_get_header(m, "DAHDIChannel");
13492    const char *number = astman_get_header(m, "Number");
13493    int i;
13494 
13495    if (ast_strlen_zero(channel)) {
13496       astman_send_error(s, m, "No channel specified");
13497       return 0;
13498    }
13499    if (ast_strlen_zero(number)) {
13500       astman_send_error(s, m, "No number specified");
13501       return 0;
13502    }
13503    p = find_channel(atoi(channel));
13504    if (!p) {
13505       astman_send_error(s, m, "No such channel");
13506       return 0;
13507    }
13508    if (!p->owner) {
13509       astman_send_error(s, m, "Channel does not have it's owner");
13510       return 0;
13511    }
13512    for (i = 0; i < strlen(number); i++) {
13513       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
13514       dahdi_queue_frame(p, &f, NULL); 
13515    }
13516    astman_send_ack(s, m, "DAHDIDialOffhook");
13517    return 0;
13518 }

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

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

13432 {
13433    struct dahdi_pvt *p = NULL;
13434    const char *channel = astman_get_header(m, "DAHDIChannel");
13435 
13436    if (ast_strlen_zero(channel)) {
13437       astman_send_error(s, m, "No channel specified");
13438       return 0;
13439    }
13440    p = find_channel(atoi(channel));
13441    if (!p) {
13442       astman_send_error(s, m, "No such channel");
13443       return 0;
13444    }
13445    p->dnd = 0;
13446    astman_send_ack(s, m, "DND Disabled");
13447    return 0;
13448 }

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

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

13413 {
13414    struct dahdi_pvt *p = NULL;
13415    const char *channel = astman_get_header(m, "DAHDIChannel");
13416 
13417    if (ast_strlen_zero(channel)) {
13418       astman_send_error(s, m, "No channel specified");
13419       return 0;
13420    }
13421    p = find_channel(atoi(channel));
13422    if (!p) {
13423       astman_send_error(s, m, "No such channel");
13424       return 0;
13425    }
13426    p->dnd = 1;
13427    astman_send_ack(s, m, "DND Enabled");
13428    return 0;
13429 }

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

Definition at line 12705 of file chan_dahdi.c.

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

Referenced by load_module().

12706 {
12707    if (dahdi_restart() != 0) {
12708       astman_send_error(s, m, "Failed rereading DAHDI configuration");
12709       return 1;
12710    }
12711    astman_send_ack(s, m, "DAHDIRestart: Success");
12712    return 0;
12713 }

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

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

13521 {
13522    struct dahdi_pvt *tmp = NULL;
13523    const char *id = astman_get_header(m, "ActionID");
13524    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
13525    char idText[256] = "";
13526    int channels = 0;
13527    int dahdichanquery = -1;
13528    if (!ast_strlen_zero(dahdichannel)) {
13529       dahdichanquery = atoi(dahdichannel);
13530    }
13531 
13532    astman_send_ack(s, m, "DAHDI channel status will follow");
13533    if (!ast_strlen_zero(id))
13534       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
13535 
13536    ast_mutex_lock(&iflock);
13537    
13538    tmp = iflist;
13539    while (tmp) {
13540       if (tmp->channel > 0) {
13541          int alm = get_alarms(tmp);
13542 
13543          /* If a specific channel is queried for, only deliver status for that channel */
13544          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
13545             continue;
13546 
13547          channels++;
13548          if (tmp->owner) {
13549             /* Add data if we have a current call */
13550             astman_append(s,
13551                "Event: DAHDIShowChannels\r\n"
13552                "DAHDIChannel: %d\r\n"
13553                "Channel: %s\r\n"
13554                "Uniqueid: %s\r\n"
13555                "AccountCode: %s\r\n"
13556                "Signalling: %s\r\n"
13557                "SignallingCode: %d\r\n"
13558                "Context: %s\r\n"
13559                "DND: %s\r\n"
13560                "Alarm: %s\r\n"
13561                "%s"
13562                "\r\n",
13563                tmp->channel, 
13564                tmp->owner->name,
13565                tmp->owner->uniqueid,
13566                tmp->owner->accountcode,
13567                sig2str(tmp->sig), 
13568                tmp->sig,
13569                tmp->context, 
13570                tmp->dnd ? "Enabled" : "Disabled",
13571                alarm2str(alm), idText);
13572          } else {
13573             astman_append(s,
13574                "Event: DAHDIShowChannels\r\n"
13575                "DAHDIChannel: %d\r\n"
13576                "Signalling: %s\r\n"
13577                "SignallingCode: %d\r\n"
13578                "Context: %s\r\n"
13579                "DND: %s\r\n"
13580                "Alarm: %s\r\n"
13581                "%s"
13582                "\r\n",
13583                tmp->channel, sig2str(tmp->sig), tmp->sig, 
13584                tmp->context, 
13585                tmp->dnd ? "Enabled" : "Disabled",
13586                alarm2str(alm), idText);
13587          }
13588       } 
13589 
13590       tmp = tmp->next;
13591    }
13592 
13593    ast_mutex_unlock(&iflock);
13594    
13595    astman_append(s, 
13596       "Event: DAHDIShowChannelsComplete\r\n"
13597       "%s"
13598       "Items: %d\r\n"
13599       "\r\n", 
13600       idText,
13601       channels);
13602    return 0;
13603 }

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

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

13451 {
13452    struct dahdi_pvt *p = NULL;
13453    const char *channel = astman_get_header(m, "DAHDIChannel");
13454 
13455    if (ast_strlen_zero(channel)) {
13456       astman_send_error(s, m, "No channel specified");
13457       return 0;
13458    }
13459    p = find_channel(atoi(channel));
13460    if (!p) {
13461       astman_send_error(s, m, "No such channel");
13462       return 0;
13463    }
13464    dahdi_fake_event(p,TRANSFER);
13465    astman_send_ack(s, m, "DAHDITransfer");
13466    return 0;
13467 }

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

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

13470 {
13471    struct dahdi_pvt *p = NULL;
13472    const char *channel = astman_get_header(m, "DAHDIChannel");
13473 
13474    if (ast_strlen_zero(channel)) {
13475       astman_send_error(s, m, "No channel specified");
13476       return 0;
13477    }
13478    p = find_channel(atoi(channel));
13479    if (!p) {
13480       astman_send_error(s, m, "No such channel");
13481       return 0;
13482    }
13483    dahdi_fake_event(p,HANGUP);
13484    astman_send_ack(s, m, "DAHDIHangup");
13485    return 0;
13486 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 1726 of file chan_dahdi.c.

References alarm, alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

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

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

Definition at line 1522 of file chan_dahdi.c.

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

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

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

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

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

10886 {
10887    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
10888       snprintf(buf, size, "%s", number);
10889       return;
10890    }
10891    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
10892       if (size) {
10893          *buf = '\0';
10894       }
10895       return;
10896    }
10897    switch (plan) {
10898    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
10899       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
10900       break;
10901    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
10902       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
10903       break;
10904    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
10905       snprintf(buf, size, "%s%s", pri->localprefix, number);
10906       break;
10907    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
10908       snprintf(buf, size, "%s%s", pri->privateprefix, number);
10909       break;
10910    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
10911       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
10912       break;
10913    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
10914       snprintf(buf, size, "%s", number);
10915       break;
10916    }
10917 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

14152 {
14153    char *c, *chan;
14154    int x, start, finish;
14155    struct dahdi_pvt *tmp;
14156 #ifdef HAVE_PRI
14157    struct dahdi_pri *pri;
14158    int trunkgroup, y;
14159 #endif
14160    
14161    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
14162       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
14163       return -1;
14164    }
14165 
14166    c = ast_strdupa(value);
14167 
14168 #ifdef HAVE_PRI
14169    pri = NULL;
14170    if (iscrv) {
14171       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
14172          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
14173          return -1;
14174       }
14175       if (trunkgroup < 1) {
14176          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
14177          return -1;
14178       }
14179       c += y;
14180       for (y = 0; y < NUM_SPANS; y++) {
14181          if (pris[y].trunkgroup == trunkgroup) {
14182             pri = pris + y;
14183             break;
14184          }
14185       }
14186       if (!pri) {
14187          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
14188          return -1;
14189       }
14190    }
14191 #endif         
14192 
14193    while ((chan = strsep(&c, ","))) {
14194       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
14195          /* Range */
14196       } else if (sscanf(chan, "%30d", &start)) {
14197          /* Just one */
14198          finish = start;
14199       } else if (!strcasecmp(chan, "pseudo")) {
14200          finish = start = CHAN_PSEUDO;
14201          if (found_pseudo)
14202             *found_pseudo = 1;
14203       } else {
14204          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
14205          return -1;
14206       }
14207       if (finish < start) {
14208          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
14209          x = finish;
14210          finish = start;
14211          start = x;
14212       }
14213 
14214       for (x = start; x <= finish; x++) {
14215 #ifdef HAVE_PRI
14216          tmp = mkintf(x, conf, pri, reload);
14217 #else       
14218          tmp = mkintf(x, conf, NULL, reload);
14219 #endif         
14220 
14221          if (tmp) {
14222 #ifdef HAVE_PRI
14223                if (pri)
14224                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
14225                else
14226 #endif
14227                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
14228          } else {
14229             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
14230                (reload == 1) ? "reconfigure" : "register", value);
14231             return -1;
14232          }
14233       }
14234    }
14235 
14236    return 0;
14237 }

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

Definition at line 12336 of file chan_dahdi.c.

References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

12337 {
12338    if (!s || len < 1) {
12339       return;
12340    }
12341    s[0] = '\0';
12342    if (status & DCHAN_PROVISIONED)
12343       strncat(s, "Provisioned, ", len - strlen(s) - 1);
12344    if (!(status & DCHAN_NOTINALARM))
12345       strncat(s, "In Alarm, ", len - strlen(s) - 1);
12346    if (status & DCHAN_UP)
12347       strncat(s, "Up", len - strlen(s) - 1);
12348    else
12349       strncat(s, "Down", len - strlen(s) - 1);
12350    if (active)
12351       strncat(s, ", Active", len - strlen(s) - 1);
12352    else
12353       strncat(s, ", Standby", len - strlen(s) - 1);
12354    s[len - 1] = '\0';
12355 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

Definition at line 2181 of file chan_dahdi.c.

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

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

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

Definition at line 7793 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

07794 {
07795    int x;
07796    int sum = 0;
07797 
07798    if (!len)
07799       return 0;
07800 
07801    for (x = 0; x < len; x++)
07802       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
07803 
07804    return sum / len;
07805 }

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

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

09434 {
09435    struct dahdi_pvt *p;
09436    struct dahdi_bufferinfo bi;
09437    int res;
09438    
09439    if ((p = ast_malloc(sizeof(*p)))) {
09440       memcpy(p, src, sizeof(struct dahdi_pvt));
09441       ast_mutex_init(&p->lock);
09442       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
09443       /* Allocate a dahdi structure */
09444       if (p->subs[SUB_REAL].dfd < 0) {
09445          ast_log(LOG_ERROR, "Unable to dup channel: %s\n",  strerror(errno));
09446          destroy_dahdi_pvt(&p);
09447          return NULL;
09448       }
09449       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
09450       if (!res) {
09451          bi.txbufpolicy = src->buf_policy;
09452          bi.rxbufpolicy = src->buf_policy;
09453          bi.numbufs = src->buf_no;
09454          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
09455          if (res < 0) {
09456             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
09457          }
09458       } else
09459          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
09460    }
09461    p->destroy = 1;
09462    p->next = iflist;
09463    p->prev = NULL;
09464    iflist = p;
09465    if (iflist->next)
09466       iflist->next->prev = p;
09467    return p;
09468 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

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

static unsigned char cid_pres2ss7pres ( int  cid_pres  )  [static]

Definition at line 2433 of file chan_dahdi.c.

Referenced by dahdi_call().

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

static unsigned char cid_pres2ss7screen ( int  cid_pres  )  [static]

Definition at line 2438 of file chan_dahdi.c.

Referenced by dahdi_call().

02439 {
02440    return cid_pres & 0x03;
02441 }

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

Definition at line 12161 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

12162 {
12163    return complete_span_helper(line,word,pos,state,3);
12164 }

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

Definition at line 12166 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_no_debug(), and handle_pri_really_debug().

12167 {
12168    return complete_span_helper(line,word,pos,state,4);
12169 }

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

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

12143 {
12144    int which, span;
12145    char *ret = NULL;
12146 
12147    if (pos != rpos)
12148       return ret;
12149 
12150    for (which = span = 0; span < NUM_SPANS; span++) {
12151       if (pris[span].pri && ++which > state) {
12152          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
12153             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
12154          }
12155          break;
12156       }
12157    }
12158    return ret;
12159 }

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

Definition at line 1823 of file chan_dahdi.c.

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

Referenced by update_conf().

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

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

Definition at line 1872 of file chan_dahdi.c.

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

Referenced by dahdi_unlink(), and update_conf().

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

static int dahdi_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

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

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

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

static void dahdi_close ( int  fd  )  [static]

Definition at line 1484 of file chan_dahdi.c.

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

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

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

Definition at line 1497 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

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

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

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

Definition at line 1505 of file chan_dahdi.c.

References dahdi_close(), and dahdi_ss7::fds.

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

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

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

Definition at line 1490 of file chan_dahdi.c.

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

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

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

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

Definition at line 2225 of file chan_dahdi.c.

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

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

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

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

12514 {
12515    int channel;
12516    int ret;
12517    switch (cmd) {
12518    case CLI_INIT:
12519       e->command = "dahdi destroy channel";
12520       e->usage = 
12521          "Usage: dahdi destroy channel <chan num>\n"
12522          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
12523       return NULL;
12524    case CLI_GENERATE:
12525       return NULL;   
12526    }
12527    if (a->argc != 4)
12528       return CLI_SHOWUSAGE;
12529    
12530    channel = atoi(a->argv[3]);
12531    ret = dahdi_destroy_channel_bynum(channel);
12532    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
12533 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

08104 {
08105    struct dahdi_pvt *tmp = NULL;
08106    struct dahdi_pvt *prev = NULL;
08107 
08108    tmp = iflist;
08109    while (tmp) {
08110       if (tmp->channel == channel) {
08111          int x = DAHDI_FLASH;
08112          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 */
08113          destroy_channel(prev, tmp, 1);
08114          ast_module_unref(ast_module_info->self);
08115          return RESULT_SUCCESS;
08116       }
08117       prev = tmp;
08118       tmp = tmp->next;
08119    }
08120    return RESULT_FAILURE;
08121 }

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

Definition at line 1592 of file chan_dahdi.c.

References ast_channel::_state, ast_debug, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DIALING, dahdi_pvt::begindigit, dahdi_pvt::call, 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.

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

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

Definition at line 1654 of file chan_dahdi.c.

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

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

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2054 of file chan_dahdi.c.

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

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

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

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

Parameters:
dahdichan "Physical" DAHDI channel (e.g: DAHDI/5)
on 1 to enable, 0 to disable

chan_dahdi has a DND (Do Not Disturb) mode for each dahdichan (physical DAHDI channel). Use this to enable or disable it.

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

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

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

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2005 of file chan_dahdi.c.

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

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

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

Definition at line 5659 of file chan_dahdi.c.

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

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

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

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

13385 {
13386    if (p) {
13387       switch (mode) {
13388          case TRANSFER:
13389             p->fake_event = DAHDI_EVENT_WINKFLASH;
13390             break;
13391          case HANGUP:
13392             p->fake_event = DAHDI_EVENT_ONHOOK;
13393             break;
13394          default:
13395             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);   
13396       }
13397    }
13398    return 0;
13399 }

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

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

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

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

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

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

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 304 of file chan_dahdi.c.

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

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

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

Definition at line 1298 of file chan_dahdi.c.

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

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

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

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

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

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

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

static int dahdi_hangup ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

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

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

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

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

09849 {
09850    if (p->loopedback != enable) {
09851       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
09852          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
09853          return;
09854       }
09855       p->loopedback = enable;
09856    }
09857 }

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

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

static int dahdi_open ( char *  fn  )  [static]

Definition at line 1437 of file chan_dahdi.c.

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

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

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

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

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

10788 {
10789    int x, y;
10790    int dchan = -1, span = -1;
10791    int dchancount = 0;
10792 
10793    if (pri) {
10794       for (x = 0; x < NUM_SPANS; x++) {
10795          for (y = 0; y < NUM_DCHANS; y++) {
10796             if (pris[x].dchans[y])
10797                dchancount++;
10798 
10799             if (pris[x].dchans[y] == pri)
10800                dchan = y;
10801          }
10802          if (dchan >= 0) {
10803             span = x;
10804             break;
10805          }
10806          dchancount = 0;
10807       }
10808       if ((dchancount > 1) && (span > -1))
10809          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
10810       else
10811          ast_log(LOG_ERROR, "%s", s);
10812    } else
10813       ast_log(LOG_ERROR, "%s", s);
10814 
10815    ast_mutex_lock(&pridebugfdlock);
10816 
10817    if (pridebugfd >= 0) {
10818       if (write(pridebugfd, s, strlen(s)) < 0) {
10819          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
10820       }
10821    }
10822 
10823    ast_mutex_unlock(&pridebugfdlock);
10824 }

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

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

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

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

Definition at line 1343 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_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().

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

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

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

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

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

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

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

static int dahdi_restart ( void   )  [static]

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

12565 {
12566 #if defined(HAVE_PRI) || defined(HAVE_SS7)
12567    int i, j;
12568 #endif
12569    int cancel_code;
12570    struct dahdi_pvt *p;
12571 
12572    ast_mutex_lock(&restart_lock);
12573 
12574    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
12575    dahdi_softhangup_all();
12576    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
12577 
12578 #if defined(HAVE_PRI)
12579    for (i = 0; i < NUM_SPANS; i++) {
12580       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
12581          cancel_code = pthread_cancel(pris[i].master);
12582          pthread_kill(pris[i].master, SIGURG);
12583          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
12584          pthread_join(pris[i].master, NULL);
12585          ast_debug(4, "Joined thread of span %d\n", i);
12586       }
12587    }
12588 #endif
12589 
12590 #if defined(HAVE_SS7)
12591    for (i = 0; i < NUM_SPANS; i++) {
12592       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
12593          cancel_code = pthread_cancel(linksets[i].master);
12594          pthread_kill(linksets[i].master, SIGURG);
12595          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
12596          pthread_join(linksets[i].master, NULL);
12597          ast_debug(4, "Joined thread of span %d\n", i);
12598       }
12599     }
12600 #endif
12601 
12602    ast_mutex_lock(&monlock);
12603    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
12604       cancel_code = pthread_cancel(monitor_thread);
12605       pthread_kill(monitor_thread, SIGURG);
12606       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
12607       pthread_join(monitor_thread, NULL);
12608       ast_debug(4, "Joined monitor thread\n");
12609    }
12610    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
12611 
12612    ast_mutex_lock(&mwi_thread_lock);
12613    while (mwi_thread_count > 0) {
12614       ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
12615       ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
12616    }
12617    ast_mutex_unlock(&mwi_thread_lock);
12618    ast_mutex_lock(&ss_thread_lock);
12619    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
12620       int x = DAHDI_FLASH;
12621       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
12622 
12623       for (p = iflist; p; p = p->next) {
12624          if (p->owner)
12625             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 */      
12626          }
12627          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
12628       }
12629 
12630    /* ensure any created channels before monitor threads were stopped are hungup */
12631    dahdi_softhangup_all();
12632    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
12633    destroy_all_channels();
12634    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
12635 
12636    ast_mutex_unlock(&monlock);
12637 
12638 #ifdef HAVE_PRI
12639    for (i = 0; i < NUM_SPANS; i++) {
12640       for (j = 0; j < NUM_DCHANS; j++)
12641          dahdi_close_pri_fd(&(pris[i]), j);
12642    }
12643 
12644    memset(pris, 0, sizeof(pris));
12645    for (i = 0; i < NUM_SPANS; i++) {
12646       ast_mutex_init(&pris[i].lock);
12647       pris[i].offset = -1;
12648       pris[i].master = AST_PTHREADT_NULL;
12649       for (j = 0; j < NUM_DCHANS; j++)
12650          pris[i].fds[j] = -1;
12651       }
12652    pri_set_error(dahdi_pri_error);
12653    pri_set_message(dahdi_pri_message);
12654 #endif
12655 #ifdef HAVE_SS7
12656    for (i = 0; i < NUM_SPANS; i++) {
12657       for (j = 0; j < NUM_DCHANS; j++)
12658          dahdi_close_ss7_fd(&(linksets[i]), j);
12659    }
12660 
12661    memset(linksets, 0, sizeof(linksets));
12662    for (i = 0; i < NUM_SPANS; i++) {
12663       ast_mutex_init(&linksets[i].lock);
12664       linksets[i].master = AST_PTHREADT_NULL;
12665       for (j = 0; j < NUM_DCHANS; j++)
12666          linksets[i].fds[j] = -1;
12667    }
12668    ss7_set_error(dahdi_ss7_error);
12669    ss7_set_message(dahdi_ss7_message);
12670 #endif
12671 
12672    if (setup_dahdi(2) != 0) {
12673       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
12674       ast_mutex_unlock(&ss_thread_lock);
12675       return 1;
12676    }
12677    ast_mutex_unlock(&ss_thread_lock);
12678    ast_mutex_unlock(&restart_lock);
12679    return 0;
12680 }

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

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

12683 {
12684    switch (cmd) {
12685    case CLI_INIT:
12686       e->command = "dahdi restart";
12687       e->usage = 
12688          "Usage: dahdi restart\n"
12689          "  Restarts the DAHDI channels: destroys them all and then\n"
12690          "  re-reads them from chan_dahdi.conf.\n"
12691          "  Note that this will STOP any running CALL on DAHDI channels.\n"
12692          "";
12693       return NULL;
12694    case CLI_GENERATE:
12695       return NULL;
12696    }
12697    if (a->argc != 2)
12698       return CLI_SHOWUSAGE;
12699 
12700    if (dahdi_restart() != 0)
12701       return CLI_FAILURE;
12702    return CLI_SUCCESS;
12703 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

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

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

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

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

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

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

15414 {
15415 #define  END_SILENCE_LEN 400
15416 #define  HEADER_MS 50
15417 #define  TRAILER_MS 5
15418 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
15419 #define  ASCII_BYTES_PER_CHAR 80
15420 
15421    unsigned char *buf,*mybuf;
15422    struct dahdi_pvt *p = c->tech_pvt;
15423    struct pollfd fds[1];
15424    int size,res,fd,len,x;
15425    int bytes=0;
15426    /* Initial carrier (imaginary) */
15427    float cr = 1.0;
15428    float ci = 0.0;
15429    float scont = 0.0;
15430    int idx;
15431 
15432    idx = dahdi_get_index(c, p, 0);
15433    if (idx < 0) {
15434       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
15435       return -1;
15436    }
15437    if (!text[0]) return(0); /* if nothing to send, dont */
15438    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
15439    if (p->mate) 
15440       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
15441    else
15442       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
15443    if (!buf)
15444       return -1;
15445    mybuf = buf;
15446    if (p->mate) {
15447       int codec = AST_LAW(p);
15448       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
15449          PUT_CLID_MARKMS;
15450       }
15451       /* Put actual message */
15452       for (x = 0; text[x]; x++) {
15453          PUT_CLID(text[x]);
15454       }
15455       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
15456          PUT_CLID_MARKMS;
15457       }
15458       len = bytes;
15459       buf = mybuf;
15460    } else {
15461       len = tdd_generate(p->tdd, buf, text);
15462       if (len < 1) {
15463          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
15464          ast_free(mybuf);
15465          return -1;
15466       }
15467    }
15468    memset(buf + len, 0x7f, END_SILENCE_LEN);
15469    len += END_SILENCE_LEN;
15470    fd = p->subs[idx].dfd;
15471    while (len) {
15472       if (ast_check_hangup(c)) {
15473          ast_free(mybuf);
15474          return -1;
15475       }
15476       size = len;
15477       if (size > READ_SIZE)
15478          size = READ_SIZE;
15479       fds[0].fd = fd;
15480       fds[0].events = POLLOUT | POLLPRI;
15481       fds[0].revents = 0;
15482       res = poll(fds, 1, -1);
15483       if (!res) {
15484          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
15485          continue;
15486       }
15487         /* if got exception */
15488       if (fds[0].revents & POLLPRI) {
15489          ast_free(mybuf);
15490          return -1;
15491       }
15492       if (!(fds[0].revents & POLLOUT)) {
15493          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
15494          continue;
15495       }
15496       res = write(fd, buf, size);
15497       if (res != size) {
15498          if (res == -1) {
15499             ast_free(mybuf);
15500             return -1;
15501          }
15502          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
15503          break;
15504       }
15505       len -= size;
15506       buf += size;
15507    }
15508    ast_free(mybuf);
15509    return(0);
15510 }

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

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

13312 {
13313    int channel;
13314    int on;
13315    struct dahdi_pvt *dahdi_chan = NULL;
13316 
13317    switch (cmd) {
13318    case CLI_INIT:
13319       e->command = "dahdi set dnd";
13320       e->usage = 
13321          "Usage: dahdi set dnd <chan#> <on|off>\n"
13322          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
13323          "  Changes take effect immediately.\n"
13324          "  <chan num> is the channel number\n"
13325          "  <on|off> Enable or disable DND mode?\n"
13326          ;
13327       return NULL;
13328    case CLI_GENERATE:
13329       return NULL;   
13330    }
13331 
13332    if (a->argc != 5)
13333       return CLI_SHOWUSAGE;
13334 
13335    if ((channel = atoi(a->argv[3])) <= 0) {
13336       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
13337       return CLI_SHOWUSAGE;
13338    }
13339    
13340    if (ast_true(a->argv[4]))
13341       on = 1;
13342    else if (ast_false(a->argv[4]))
13343       on = 0;
13344    else {
13345       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
13346       return CLI_SHOWUSAGE;
13347    }
13348 
13349    ast_mutex_lock(&iflock);
13350    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
13351       if (dahdi_chan->channel != channel)
13352          continue;
13353 
13354       /* Found the channel. Actually set it */
13355       dahdi_dnd(dahdi_chan, on);
13356       break;
13357    }
13358    ast_mutex_unlock(&iflock);
13359 
13360    if (!dahdi_chan) {
13361       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13362       return CLI_FAILURE;
13363    }
13364 
13365    return CLI_SUCCESS;
13366 }

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

Definition at line 2208 of file chan_dahdi.c.

References ast_log(), errno, and LOG_WARNING.

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

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

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

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

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

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

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

13238 {
13239    int channel;
13240    float gain;
13241    int tx;
13242    int res;
13243    ast_mutex_t *lock;
13244    struct dahdi_pvt *tmp = NULL;
13245 
13246    switch (cmd) {
13247    case CLI_INIT:
13248       e->command = "dahdi set swgain";
13249       e->usage = 
13250          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
13251          "  Sets the software gain on a a given channel, overriding the\n"
13252          "   value provided at module loadtime, whether the channel is in\n"
13253          "   use or not.  Changes take effect immediately.\n"
13254          "   <rx|tx> which direction do you want to change (relative to our module)\n"
13255          "   <chan num> is the channel number relative to the device\n"
13256          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
13257       return NULL;
13258    case CLI_GENERATE:
13259       return NULL;   
13260    }
13261 
13262    lock = &iflock;
13263 
13264    if (a->argc != 6)
13265       return CLI_SHOWUSAGE;
13266    
13267    if (!strcasecmp("rx", a->argv[3]))
13268       tx = 0; /* rx */
13269    else if (!strcasecmp("tx", a->argv[3]))
13270       tx = 1; /* tx */
13271    else
13272       return CLI_SHOWUSAGE;
13273 
13274    channel = atoi(a->argv[4]);
13275    gain = atof(a->argv[5]);
13276 
13277    ast_mutex_lock(lock);
13278    for (tmp = iflist; tmp; tmp = tmp->next) {
13279 
13280       if (tmp->channel != channel)
13281          continue;
13282 
13283       if (tmp->subs[SUB_REAL].dfd == -1)
13284          break;
13285 
13286       if (tx)
13287          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13288       else
13289          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
13290 
13291       if (res) {
13292          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
13293          ast_mutex_unlock(lock);
13294          return CLI_FAILURE;
13295       }
13296 
13297       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
13298          tx ? "tx" : "rx", gain, channel);
13299       break;
13300    }
13301    ast_mutex_unlock(lock);
13302 
13303    if (tmp)
13304       return CLI_SUCCESS;
13305 
13306    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
13307    return CLI_FAILURE;
13308 
13309 }

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

Definition at line 9742 of file chan_dahdi.c.

Referenced by pri_dchannel(), and ss7_start_call().

09743 {
09744    return ioctl(dfd, DAHDI_SETLAW, &law);
09745 }

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

Definition at line 1512 of file chan_dahdi.c.

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

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

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

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

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

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

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

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

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

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

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

12716 {
12717 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12718 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
12719    unsigned int targetnum = 0;
12720    int filtertype = 0;
12721    struct dahdi_pvt *tmp = NULL;
12722    char tmps[20] = "";
12723    char statestr[20] = "";
12724    char blockstr[20] = "";
12725    ast_mutex_t *lock;
12726    struct dahdi_pvt *start;
12727 #ifdef HAVE_PRI
12728    int trunkgroup;
12729    struct dahdi_pri *pri = NULL;
12730    int x;
12731 #endif
12732    switch (cmd) {
12733    case CLI_INIT:
12734       e->command = "dahdi show channels [trunkgroup|group|context]";
12735       e->usage = 
12736          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
12737          "  Shows a list of available channels with optional filtering\n"
12738          "  <group> must be a number between 0 and 63\n";
12739       return NULL;
12740    case CLI_GENERATE:
12741       return NULL;   
12742    }
12743 
12744    lock = &iflock;
12745    start = iflist;
12746 
12747    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
12748 
12749    if (!((a->argc == 3) || (a->argc == 5)))
12750       return CLI_SHOWUSAGE;
12751 
12752    if (a->argc == 5) {
12753 #ifdef HAVE_PRI
12754       if (!strcasecmp(a->argv[3], "trunkgroup")) {
12755          /* this option requires no special handling, so leave filtertype to zero */
12756          if ((trunkgroup = atoi(a->argv[4])) < 1)
12757             return CLI_SHOWUSAGE;
12758          for (x = 0; x < NUM_SPANS; x++) {
12759             if (pris[x].trunkgroup == trunkgroup) {
12760                pri = pris + x;
12761                break;
12762             }
12763          }
12764          if (pri) {
12765             start = pri->crvs;
12766             lock = &pri->lock;
12767          } else {
12768             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
12769             return CLI_FAILURE;
12770          }
12771       } else
12772 #endif   
12773       if (!strcasecmp(a->argv[3], "group")) {
12774          targetnum = atoi(a->argv[4]);
12775          if ((targetnum < 0) || (targetnum > 63))
12776             return CLI_SHOWUSAGE;
12777          targetnum = 1 << targetnum;
12778          filtertype = 1;
12779       } else if (!strcasecmp(a->argv[3], "context")) {
12780          filtertype = 2;
12781       }
12782    }
12783 
12784    ast_mutex_lock(lock);
12785 #ifdef HAVE_PRI
12786    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12787 #else
12788    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
12789 #endif   
12790    
12791    tmp = start;
12792    while (tmp) {
12793       if (filtertype) {
12794          switch(filtertype) {
12795          case 1: /* dahdi show channels group <group> */
12796             if (!(tmp->group & targetnum)) {
12797                tmp = tmp->next;
12798                continue;
12799             }
12800             break;
12801          case 2: /* dahdi show channels context <context> */
12802             if (strcasecmp(tmp->context, a->argv[4])) {
12803                tmp = tmp->next;
12804                continue;
12805             }
12806             break;
12807          default:
12808             ;
12809          }
12810       }
12811       if (tmp->channel > 0) {
12812          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
12813       } else
12814          ast_copy_string(tmps, "pseudo", sizeof(tmps));
12815 
12816       if (tmp->locallyblocked)
12817          blockstr[0] = 'L';
12818       else
12819          blockstr[0] = ' ';
12820 
12821       if (tmp->remotelyblocked)
12822          blockstr[1] = 'R';
12823       else
12824          blockstr[1] = ' ';
12825 
12826       blockstr[2] = '\0';
12827 
12828       snprintf(statestr, sizeof(statestr), "%s", "In Service");
12829 
12830       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
12831       tmp = tmp->next;
12832    }
12833    ast_mutex_unlock(lock);
12834    return CLI_SUCCESS;
12835 #undef FORMAT
12836 #undef FORMAT2
12837 }

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

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

13054 {
13055    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
13056    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
13057    int span;
13058    int res;
13059    char alarmstr[50];
13060 
13061    int ctl;
13062    struct dahdi_spaninfo s;
13063 
13064    switch (cmd) {
13065    case CLI_INIT:
13066       e->command = "dahdi show status";
13067       e->usage = 
13068          "Usage: dahdi show status\n"
13069          "       Shows a list of DAHDI cards with status\n";
13070       return NULL;
13071    case CLI_GENERATE:
13072       return NULL;   
13073    }
13074    ctl = open("/dev/dahdi/ctl", O_RDWR);
13075    if (ctl < 0) {
13076       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
13077       return CLI_FAILURE;
13078    }
13079    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
13080 
13081    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
13082       s.spanno = span;
13083       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
13084       if (res) {
13085          continue;
13086       }
13087       alarmstr[0] = '\0';
13088       if (s.alarms > 0) {
13089          if (s.alarms & DAHDI_ALARM_BLUE)
13090             strcat(alarmstr, "BLU/");
13091          if (s.alarms & DAHDI_ALARM_YELLOW)
13092             strcat(alarmstr, "YEL/");
13093          if (s.alarms & DAHDI_ALARM_RED)
13094             strcat(alarmstr, "RED/");
13095          if (s.alarms & DAHDI_ALARM_LOOPBACK)
13096             strcat(alarmstr, "LB/");
13097          if (s.alarms & DAHDI_ALARM_RECOVER)
13098             strcat(alarmstr, "REC/");
13099          if (s.alarms & DAHDI_ALARM_NOTOPEN)
13100             strcat(alarmstr, "NOP/");
13101          if (!strlen(alarmstr))
13102             strcat(alarmstr, "UUU/");
13103          if (strlen(alarmstr)) {
13104             /* Strip trailing / */
13105             alarmstr[strlen(alarmstr) - 1] = '\0';
13106          }
13107       } else {
13108          if (s.numchans)
13109             strcpy(alarmstr, "OK");
13110          else
13111             strcpy(alarmstr, "UNCONFIGURED");
13112       }
13113 
13114       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count
13115             , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
13116               s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
13117               s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
13118               "CAS"
13119             , s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
13120               s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
13121               s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
13122               "Unk"
13123             , s.lineconfig & DAHDI_CONFIG_CRC4 ?
13124               s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
13125             , lbostr[s.lbo]
13126          );
13127    }
13128    close(ctl);
13129 
13130    return CLI_SUCCESS;
13131 #undef FORMAT
13132 #undef FORMAT2
13133 }

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

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

13136 {
13137    int pseudo_fd = -1;
13138    struct dahdi_versioninfo vi;
13139 
13140    switch (cmd) {
13141    case CLI_INIT:
13142       e->command = "dahdi show version";
13143       e->usage = 
13144          "Usage: dahdi show version\n"
13145          "       Shows the DAHDI version in use\n";
13146       return NULL;
13147    case CLI_GENERATE:
13148       return NULL;
13149    }
13150    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
13151       ast_cli(a->fd, "Failed to open control file to get version.\n");
13152       return CLI_SUCCESS;
13153    }
13154 
13155    strcpy(vi.version, "Unknown");
13156    strcpy(vi.echo_canceller, "Unknown");
13157 
13158    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
13159       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
13160    else
13161       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
13162 
13163    close(pseudo_fd);
13164 
13165    return CLI_SUCCESS;
13166 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 1755 of file chan_dahdi.c.

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

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

static void dahdi_softhangup_all ( void   )  [static]

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

12536 {
12537    struct dahdi_pvt *p;
12538 retry:
12539    ast_mutex_lock(&iflock);
12540     for (p = iflist; p; p = p->next) {
12541       ast_mutex_lock(&p->lock);
12542         if (p->owner && !p->restartpending) {
12543          if (ast_channel_trylock(p->owner)) {
12544             if (option_debug > 2)
12545                ast_verbose("Avoiding deadlock\n");
12546             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
12547             ast_mutex_unlock(&p->lock);
12548             ast_mutex_unlock(&iflock);
12549             goto retry;
12550          }
12551          if (option_debug > 2)
12552             ast_verbose("Softhanging up on %s\n", p->owner->name);
12553          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
12554          p->restartpending = 1;
12555          num_restart_pending++;
12556          ast_channel_unlock(p->owner);
12557       }
12558       ast_mutex_unlock(&p->lock);
12559     }
12560    ast_mutex_unlock(&iflock);
12561 }

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

Definition at line 10556 of file chan_dahdi.c.

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

Referenced by dahdi_restart(), and load_module().

10557 {
10558 #if 0
10559    int i;
10560 
10561    for (i = 0; i < NUM_SPANS; i++)
10562       if (linksets[i].ss7 == ss7)
10563          break;
10564 
10565 #else
10566    ast_log(LOG_ERROR, "%s", s);
10567 #endif
10568 }

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

Definition at line 10541 of file chan_dahdi.c.

References ast_verbose, linksets, and NUM_SPANS.

Referenced by dahdi_restart(), and load_module().

10542 {
10543 #if 0
10544    int i;
10545 
10546    for (i = 0; i < NUM_SPANS; i++)
10547       if (linksets[i].ss7 == ss7)
10548          break;
10549 
10550    ast_verbose("[%d] %s", i+1, s);
10551 #else
10552    ast_verbose("%s", s);
10553 #endif
10554 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

Definition at line 2037 of file chan_dahdi.c.

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

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

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

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

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

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 313 of file chan_dahdi.c.

Referenced by ss_thread().

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

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

Definition at line 6514 of file chan_dahdi.c.

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

Referenced by ss_thread().

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

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

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

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

static void destroy_all_channels ( void   )  [static]

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

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

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

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

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

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

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

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

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 1746 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

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

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 1576 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

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

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

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

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

10698 {
10699    struct ast_channel *chan = vchan;
10700    struct dahdi_pvt *pvt = chan->tech_pvt;
10701    struct ast_frame *f;
10702    char ex[80];
10703    /* Wait up to 30 seconds for an answer */
10704    int newms, ms = 30000;
10705    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
10706    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
10707    if (ast_call(chan, ex, 0)) {
10708       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
10709       ast_hangup(chan);
10710       return NULL;
10711    }
10712    while ((newms = ast_waitfor(chan, ms)) > 0) {
10713       f = ast_read(chan);
10714       if (!f) {
10715          /* Got hangup */
10716          break;
10717       }
10718       if (f->frametype == AST_FRAME_CONTROL) {
10719          switch (f->subclass) {
10720          case AST_CONTROL_ANSWER:
10721             /* Launch the PBX */
10722             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
10723             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
10724             chan->priority = 1;
10725             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
10726             ast_pbx_run(chan);
10727             /* It's already hungup, return immediately */
10728             return NULL;
10729          case AST_CONTROL_BUSY:
10730             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
10731             break;
10732          case AST_CONTROL_CONGESTION:
10733             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
10734             break;
10735          };
10736       }
10737       ast_frfree(f);
10738       ms = newms;
10739    }
10740    /* Hangup the channel since nothing happend */
10741    ast_hangup(chan);
10742    return NULL;
10743 }

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

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

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

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

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

static char* event2str ( int  event  )  [static]

Definition at line 1736 of file chan_dahdi.c.

References ARRAY_LEN, and buf.

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

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

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

Definition at line 2106 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

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

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

Definition at line 2072 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

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

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

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

13401 {
13402    struct dahdi_pvt *p = iflist;
13403    while (p) {
13404       if (p->channel == channel) {
13405          break;
13406       }
13407       p = p->next;
13408    }
13409    return p;
13410 }

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

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

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

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

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

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

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

13017 {
13018    int i, j;
13019    switch (cmd) {
13020    case CLI_INIT:
13021       e->command = "dahdi show cadences";
13022       e->usage = 
13023          "Usage: dahdi show cadences\n"
13024          "       Shows all cadences currently defined\n";
13025       return NULL;
13026    case CLI_GENERATE:
13027       return NULL;   
13028    }
13029    for (i = 0; i < num_cadence; i++) {
13030       char output[1024];
13031       char tmp[16], tmp2[64];
13032       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
13033       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
13034 
13035       for (j = 0; j < 16; j++) {
13036          if (cadences[i].ringcadence[j] == 0)
13037             break;
13038          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
13039          if (cidrings[i] * 2 - 1 == j)
13040             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
13041          else
13042             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
13043          if (j != 0)
13044             strncat(output, ",", sizeof(output) - strlen(output) - 1);
13045          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
13046       }
13047       ast_cli(a->fd,"%s\n",output);
13048    }
13049    return CLI_SUCCESS;
13050 }

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

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

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

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

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

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

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

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

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

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

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

12301 {
12302    int span;
12303    int x;
12304    switch (cmd) {
12305    case CLI_INIT:
12306       e->command = "pri intensive debug span";
12307       e->usage = 
12308          "Usage: pri intensive debug span <span>\n"
12309          "       Enables debugging down to the Q.921 level\n";
12310       return NULL;
12311    case CLI_GENERATE:
12312       return complete_span_5(a->line, a->word, a->pos, a->n);
12313    }
12314 
12315    if (a->argc < 5)
12316       return CLI_SHOWUSAGE;
12317    span = atoi(a->argv[4]);
12318    if ((span < 1) || (span > NUM_SPANS)) {
12319       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
12320       return CLI_SUCCESS;
12321    }
12322    if (!pris[span-1].pri) {
12323       ast_cli(a->fd, "No PRI running on span %d\n", span);
12324       return CLI_SUCCESS;
12325    }
12326    for (x = 0; x < NUM_DCHANS; x++) {
12327       if (pris[span-1].dchans[x])
12328          pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
12329                                                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
12330                                                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
12331    }
12332    ast_cli(a->fd, "Enabled EXTENSIVE debugging on span %d\n", span);
12333    return CLI_SUCCESS;
12334 }

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

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

12193 {
12194    int myfd;
12195    switch (cmd) {
12196    case CLI_INIT:
12197       e->command = "pri set debug file";
12198       e->usage = "Usage: pri set debug file [output-file]\n"
12199             "       Sends PRI debug output to the specified output file\n";
12200       return NULL;
12201    case CLI_GENERATE:
12202       return NULL;   
12203    }
12204    if (a->argc < 5)
12205       return CLI_SHOWUSAGE;
12206 
12207    if (ast_strlen_zero(a->argv[4]))
12208       return CLI_SHOWUSAGE;
12209 
12210    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
12211    if (myfd < 0) {
12212       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
12213       return CLI_SUCCESS;
12214    }
12215 
12216    ast_mutex_lock(&pridebugfdlock);
12217 
12218    if (pridebugfd >= 0)
12219       close(pridebugfd);
12220 
12221    pridebugfd = myfd;
12222    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
12223    ast_mutex_unlock(&pridebugfdlock);
12224    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
12225    return CLI_SUCCESS;
12226 }

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

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

12441 {
12442    int x;
12443    int span;
12444    int count=0;
12445    int debug=0;
12446 
12447    switch (cmd) {
12448    case CLI_INIT: 
12449       e->command = "pri show debug";
12450       e->usage = 
12451          "Usage: pri show debug\n"
12452          "  Show the debug state of pri spans\n";
12453       return NULL;
12454    case CLI_GENERATE:
12455       return NULL;   
12456    }
12457 
12458    for (span = 0; span < NUM_SPANS; span++) {
12459            if (pris[span].pri) {
12460          for (x = 0; x < NUM_DCHANS; x++) {
12461             debug = 0;
12462                if (pris[span].dchans[x]) {
12463                   debug = pri_get_debug(pris[span].dchans[x]);
12464                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" );
12465                count++;
12466             }
12467          }
12468       }
12469 
12470    }
12471    ast_mutex_lock(&pridebugfdlock);
12472    if (pridebugfd >= 0) 
12473       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
12474    ast_mutex_unlock(&pridebugfdlock);
12475        
12476    if (!count) 
12477       ast_cli(a->fd, "No debug set or no PRI running\n");
12478    return CLI_SUCCESS;
12479 }

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

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

12391 {
12392    int span;
12393    int x;
12394    char status[256];
12395    switch (cmd) {
12396    case CLI_INIT: 
12397       e->command = "pri show span";
12398       e->usage = 
12399          "Usage: pri show span <span>\n"
12400          "       Displays PRI Information on a given PRI span\n";
12401       return NULL;
12402    case CLI_GENERATE:
12403       return complete_span_4(a->line, a->word, a->pos, a->n);
12404    }
12405 
12406    if (a->argc < 4)
12407       return CLI_SHOWUSAGE;
12408    span = atoi(a->argv[3]);
12409    if ((span < 1) || (span > NUM_SPANS)) {
12410       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
12411       return CLI_SUCCESS;
12412    }
12413    if (!pris[span-1].pri) {
12414       ast_cli(a->fd, "No PRI running on span %d\n", span);
12415       return CLI_SUCCESS;
12416    }
12417    for (x = 0; x < NUM_DCHANS; x++) {
12418       if (pris[span-1].dchannels[x]) {
12419 #ifdef PRI_DUMP_INFO_STR
12420          char *info_str = NULL;
12421 #endif
12422          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
12423          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
12424          ast_cli(a->fd, "Status: %s\n", status);
12425 #ifdef PRI_DUMP_INFO_STR
12426          info_str = pri_dump_info_str(pris[span-1].pri);
12427          if (info_str) {
12428             ast_cli(a->fd, "%s", info_str);
12429             ast_free(info_str);
12430          }
12431 #else
12432          pri_dump_info(pris[span-1].pri);
12433 #endif
12434          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
12435       }
12436    }
12437    return CLI_SUCCESS;
12438 }

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

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

12358 {
12359    int span;
12360    int x;
12361    char status[256];
12362 
12363    switch (cmd) {
12364    case CLI_INIT:
12365       e->command = "pri show spans";
12366       e->usage = 
12367          "Usage: pri show spans\n"
12368          "       Displays PRI Information\n";
12369       return NULL;
12370    case CLI_GENERATE:
12371       return NULL;   
12372    }
12373 
12374    if (a->argc != 3)
12375       return CLI_SHOWUSAGE;
12376 
12377    for (span = 0; span < NUM_SPANS; span++) {
12378       if (pris[span].pri) {
12379          for (x = 0; x < NUM_DCHANS; x++) {
12380             if (pris[span].dchannels[x]) {
12381                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
12382                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
12383             }
12384          }
12385       }
12386    }
12387    return CLI_SUCCESS;
12388 }

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

Definition at line 12171 of file chan_dahdi.c.

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

12172 {
12173    switch (cmd) {
12174    case CLI_INIT:
12175       e->command = "pri unset debug file";
12176       e->usage = "Usage: pri unset debug file\n"
12177             "       Stop sending debug output to the previously \n"
12178                  "       specified file\n";
12179       return NULL;
12180    case CLI_GENERATE:
12181       return NULL;   
12182    }
12183    /* Assume it is unset */
12184    ast_mutex_lock(&pridebugfdlock);
12185    close(pridebugfd);
12186    pridebugfd = -1;
12187    ast_cli(a->fd, "PRI debug output to file disabled\n");
12188    ast_mutex_unlock(&pridebugfdlock);
12189    return CLI_SUCCESS;
12190 }

static char* handle_pri_version ( 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(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

12482 {
12483    switch (cmd) {
12484    case CLI_INIT:
12485       e->command = "pri show version";
12486       e->usage = 
12487          "Usage: pri show version\n"
12488          "Show libpri version information\n";
12489       return NULL;
12490    case CLI_GENERATE:
12491       return NULL;
12492    }
12493 
12494    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
12495 
12496    return CLI_SUCCESS;
12497 }

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

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

13790 {
13791    int linkset, cic;
13792    int blocked = -1, i;
13793    switch (cmd) {
13794    case CLI_INIT:
13795       e->command = "ss7 block cic";
13796       e->usage = 
13797          "Usage: ss7 block cic <linkset> <CIC>\n"
13798          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
13799       return NULL;
13800    case CLI_GENERATE:
13801       return NULL;
13802    }
13803    if (a->argc == 5)
13804       linkset = atoi(a->argv[3]);
13805    else
13806       return CLI_SHOWUSAGE;
13807 
13808    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13809       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13810       return CLI_SUCCESS;
13811    }
13812 
13813    if (!linksets[linkset-1].ss7) {
13814       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13815       return CLI_SUCCESS;
13816    }
13817 
13818    cic = atoi(a->argv[4]);
13819 
13820    if (cic < 1) {
13821       ast_cli(a->fd, "Invalid CIC specified!\n");
13822       return CLI_SUCCESS;
13823    }
13824 
13825    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13826       if (linksets[linkset-1].pvts[i]->cic == cic) {
13827          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13828          if (!blocked) {
13829             ast_mutex_lock(&linksets[linkset-1].lock);
13830             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13831             ast_mutex_unlock(&linksets[linkset-1].lock);
13832          }
13833       }
13834    }
13835 
13836    if (blocked < 0) {
13837       ast_cli(a->fd, "Invalid CIC specified!\n");
13838       return CLI_SUCCESS;
13839    }
13840 
13841    if (!blocked)
13842       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
13843    else
13844       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
13845 
13846    /* Break poll on the linkset so it sends our messages */
13847    pthread_kill(linksets[linkset-1].master, SIGURG);
13848 
13849    return CLI_SUCCESS;
13850 }

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

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

13853 {
13854    int linkset;
13855    int i;
13856    switch (cmd) {
13857    case CLI_INIT:
13858       e->command = "ss7 block linkset";
13859       e->usage = 
13860          "Usage: ss7 block linkset <linkset number>\n"
13861          "       Sends a remote blocking request for all CICs on the given linkset\n";
13862       return NULL;
13863    case CLI_GENERATE:
13864       return NULL;
13865    }
13866    if (a->argc == 4)
13867       linkset = atoi(a->argv[3]);
13868    else
13869       return CLI_SHOWUSAGE;
13870 
13871    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13872       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13873       return CLI_SUCCESS;
13874    }
13875 
13876    if (!linksets[linkset-1].ss7) {
13877       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13878       return CLI_SUCCESS;
13879    }
13880 
13881    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13882       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13883       ast_mutex_lock(&linksets[linkset-1].lock);
13884       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13885       ast_mutex_unlock(&linksets[linkset-1].lock);
13886    }
13887 
13888    /* Break poll on the linkset so it sends our messages */
13889    pthread_kill(linksets[linkset-1].master, SIGURG);
13890 
13891    return CLI_SUCCESS;
13892 }

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

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

13759 {
13760    int span;
13761    switch (cmd) {
13762    case CLI_INIT:
13763       e->command = "ss7 debug linkset";
13764       e->usage = 
13765          "Usage: ss7 debug linkset <linkset>\n"
13766          "       Enables debugging on a given SS7 linkset\n";
13767       return NULL;
13768    case CLI_GENERATE:
13769       return NULL;
13770    }
13771    if (a->argc < 4)
13772       return CLI_SHOWUSAGE;
13773    span = atoi(a->argv[3]);
13774    if ((span < 1) || (span > NUM_SPANS)) {
13775       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13776       return CLI_SUCCESS;
13777    }
13778    if (!linksets[span-1].ss7) {
13779       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
13780       return CLI_SUCCESS;
13781    }
13782    if (linksets[span-1].ss7)
13783       ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
13784 
13785    ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
13786    return CLI_SUCCESS;
13787 }

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

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

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

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

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

13995 {
13996    int linkset;
13997    struct dahdi_ss7 *ss7;
13998    switch (cmd) {
13999    case CLI_INIT:
14000       e->command = "ss7 show linkset";
14001       e->usage = 
14002          "Usage: ss7 show linkset <span>\n"
14003          "       Shows the status of an SS7 linkset.\n";
14004       return NULL;
14005    case CLI_GENERATE:
14006       return NULL;
14007    }
14008 
14009    if (a->argc < 4)
14010       return CLI_SHOWUSAGE;
14011    linkset = atoi(a->argv[3]);
14012    if ((linkset < 1) || (linkset > NUM_SPANS)) {
14013       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
14014       return CLI_SUCCESS;
14015    }
14016    if (!linksets[linkset-1].ss7) {
14017       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
14018       return CLI_SUCCESS;
14019    }
14020    if (linksets[linkset-1].ss7)
14021       ss7 = &linksets[linkset-1];
14022 
14023    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
14024 
14025    return CLI_SUCCESS;
14026 }

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

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

13895 {
13896    int linkset, cic;
13897    int i, blocked = -1;
13898    switch (cmd) {
13899    case CLI_INIT:
13900       e->command = "ss7 unblock cic";
13901       e->usage = 
13902          "Usage: ss7 unblock cic <linkset> <CIC>\n"
13903          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
13904       return NULL;
13905    case CLI_GENERATE:
13906       return NULL;
13907    }
13908 
13909    if (a->argc == 5)
13910       linkset = atoi(a->argv[3]);
13911    else
13912       return CLI_SHOWUSAGE;
13913 
13914    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13915       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13916       return CLI_SUCCESS;
13917    }
13918 
13919    if (!linksets[linkset-1].ss7) {
13920       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13921       return CLI_SUCCESS;
13922    }
13923 
13924    cic = atoi(a->argv[4]);
13925 
13926    if (cic < 1) {
13927       ast_cli(a->fd, "Invalid CIC specified!\n");
13928       return CLI_SUCCESS;
13929    }
13930 
13931    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13932       if (linksets[linkset-1].pvts[i]->cic == cic) {
13933          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
13934          if (blocked) {
13935             ast_mutex_lock(&linksets[linkset-1].lock);
13936             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
13937             ast_mutex_unlock(&linksets[linkset-1].lock);
13938          }
13939       }
13940    }
13941 
13942    if (blocked > 0)
13943       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
13944 
13945    /* Break poll on the linkset so it sends our messages */
13946    pthread_kill(linksets[linkset-1].master, SIGURG);
13947 
13948    return CLI_SUCCESS;
13949 }

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

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

13952 {
13953    int linkset;
13954    int i;
13955    switch (cmd) {
13956    case CLI_INIT:
13957       e->command = "ss7 unblock linkset";
13958       e->usage = 
13959          "Usage: ss7 unblock linkset <linkset number>\n"
13960          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
13961       return NULL;
13962    case CLI_GENERATE:
13963       return NULL;
13964    }
13965 
13966    if (a->argc == 4)
13967       linkset = atoi(a->argv[3]);
13968    else
13969       return CLI_SHOWUSAGE;
13970 
13971    if ((linkset < 1) || (linkset > NUM_SPANS)) {
13972       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
13973       return CLI_SUCCESS;
13974    }
13975 
13976    if (!linksets[linkset-1].ss7) {
13977       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
13978       return CLI_SUCCESS;
13979    }
13980 
13981    for (i = 0; i < linksets[linkset-1].numchans; i++) {
13982       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
13983       ast_mutex_lock(&linksets[linkset-1].lock);
13984       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
13985       ast_mutex_unlock(&linksets[linkset-1].lock);
13986    }
13987 
13988    /* Break poll on the linkset so it sends our messages */
13989    pthread_kill(linksets[linkset-1].master, SIGURG);
13990 
13991    return CLI_SUCCESS;
13992 }

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

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

14029 {
14030    switch (cmd) {
14031    case CLI_INIT:
14032       e->command = "ss7 show version";
14033       e->usage = 
14034          "Usage: ss7 show version\n"
14035          "  Show the libss7 version\n";
14036       return NULL;
14037    case CLI_GENERATE:
14038       return NULL;
14039    }
14040 
14041    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
14042 
14043    return CLI_SUCCESS;
14044 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 1861 of file chan_dahdi.c.

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

Referenced by conf_del().

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

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

Definition at line 1891 of file chan_dahdi.c.

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

Referenced by update_conf().

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

static int linkset_addsigchan ( int  sigchan  )  [static]

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

13607 {
13608    struct dahdi_ss7 *link;
13609    int res;
13610    int curfd;
13611    struct dahdi_params p;
13612    struct dahdi_bufferinfo bi;
13613    struct dahdi_spaninfo si;
13614 
13615 
13616    link = ss7_resolve_linkset(cur_linkset);
13617    if (!link) {
13618       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
13619       return -1;
13620    }
13621 
13622    if (cur_ss7type < 0) {
13623       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
13624       return -1;
13625    }
13626 
13627    if (!link->ss7)
13628       link->ss7 = ss7_new(cur_ss7type);
13629 
13630    if (!link->ss7) {
13631       ast_log(LOG_ERROR, "Can't create new SS7!\n");
13632       return -1;
13633    }
13634 
13635    link->type = cur_ss7type;
13636 
13637    if (cur_pointcode < 0) {
13638       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
13639       return -1;
13640    } else
13641       ss7_set_pc(link->ss7, cur_pointcode);
13642 
13643    if (sigchan < 0) {
13644       ast_log(LOG_ERROR, "Invalid sigchan!\n");
13645       return -1;
13646    } else {
13647       if (link->numsigchans >= NUM_DCHANS) {
13648          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
13649          return -1;
13650       }
13651       curfd = link->numsigchans;
13652 
13653       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
13654       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
13655          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
13656          return -1;
13657       }
13658       memset(&p, 0, sizeof(p));
13659       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
13660       if (res) {
13661          dahdi_close_ss7_fd(link, curfd);
13662          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
13663          return -1;
13664       }
13665       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
13666          dahdi_close_ss7_fd(link, curfd);
13667          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
13668          return -1;
13669       }
13670 
13671       memset(&bi, 0, sizeof(bi));
13672       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13673       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13674       bi.numbufs = 32;
13675       bi.bufsize = 512;
13676 
13677       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
13678          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
13679          dahdi_close_ss7_fd(link, curfd);
13680          return -1;
13681       }
13682 
13683       if (p.sigtype == DAHDI_SIG_MTP2)
13684          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
13685       else
13686          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
13687 
13688       link->numsigchans++;
13689 
13690       memset(&si, 0, sizeof(si));
13691       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
13692       if (res) {
13693          dahdi_close_ss7_fd(link, curfd);
13694          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
13695       }
13696 
13697       if (!si.alarms) {
13698          link->linkstate[curfd] = LINKSTATE_DOWN;
13699          ss7_link_noalarm(link->ss7, link->fds[curfd]);
13700       } else {
13701          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
13702          ss7_link_alarm(link->ss7, link->fds[curfd]);
13703       }
13704    }
13705 
13706    if (cur_adjpointcode < 0) {
13707       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
13708       return -1;
13709    } else {
13710       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
13711    }
13712 
13713    if (cur_defaultdpc < 0) {
13714       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
13715       return -1;
13716    }
13717 
13718    if (cur_networkindicator < 0) {
13719       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
13720       return -1;
13721    } else
13722       ss7_set_network_ind(link->ss7, cur_networkindicator);
13723 
13724    return 0;
13725 }

static int load_module ( void   )  [static]

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

15347 {
15348    int res;
15349 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15350    int y, i;
15351 #endif
15352 
15353 #ifdef HAVE_PRI
15354    memset(pris, 0, sizeof(pris));
15355    for (y = 0; y < NUM_SPANS; y++) {
15356       ast_mutex_init(&pris[y].lock);
15357       pris[y].offset = -1;
15358       pris[y].master = AST_PTHREADT_NULL;
15359       for (i = 0; i < NUM_DCHANS; i++)
15360          pris[y].fds[i] = -1;
15361    }
15362    pri_set_error(dahdi_pri_error);
15363    pri_set_message(dahdi_pri_message);
15364    ast_register_application(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec,
15365          dahdi_send_keypad_facility_synopsis, dahdi_send_keypad_facility_descrip);
15366 #endif
15367 #ifdef HAVE_SS7
15368    memset(linksets, 0, sizeof(linksets));
15369    for (y = 0; y < NUM_SPANS; y++) {
15370       ast_mutex_init(&linksets[y].lock);
15371       linksets[y].master = AST_PTHREADT_NULL;
15372       for (i = 0; i < NUM_DCHANS; i++)
15373          linksets[y].fds[i] = -1;
15374    }
15375    ss7_set_error(dahdi_ss7_error);
15376    ss7_set_message(dahdi_ss7_message);
15377 #endif /* HAVE_SS7 */
15378    res = setup_dahdi(0);
15379    /* Make sure we can register our DAHDI channel type */
15380    if (res)
15381       return AST_MODULE_LOAD_DECLINE;
15382    if (ast_channel_register(&dahdi_tech)) {
15383       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
15384       __unload_module();
15385       return AST_MODULE_LOAD_FAILURE;
15386    }
15387 #ifdef HAVE_PRI
15388    ast_string_field_init(&inuse, 16);
15389    ast_string_field_set(&inuse, name, "GR-303InUse");
15390    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15391 #endif   
15392 #ifdef HAVE_SS7
15393    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15394 #endif
15395 
15396    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15397    
15398    memset(round_robin, 0, sizeof(round_robin));
15399    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
15400    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
15401    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
15402    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
15403    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
15404    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
15405    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
15406 
15407    ast_cond_init(&mwi_thread_complete, NULL);
15408    ast_cond_init(&ss_thread_complete, NULL);
15409 
15410    return res;
15411 }

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

Definition at line 8744 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, ast_variable::file, 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, ast_variable::next, 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().

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

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

Definition at line 295 of file chan_dahdi.c.

Referenced by mkintf().

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

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

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

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

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

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

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

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

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

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

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

Definition at line 6495 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

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

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

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

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

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

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

Definition at line 8711 of file chan_dahdi.c.

Referenced by process_dahdi().

08712 {
08713    unsigned int code1, code2, code3;
08714    int numvals;
08715 
08716    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
08717    if (numvals == 1)
08718       return code1;
08719    if (numvals == 3)
08720       return (code1 << 16) | (code2 << 8) | code3;
08721 
08722    return 0;
08723 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

Definition at line 3341 of file chan_dahdi.c.

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

Referenced by pri_find_principle().

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

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

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

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

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

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

10827 {
10828    do {
10829       pri->resetpos++;
10830    } while ((pri->resetpos < pri->numchans) &&
10831        (!pri->pvts[pri->resetpos] ||
10832         pri->pvts[pri->resetpos]->call ||
10833         pri->pvts[pri->resetpos]->resetting));
10834    if (pri->resetpos < pri->numchans) {
10835       /* Mark the channel as resetting and restart it */
10836       pri->pvts[pri->resetpos]->resetting = 1;
10837       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
10838    } else {
10839       pri->resetting = 0;
10840       time(&pri->lastreset);
10841    }
10842    return 0;
10843 }

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

Definition at line 8696 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

08697 {
08698    if (pris[span].mastertrunkgroup) {
08699       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);
08700       return -1;
08701    }
08702    pris[span].mastertrunkgroup = trunkgroup;
08703    pris[span].prilogicalspan = logicalspan;
08704    return 0;
08705 }

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

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

08634 {
08635    struct dahdi_spaninfo si;
08636    struct dahdi_params p;
08637    int fd;
08638    int span;
08639    int ospan=0;
08640    int x,y;
08641    for (x = 0; x < NUM_SPANS; x++) {
08642       if (pris[x].trunkgroup == trunkgroup) {
08643          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
08644          return -1;
08645       }
08646    }
08647    for (y = 0; y < NUM_DCHANS; y++) {
08648       if (!channels[y]) 
08649          break;
08650       memset(&si, 0, sizeof(si));
08651       memset(&p, 0, sizeof(p));
08652       fd = open("/dev/dahdi/channel", O_RDWR);
08653       if (fd < 0) {
08654          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
08655          return -1;
08656       }
08657       x = channels[y];
08658       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
08659          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
08660          close(fd);
08661          return -1;
08662       }
08663       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
08664          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
08665          return -1;
08666       }
08667       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
08668          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
08669          close(fd);
08670          return -1;
08671       }
08672       span = p.spanno - 1;
08673       if (pris[span].trunkgroup) {
08674          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
08675          close(fd);
08676          return -1;
08677       }
08678       if (pris[span].pvts[0]) {
08679          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
08680          close(fd);
08681          return -1;
08682       }
08683       if (!y) {
08684          pris[span].trunkgroup = trunkgroup;
08685          pris[span].offset = channels[y] - p.chanpos;
08686          ospan = span;
08687       }
08688       pris[ospan].dchannels[y] = channels[y];
08689       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
08690       pris[span].span = span + 1;
08691       close(fd);
08692    }
08693    return 0;   
08694 }

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

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

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

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

Definition at line 10573 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

10574 {
10575    struct dahdi_pvt *p;
10576    p = pri->crvs;
10577    while (p) {
10578       if (p->channel == crv)
10579          return p;
10580       p = p->next;
10581    }
10582    return NULL;
10583 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

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

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

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

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

09473 {
09474    int x;
09475    if (backwards)
09476       x = pri->numchans;
09477    else
09478       x = 0;
09479    for (;;) {
09480       if (backwards && (x < 0))
09481          break;
09482       if (!backwards && (x >= pri->numchans))
09483          break;
09484       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
09485          ast_debug(1, "Found empty available channel %d/%d\n", 
09486             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
09487          return x;
09488       }
09489       if (backwards)
09490          x--;
09491       else
09492          x++;
09493    }
09494    return -1;
09495 }

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

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

10587 {
10588    int x;
10589    int span = PRI_SPAN(channel);
10590    int spanfd;
10591    struct dahdi_params param;
10592    int principle = -1;
10593    int explicit = PRI_EXPLICIT(channel);
10594    channel = PRI_CHANNEL(channel);
10595 
10596    if (!explicit) {
10597       spanfd = pri_active_dchan_fd(pri);
10598       memset(&param, 0, sizeof(param));
10599       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
10600          return -1;
10601       span = pris[param.spanno - 1].prilogicalspan;
10602    }
10603 
10604    for (x = 0; x < pri->numchans; x++) {
10605       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
10606          principle = x;
10607          break;
10608       }
10609    }
10610    
10611    return principle;
10612 }

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

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

10615 {
10616    int x;
10617    struct dahdi_pvt *crv;
10618    if (!c) {
10619       if (principle < 0)
10620          return -1;
10621       return principle;
10622    }
10623    if ((principle > -1) && 
10624       (principle < pri->numchans) && 
10625       (pri->pvts[principle]) && 
10626       (pri->pvts[principle]->call == c))
10627       return principle;
10628    /* First, check for other bearers */
10629    for (x = 0; x < pri->numchans; x++) {
10630       if (!pri->pvts[x])
10631          continue;
10632       if (pri->pvts[x]->call == c) {
10633          /* Found our call */
10634          if (principle != x) {
10635             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
10636 
10637             ast_verb(3, "Moving call from channel %d to channel %d\n",
10638                 old->channel, new->channel);
10639             if (new->owner) {
10640                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
10641                   old->channel, new->channel, new->channel);
10642                return -1;
10643             }
10644             /* Fix it all up now */
10645             new->owner = old->owner;
10646             old->owner = NULL;
10647             if (new->owner) {
10648                ast_string_field_build(new->owner, name, 
10649                             "DAHDI/%d:%d-%d", pri->trunkgroup,
10650                             new->channel, 1);
10651                new->owner->tech_pvt = new;
10652                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
10653                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
10654                old->subs[SUB_REAL].owner = NULL;
10655             } else
10656                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);
10657             new->call = old->call;
10658             old->call = NULL;
10659 
10660             /* Copy any DSP that may be present */
10661             new->dsp = old->dsp;
10662             new->dsp_features = old->dsp_features;
10663             old->dsp = NULL;
10664             old->dsp_features = 0;
10665          }
10666          return principle;
10667       }
10668    }
10669    /* Now check for a CRV with no bearer */
10670    crv = pri->crvs;
10671    while (crv) {
10672       if (crv->call == c) {
10673          /* This is our match...  Perform some basic checks */
10674          if (crv->bearer)
10675             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
10676          else if (pri->pvts[principle]->owner) 
10677             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
10678          else {
10679             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
10680                wakeup the potential sleeper */
10681             dahdi_close_sub(crv, SUB_REAL);
10682             pri->pvts[principle]->call = crv->call;
10683             pri_assign_bearer(crv, pri, pri->pvts[principle]);
10684             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
10685                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
10686                pri->trunkgroup, crv->channel);
10687             wakeup_sub(crv, SUB_REAL, pri);
10688          }
10689          return principle;
10690       }
10691       crv = crv->next;
10692    }
10693    ast_log(LOG_WARNING, "Call specified, but not found?\n");
10694    return -1;
10695 }

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

Definition at line 1228 of file chan_dahdi.c.

References ast_mutex_trylock(), AST_PTHREADT_NULL, DEADLOCK_AVOIDANCE, dahdi_pvt::lock, dahdi_pri::lock, 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(), dahdi_write(), and ss_thread().

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

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

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

10846 {
10847    int x;
10848    int redo;
10849    ast_mutex_unlock(&pri->lock);
10850    ast_mutex_lock(&p->lock);
10851    do {
10852       redo = 0;
10853       for (x = 0; x < 3; x++) {
10854          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
10855             redo++;
10856             DEADLOCK_AVOIDANCE(&p->lock);
10857          }
10858          if (p->subs[x].owner) {
10859             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
10860             ast_channel_unlock(p->subs[x].owner);
10861          }
10862       }
10863    } while (redo);
10864    ast_mutex_unlock(&p->lock);
10865    ast_mutex_lock(&pri->lock);
10866    return 0;
10867 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 3301 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.

Referenced by mkintf(), and pri_dchannel().

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

static char* pri_order ( int  level  )  [static]

Definition at line 3324 of file chan_dahdi.c.

Referenced by handle_pri_show_span(), and pri_dchannel().

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

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

08588 {
08589    int x;
08590    int trunkgroup;
08591    /* Get appropriate trunk group if there is one */
08592    trunkgroup = pris[*span].mastertrunkgroup;
08593    if (trunkgroup) {
08594       /* Select a specific trunk group */
08595       for (x = 0; x < NUM_SPANS; x++) {
08596          if (pris[x].trunkgroup == trunkgroup) {
08597             *span = x;
08598             return 0;
08599          }
08600       }
08601       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
08602       *span = -1;
08603    } else {
08604       if (pris[*span].trunkgroup) {
08605          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
08606          *span = -1;
08607       } else if (pris[*span].mastertrunkgroup) {
08608          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
08609          *span = -1;
08610       } else {
08611          if (si->totalchans == 31) {
08612             /* E1 */
08613             pris[*span].dchannels[0] = 16 + offset;
08614          } else if (si->totalchans == 24) {
08615             /* T1 or J1 */
08616             pris[*span].dchannels[0] = 24 + offset;
08617          } else if (si->totalchans == 3) {
08618             /* BRI */
08619             pris[*span].dchannels[0] = 3 + offset;
08620          } else {
08621             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);
08622             *span = -1;
08623             return 0;
08624          }
08625          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
08626          pris[*span].offset = offset;
08627          pris[*span].span = *span + 1;
08628       }
08629    }
08630    return 0;
08631 }

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

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

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

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

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

14244 {
14245    char *parse = ast_strdupa(data);
14246    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
14247    unsigned int param_count;
14248    unsigned int x;
14249 
14250    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
14251       return;
14252 
14253    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
14254 
14255    /* first parameter is tap length, process it here */
14256 
14257    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
14258    
14259    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
14260       confp->chan.echocancel.head.tap_length = x;
14261    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
14262       confp->chan.echocancel.head.tap_length = 128;
14263 
14264    /* now process any remaining parameters */
14265 
14266    for (x = 1; x < param_count; x++) {
14267       struct {
14268          char *name;
14269          char *value;
14270       } param;
14271 
14272       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
14273          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
14274          continue;
14275       }
14276 
14277       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
14278          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
14279          continue;
14280       }
14281 
14282       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
14283 
14284       if (param.value) {
14285          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
14286             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
14287             continue;
14288          }
14289       }
14290       confp->chan.echocancel.head.param_count++;
14291    }
14292 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 10869 of file chan_dahdi.c.

Referenced by pri_dchannel().

10870 {
10871    switch (redirectingreason) {
10872    case 0:
10873       return "UNKNOWN";
10874    case 1:
10875       return "BUSY";
10876    case 2:
10877       return "NO_REPLY";
10878    case 0xF:
10879       return "UNCONDITIONAL";
10880    default:
10881       return "NOREDIRECT";
10882    }
10883 }

static int reload ( void   )  [static]

Definition at line 15513 of file chan_dahdi.c.

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

15514 {
15515    int res = 0;
15516 
15517    res = setup_dahdi(1);
15518    if (res) {
15519       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
15520       return -1;
15521    }
15522    return 0;
15523 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

Definition at line 1935 of file chan_dahdi.c.

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

Referenced by dahdi_hangup().

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

static int restart_monitor ( void   )  [static]

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

08561 {
08562    /* If we're supposed to be stopped -- stay stopped */
08563    if (monitor_thread == AST_PTHREADT_STOP)
08564       return 0;
08565    ast_mutex_lock(&monlock);
08566    if (monitor_thread == pthread_self()) {
08567       ast_mutex_unlock(&monlock);
08568       ast_log(LOG_WARNING, "Cannot kill myself\n");
08569       return -1;
08570    }
08571    if (monitor_thread != AST_PTHREADT_NULL) {
08572       /* Wake up the thread */
08573       pthread_kill(monitor_thread, SIGURG);
08574    } else {
08575       /* Start a new monitor */
08576       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
08577          ast_mutex_unlock(&monlock);
08578          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
08579          return -1;
08580       }
08581    }
08582    ast_mutex_unlock(&monlock);
08583    return 0;
08584 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

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

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

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

static int save_conference ( struct dahdi_pvt p  )  [static]

Definition at line 2241 of file chan_dahdi.c.

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

Referenced by dahdi_callwait(), and dahdi_handle_event().

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

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

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

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 2176 of file chan_dahdi.c.

References set_actual_rxgain(), and set_actual_txgain().

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

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

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

Definition at line 2158 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

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

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

Definition at line 2140 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

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

static int setup_dahdi ( int  reload  )  [static]

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

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

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 8739 of file chan_dahdi.c.

Referenced by mkintf().

08740 {
08741         return sigtype;
08742 }

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

09977 {
09978    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
09979       if (size) {
09980          *buf = '\0';
09981       }
09982       return;
09983    }
09984    switch (nai) {
09985    case SS7_NAI_INTERNATIONAL:
09986       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
09987       break;
09988    case SS7_NAI_NATIONAL:
09989       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
09990       break;
09991    case SS7_NAI_SUBSCRIBER:
09992       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
09993       break;
09994    case SS7_NAI_UNKNOWN:
09995       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
09996       break;
09997    default:
09998       snprintf(buf, size, "%s", number);
09999       break;
10000    }
10001 }

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

09796 {
09797    int i;
09798 
09799    for (i = 0; i < linkset->numchans; i++) {
09800       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09801          if (state) {
09802             if (state[i])
09803                linkset->pvts[i]->remotelyblocked = block;
09804          } else
09805             linkset->pvts[i]->remotelyblocked = block;
09806       }
09807    }
09808 }

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

Definition at line 9750 of file chan_dahdi.c.

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

Referenced by ss7_linkset().

09751 {
09752    int i;
09753    int winner = -1;
09754    for (i = 0; i < linkset->numchans; i++) {
09755       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
09756          winner = i;
09757          break;
09758       }
09759    }
09760    return winner;
09761 }

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

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

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

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

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

09764 {
09765    unsigned char status[32];
09766    struct dahdi_pvt *p = NULL;
09767    int i, offset;
09768 
09769    for (i = 0; i < linkset->numchans; i++) {
09770       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
09771          p = linkset->pvts[i];
09772          offset = p->cic - startcic;
09773          status[offset] = 0;
09774          if (p->locallyblocked)
09775             status[offset] |= (1 << 0) | (1 << 4);
09776          if (p->remotelyblocked)
09777             status[offset] |= (1 << 1) | (1 << 5);
09778          if (p->ss7call) {
09779             if (p->outgoing)
09780                status[offset] |= (1 << 3);
09781             else
09782                status[offset] |= (1 << 2);
09783          } else
09784             status[offset] |= 0x3 << 2;
09785       }
09786    }
09787 
09788    if (p)
09789       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
09790    else
09791       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
09792    
09793 }

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

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

09811 {
09812    int i;
09813 
09814    for (i = 0; i < linkset->numchans; i++) {
09815       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
09816          linkset->pvts[i]->inservice = 1;
09817    }
09818 }

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

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

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

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

Definition at line 10002 of file chan_dahdi.c.

Referenced by ss7_linkset().

10003 {
10004     return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
10005 }

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

Definition at line 1246 of file chan_dahdi.c.

References ast_mutex_unlock(), and dahdi_ss7::lock.

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

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

static void ss7_reset_linkset ( struct dahdi_ss7 linkset  )  [static]

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

09821 {
09822    int i, startcic = -1, endcic, dpc;
09823 
09824    if (linkset->numchans <= 0)
09825       return;
09826 
09827    startcic = linkset->pvts[0]->cic;
09828    /* DB: CIC's DPC fix */
09829    dpc = linkset->pvts[0]->dpc;
09830 
09831    for (i = 0; i < linkset->numchans; i++) {
09832       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)) {
09833          continue;
09834       } else {
09835          endcic = linkset->pvts[i]->cic;
09836          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
09837          isup_grs(linkset->ss7, startcic, endcic, dpc);
09838 
09839          /* DB: CIC's DPC fix */
09840          if (linkset->pvts[i+1]) {
09841             startcic = linkset->pvts[i+1]->cic;
09842             dpc = linkset->pvts[i+1]->dpc;
09843          }
09844       }
09845    }
09846 }

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

Definition at line 8725 of file chan_dahdi.c.

References linksets, and NUM_SPANS.

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

08726 {
08727    if ((linkset < 0) || (linkset >= NUM_SPANS))
08728       return NULL;
08729    else
08730       return &linksets[linkset - 1];
08731 }

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

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

09861 {
09862    struct ss7 *ss7 = linkset->ss7;
09863    int res;
09864    int law = 1;
09865    struct ast_channel *c;
09866    char tmp[256];
09867 
09868    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
09869       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
09870    
09871    if (linkset->type == SS7_ITU)
09872       law = DAHDI_LAW_ALAW;
09873    else
09874       law = DAHDI_LAW_MULAW;
09875 
09876    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
09877    if (res < 0) 
09878       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
09879    
09880    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
09881       p->proceeding = 1;
09882       isup_acm(ss7, p->ss7call);
09883    }
09884 
09885    ast_mutex_unlock(&linkset->lock);
09886    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
09887 
09888    if (!c) {
09889       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
09890       /* Holding this lock is assumed entering the function */
09891       ast_mutex_lock(&linkset->lock);
09892       return;
09893    } else
09894       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
09895 
09896    dahdi_enable_ec(p);
09897 
09898    /* We only reference these variables in the context of the ss7_linkset function
09899     * when receiving either and IAM or a COT message.  Since they are only accessed
09900     * from this context, we should be safe to unlock around them */
09901 
09902    ast_mutex_unlock(&p->lock);
09903 
09904    if (!ast_strlen_zero(p->charge_number)) {
09905       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
09906       /* Clear this after we set it */
09907       p->charge_number[0] = 0;
09908    }
09909    if (!ast_strlen_zero(p->gen_add_number)) {
09910       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
09911       /* Clear this after we set it */
09912       p->gen_add_number[0] = 0;
09913    }
09914    if (!ast_strlen_zero(p->jip_number)) {
09915       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
09916       /* Clear this after we set it */
09917       p->jip_number[0] = 0;
09918    }
09919    if (!ast_strlen_zero(p->gen_dig_number)) {
09920       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
09921       /* Clear this after we set it */
09922       p->gen_dig_number[0] = 0;
09923    }
09924    if (!ast_strlen_zero(p->orig_called_num)) {
09925       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
09926       /* Clear this after we set it */
09927       p->orig_called_num[0] = 0;
09928    }
09929 
09930    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
09931    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
09932    /* Clear this after we set it */
09933    p->gen_dig_type = 0;
09934 
09935    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
09936    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
09937    /* Clear this after we set it */
09938    p->gen_dig_scheme = 0;
09939 
09940    if (!ast_strlen_zero(p->lspi_ident)) {
09941       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
09942       /* Clear this after we set it */
09943       p->lspi_ident[0] = 0;
09944    }
09945 
09946    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
09947    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
09948    /* Clear this after we set it */
09949    p->call_ref_ident = 0;
09950 
09951    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
09952    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
09953    /* Clear this after we set it */
09954    p->call_ref_pc = 0;
09955 
09956    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
09957    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
09958    /* Clear this after we set it */
09959    p->calling_party_cat = 0;
09960 
09961    if (!ast_strlen_zero(p->redirecting_num)) {
09962       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
09963       /* Clear this after we set it */
09964       p->redirecting_num[0] = 0;
09965    }
09966    if (!ast_strlen_zero(p->generic_name)) {
09967       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
09968       /* Clear this after we set it */
09969       p->generic_name[0] = 0;
09970    }
09971 
09972    ast_mutex_lock(&p->lock);
09973    ast_mutex_lock(&linkset->lock);
09974 }

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

Definition at line 6554 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_OVERLAPDIAL_INCOMING, 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, dahdi_pvt::inalarm, 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_pri::overlapdial, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_setvar_helper(), dahdi_pvt::polarity, POLARITY_IDLE, POLARITY_REV, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, PVT_TO_CHANNEL, 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, dahdi_pvt::span, 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().

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

static int start_pri ( struct dahdi_pri pri  )  [static]

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

12045 {
12046    int res, x;
12047    struct dahdi_params p;
12048    struct dahdi_bufferinfo bi;
12049    struct dahdi_spaninfo si;
12050    int i;
12051    
12052    for (i = 0; i < NUM_DCHANS; i++) {
12053       if (!pri->dchannels[i])
12054          break;
12055       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
12056       x = pri->dchannels[i];
12057       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
12058          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
12059          return -1;
12060       }
12061       memset(&p, 0, sizeof(p));
12062       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
12063       if (res) {
12064          dahdi_close_pri_fd(pri, i);
12065          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
12066          return -1;
12067       }
12068       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
12069          dahdi_close_pri_fd(pri, i);
12070          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
12071          return -1;
12072       }
12073       memset(&si, 0, sizeof(si));
12074       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
12075       if (res) {
12076          dahdi_close_pri_fd(pri, i);
12077          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
12078       }
12079       if (!si.alarms)
12080          pri->dchanavail[i] |= DCHAN_NOTINALARM;
12081       else
12082          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
12083       memset(&bi, 0, sizeof(bi));
12084       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
12085       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
12086       bi.numbufs = 32;
12087       bi.bufsize = 1024;
12088       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
12089          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
12090          dahdi_close_pri_fd(pri, i);
12091          return -1;
12092       }
12093       switch (pri->sig) {
12094          case SIG_BRI:
12095             pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
12096             break;
12097          case SIG_BRI_PTMP:
12098             pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
12099             break;
12100          default:
12101             pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
12102       }
12103       /* Force overlap dial if we're doing GR-303! */
12104       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
12105          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
12106       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
12107 #ifdef HAVE_PRI_INBANDDISCONNECT
12108       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
12109 #endif
12110       /* Enslave to master if appropriate */
12111       if (i)
12112          pri_enslave(pri->dchans[0], pri->dchans[i]);
12113       if (!pri->dchans[i]) {
12114          dahdi_close_pri_fd(pri, i);
12115          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
12116          return -1;
12117       }
12118       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
12119       pri_set_nsf(pri->dchans[i], pri->nsf);
12120 #ifdef PRI_GETSET_TIMERS
12121       for (x = 0; x < PRI_MAX_TIMERS; x++) {
12122          if (pritimers[x] != 0)
12123             pri_set_timer(pri->dchans[i], x, pritimers[x]);
12124       }
12125 #endif
12126    }
12127    /* Assume primary is the one we use */
12128    pri->pri = pri->dchans[0];
12129    pri->resetpos = -1;
12130    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
12131       for (i = 0; i < NUM_DCHANS; i++) {
12132          if (!pri->dchannels[i])
12133             break;
12134          dahdi_close_pri_fd(pri, i);
12135       }
12136       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
12137       return -1;
12138    }
12139    return 0;
12140 }

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

Definition at line 1409 of file chan_dahdi.c.

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

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

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

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

Definition at line 1559 of file chan_dahdi.c.

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

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

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

static int unload_module ( void   )  [static]

Definition at line 14135 of file chan_dahdi.c.

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

14136 {
14137 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14138    int y;
14139 #endif
14140 #ifdef HAVE_PRI
14141    for (y = 0; y < NUM_SPANS; y++)
14142       ast_mutex_destroy(&pris[y].lock);
14143 #endif
14144 #ifdef HAVE_SS7
14145    for (y = 0; y < NUM_SPANS; y++)
14146       ast_mutex_destroy(&linksets[y].lock);
14147 #endif /* HAVE_SS7 */
14148    return __unload_module();
14149 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

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

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

Definition at line 1316 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_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().

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


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "DAHDI Telephony w/PRI & 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 15547 of file chan_dahdi.c.

int alarm

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

Definition at line 15547 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

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

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

Definition at line 169 of file chan_dahdi.c.

int cur_adjpointcode = -1 [static]

Definition at line 384 of file chan_dahdi.c.

int cur_cicbeginswith = -1 [static]

Definition at line 383 of file chan_dahdi.c.

int cur_defaultdpc = -1 [static]

Definition at line 386 of file chan_dahdi.c.

int cur_linkset = -1 [static]

Definition at line 381 of file chan_dahdi.c.

int cur_networkindicator = -1 [static]

Definition at line 385 of file chan_dahdi.c.

int cur_pointcode = -1 [static]

Definition at line 382 of file chan_dahdi.c.

int cur_ss7type = -1 [static]

Definition at line 380 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 13368 of file chan_dahdi.c.

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 12499 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

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

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

Definition at line 3255 of file chan_dahdi.c.

struct ast_cli_entry dahdi_ss7_cli[] [static]

Definition at line 14046 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

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

char defaultozz[64] = "" [static]

Definition at line 228 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 239 of file chan_dahdi.c.

char* events[] [static]

Definition at line 1691 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

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

struct ast_jb_conf global_jbconf [static]

Definition at line 126 of file chan_dahdi.c.

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

int ifcount = 0 [static]

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

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

Definition at line 280 of file chan_dahdi.c.

int mwi_thread_count = 0 [static]

Definition at line 285 of file chan_dahdi.c.

ast_mutex_t mwi_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 mwi_send_thread().

int mwilevel = 512 [static]

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

int mwisend_rpas = 0 [static]

Definition at line 234 of file chan_dahdi.c.

char* name

Definition at line 1715 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1268 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 287 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 241 of file chan_dahdi.c.

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

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

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

Definition at line 236 of file chan_dahdi.c.

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

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

struct dahdi_pvt* round_robin[32]

Definition at line 1225 of file chan_dahdi.c.

Definition at line 281 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 286 of file chan_dahdi.c.

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

Definition at line 283 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

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

Definition at line 487 of file chan_dahdi.c.

const char tdesc[] [static]

Definition at line 160 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 238 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 1269 of file chan_dahdi.c.


Generated on 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1