Fri Nov 12 11:55:11 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 "asterisk/paths.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  mwisend_info
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_CHAN_MAPPING_LOGICAL   1
#define DAHDI_CHAN_MAPPING_PHYSICAL   0
#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_MFCR2   DAHDI_SIG_CAS
#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 TRAILER_MS   5
#define TRANSFER   0

Enumerations

enum  mwisend_states {
  MWI_SEND_NULL = 0, 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 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_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 struct dahdi_pvtduplicate_pseudo (struct dahdi_pvt *src)
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_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_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_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 int mwi_send_init (struct dahdi_pvt *pvt)
static int mwi_send_process_buffer (struct dahdi_pvt *pvt, int num_read)
static int mwi_send_process_event (struct dahdi_pvt *pvt, int event)
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_hangup_cics (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 = "Comedian Mail (Voicemail System)" , .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 = "0901e4e500243c855563a2d78b0c03e4" , .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 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 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 294 of file chan_dahdi.c.

Referenced by dahdi_handle_dtmfup(), and process_dahdi().

#define CALLPROGRESS_FAX_INCOMING   4

Definition at line 293 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_FAX_OUTGOING   2

Definition at line 292 of file chan_dahdi.c.

Referenced by dahdi_new(), and process_dahdi().

#define CALLPROGRESS_PROGRESS   1

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

Referenced by dahdi_callwait().

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

300 ms

Definition at line 402 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 1500 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 1501 of file chan_dahdi.c.

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

#define CHAN_PSEUDO   -2
#define CHANNEL_PSEUDO   -12

Definition at line 207 of file chan_dahdi.c.

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

500 ms

Definition at line 404 of file chan_dahdi.c.

Referenced by send_callerid().

#define CONF_USER_REAL   (1 << 0)

Definition at line 625 of file chan_dahdi.c.

#define CONF_USER_THIRDCALL   (1 << 1)

Definition at line 626 of file chan_dahdi.c.

#define DAHDI_CHAN_MAPPING_LOGICAL   1

Definition at line 339 of file chan_dahdi.c.

Referenced by process_dahdi(), and start_pri().

#define DAHDI_CHAN_MAPPING_PHYSICAL   0

Definition at line 338 of file chan_dahdi.c.

Referenced by dahdi_chan_conf_default(), and process_dahdi().

#define DAHDI_OVERLAPDIAL_BOTH   (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)

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

Referenced by process_dahdi().

#define DAHDI_OVERLAPDIAL_OUTGOING   1

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

Referenced by pri_find_dchan(), and pri_is_up().

#define DCHAN_NOTINALARM   (1 << 1)

Definition at line 280 of file chan_dahdi.c.

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

#define DCHAN_PROVISIONED   (1 << 0)

Definition at line 279 of file chan_dahdi.c.

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

#define DCHAN_UP   (1 << 2)

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

Referenced by dahdi_chan_conf_default().

#define DEFAULT_PRI_DEBUG   0

Definition at line 566 of file chan_dahdi.c.

Referenced by start_pri().

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

8,000 ms

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

Referenced by update_conf().

#define HANGUP   1

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

Referenced by dahdi_indicate(), and ss_thread().

#define LINKSET_FLAG_EXPLICITACM   (1 << 0)

Definition at line 425 of file chan_dahdi.c.

Referenced by process_dahdi(), and ss7_start_call().

#define LINKSTATE_DOWN   (1 << 3)

Definition at line 421 of file chan_dahdi.c.

Referenced by linkset_addsigchan(), and ss7_linkset().

#define LINKSTATE_INALARM   (1 << 0)

Definition at line 418 of file chan_dahdi.c.

Referenced by linkset_addsigchan(), and ss7_linkset().

#define LINKSTATE_STARTING   (1 << 1)

Definition at line 419 of file chan_dahdi.c.

Referenced by ss7_linkset().

#define LINKSTATE_UP   (1 << 2)

Definition at line 420 of file chan_dahdi.c.

Referenced by ss7_linkset().

#define MASK_AVAIL   (1 << 0)

Channel available for PRI use

Definition at line 399 of file chan_dahdi.c.

#define MASK_INUSE   (1 << 1)

Channel currently in use

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

Referenced by process_dahdi().

#define MAX_CHANNELS   672

No more than a DS3 per trunk group

Definition at line 275 of file chan_dahdi.c.

Referenced by mkintf().

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

2000 ms

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

Referenced by dahdi_new(), and ss_thread().

#define NUM_CADENCE_MAX   25

Definition at line 1472 of file chan_dahdi.c.

Referenced by process_dahdi().

#define NUM_DCHANS   4
#define NUM_SPANS   32
#define POLARITY_IDLE   0

Definition at line 584 of file chan_dahdi.c.

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

#define POLARITY_REV   1

Definition at line 585 of file chan_dahdi.c.

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

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

Definition at line 503 of file chan_dahdi.c.

Referenced by pri_dchannel(), and pri_find_principle().

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

Definition at line 505 of file chan_dahdi.c.

Referenced by pri_find_principle().

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

Definition at line 504 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 16092 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 16094 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 397 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 266 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 267 of file chan_dahdi.c.

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

#define SIG_MFCR2   DAHDI_SIG_CAS
#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 159 of file chan_dahdi.c.

Referenced by ss_thread().

#define SS7_NAI_DYNAMIC   -1

Definition at line 423 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 TRAILER_MS   5

Referenced by dahdi_sendtext().

#define TRANSFER   0

Enumeration Type Documentation

Enumerator:
MWI_SEND_NULL 
MWI_SEND_SA 
MWI_SEND_SA_WAIT 
MWI_SEND_PAUSE 
MWI_SEND_SPILL 
MWI_SEND_CLEANUP 
MWI_SEND_DONE 

Definition at line 633 of file chan_dahdi.c.

00633              {
00634    MWI_SEND_NULL = 0,
00635    MWI_SEND_SA,
00636    MWI_SEND_SA_WAIT,
00637    MWI_SEND_PAUSE,
00638    MWI_SEND_SPILL,
00639    MWI_SEND_CLEANUP,
00640    MWI_SEND_DONE,
00641 } mwisend_states;


Function Documentation

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

Definition at line 6601 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, dahdi_pvt::fake_event, ast_channel::fds, dahdi_pvt::flashtime, ast_frame::frametype, LOG_WARNING, ast_frame::mallocd, ast_channel::name, 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().

06602 {
06603    struct dahdi_pvt *p = ast->tech_pvt;
06604    int res;
06605    int usedindex=-1;
06606    int idx;
06607    struct ast_frame *f;
06608 
06609 
06610    idx = dahdi_get_index(ast, p, 1);
06611 
06612    p->subs[idx].f.frametype = AST_FRAME_NULL;
06613    p->subs[idx].f.datalen = 0;
06614    p->subs[idx].f.samples = 0;
06615    p->subs[idx].f.mallocd = 0;
06616    p->subs[idx].f.offset = 0;
06617    p->subs[idx].f.subclass = 0;
06618    p->subs[idx].f.delivery = ast_tv(0,0);
06619    p->subs[idx].f.src = "dahdi_exception";
06620    p->subs[idx].f.data.ptr = NULL;
06621 
06622 
06623    if ((!p->owner) && (!(p->radio || (p->oprmode < 0)))) {
06624       /* If nobody owns us, absorb the event appropriately, otherwise
06625          we loop indefinitely.  This occurs when, during call waiting, the
06626          other end hangs up our channel so that it no longer exists, but we
06627          have neither FLASH'd nor ONHOOK'd to signify our desire to
06628          change to the other channel. */
06629       if (p->fake_event) {
06630          res = p->fake_event;
06631          p->fake_event = 0;
06632       } else
06633          res = dahdi_get_event(p->subs[SUB_REAL].dfd);
06634       /* Switch to real if there is one and this isn't something really silly... */
06635       if ((res != DAHDI_EVENT_RINGEROFF) && (res != DAHDI_EVENT_RINGERON) &&
06636          (res != DAHDI_EVENT_HOOKCOMPLETE)) {
06637          ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
06638          p->owner = p->subs[SUB_REAL].owner;
06639          if (p->owner && ast_bridged_channel(p->owner))
06640             ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06641          p->subs[SUB_REAL].needunhold = 1;
06642       }
06643       switch (res) {
06644       case DAHDI_EVENT_ONHOOK:
06645          dahdi_disable_ec(p);
06646          if (p->owner) {
06647             ast_verb(3, "Channel %s still has call, ringing phone\n", p->owner->name);
06648             dahdi_ring_phone(p);
06649             p->callwaitingrepeat = 0;
06650             p->cidcwexpire = 0;
06651          } else
06652             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06653          update_conf(p);
06654          break;
06655       case DAHDI_EVENT_RINGOFFHOOK:
06656          dahdi_enable_ec(p);
06657          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
06658          if (p->owner && (p->owner->_state == AST_STATE_RINGING)) {
06659             p->subs[SUB_REAL].needanswer = 1;
06660             p->dialing = 0;
06661          }
06662          break;
06663       case DAHDI_EVENT_HOOKCOMPLETE:
06664       case DAHDI_EVENT_RINGERON:
06665       case DAHDI_EVENT_RINGEROFF:
06666          /* Do nothing */
06667          break;
06668       case DAHDI_EVENT_WINKFLASH:
06669          p->flashtime = ast_tvnow();
06670          if (p->owner) {
06671             ast_verb(3, "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
06672             if (p->owner->_state != AST_STATE_UP) {
06673                /* Answer if necessary */
06674                usedindex = dahdi_get_index(p->owner, p, 0);
06675                if (usedindex > -1) {
06676                   p->subs[usedindex].needanswer = 1;
06677                }
06678                ast_setstate(p->owner, AST_STATE_UP);
06679             }
06680             p->callwaitingrepeat = 0;
06681             p->cidcwexpire = 0;
06682             if (ast_bridged_channel(p->owner))
06683                ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06684             p->subs[SUB_REAL].needunhold = 1;
06685          } else
06686             ast_log(LOG_WARNING, "Absorbed on hook, but nobody is left!?!?\n");
06687          update_conf(p);
06688          break;
06689       default:
06690          ast_log(LOG_WARNING, "Don't know how to absorb event %s\n", event2str(res));
06691       }
06692       f = &p->subs[idx].f;
06693       return f;
06694    }
06695    if (!(p->radio || (p->oprmode < 0)))
06696       ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
06697    /* If it's not us, return NULL immediately */
06698    if (ast != p->owner) {
06699       ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
06700       f = &p->subs[idx].f;
06701       return f;
06702    }
06703    f = dahdi_handle_event(ast);
06704    return f;
06705 }

static void __reg_module ( void   )  [static]

Definition at line 17500 of file chan_dahdi.c.

static int __unload_module ( void   )  [static]

Definition at line 15849 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_DCHANS, NUM_SPANS, dahdi_pvt::owner, and pris.

Referenced by load_module(), and unload_module().

15850 {
15851    struct dahdi_pvt *p;
15852 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15853    int i, j;
15854 #endif
15855 
15856 #ifdef HAVE_PRI
15857    for (i = 0; i < NUM_SPANS; i++) {
15858       if (pris[i].master != AST_PTHREADT_NULL)
15859          pthread_cancel(pris[i].master);
15860    }
15861    ast_cli_unregister_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
15862    ast_unregister_application(dahdi_send_keypad_facility_app);
15863 #ifdef HAVE_PRI_PROG_W_CAUSE
15864    ast_unregister_application(dahdi_send_callrerouting_facility_app);
15865 #endif
15866 #endif
15867 #if defined(HAVE_SS7)
15868    for (i = 0; i < NUM_SPANS; i++) {
15869       if (linksets[i].master != AST_PTHREADT_NULL)
15870          pthread_cancel(linksets[i].master);
15871       }
15872    ast_cli_unregister_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
15873 #endif
15874 #if defined(HAVE_OPENR2)
15875    dahdi_r2_destroy_links();
15876    ast_cli_unregister_multiple(dahdi_mfcr2_cli, ARRAY_LEN(dahdi_mfcr2_cli));
15877    ast_unregister_application(dahdi_accept_r2_call_app);
15878 #endif
15879 
15880    ast_cli_unregister_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
15881    ast_manager_unregister( "DAHDIDialOffhook" );
15882    ast_manager_unregister( "DAHDIHangup" );
15883    ast_manager_unregister( "DAHDITransfer" );
15884    ast_manager_unregister( "DAHDIDNDoff" );
15885    ast_manager_unregister( "DAHDIDNDon" );
15886    ast_manager_unregister("DAHDIShowChannels");
15887    ast_manager_unregister("DAHDIRestart");
15888    ast_channel_unregister(&dahdi_tech);
15889    ast_mutex_lock(&iflock);
15890    /* Hangup all interfaces if they have an owner */
15891    p = iflist;
15892    while (p) {
15893       if (p->owner)
15894          ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
15895       p = p->next;
15896    }
15897    ast_mutex_unlock(&iflock);
15898    ast_mutex_lock(&monlock);
15899    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
15900       pthread_cancel(monitor_thread);
15901       pthread_kill(monitor_thread, SIGURG);
15902       pthread_join(monitor_thread, NULL);
15903    }
15904    monitor_thread = AST_PTHREADT_STOP;
15905    ast_mutex_unlock(&monlock);
15906 
15907    destroy_all_channels();
15908 
15909 #if defined(HAVE_PRI)
15910    for (i = 0; i < NUM_SPANS; i++) {
15911       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL))
15912          pthread_join(pris[i].master, NULL);
15913       for (j = 0; j < NUM_DCHANS; j++) {
15914          dahdi_close_pri_fd(&(pris[i]), j);
15915       }
15916    }
15917 #endif
15918 
15919 #if defined(HAVE_SS7)
15920    for (i = 0; i < NUM_SPANS; i++) {
15921       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL))
15922          pthread_join(linksets[i].master, NULL);
15923       for (j = 0; j < NUM_DCHANS; j++) {
15924          dahdi_close_ss7_fd(&(linksets[i]), j);
15925       }
15926    }
15927 #endif
15928    ast_cond_destroy(&ss_thread_complete);
15929    return 0;
15930 }

static void __unreg_module ( void   )  [static]

Definition at line 17500 of file chan_dahdi.c.

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

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

15290 {
15291    struct dahdi_pvt *p = NULL;
15292    const char *channel = astman_get_header(m, "DAHDIChannel");
15293    const char *number = astman_get_header(m, "Number");
15294    int i;
15295 
15296    if (ast_strlen_zero(channel)) {
15297       astman_send_error(s, m, "No channel specified");
15298       return 0;
15299    }
15300    if (ast_strlen_zero(number)) {
15301       astman_send_error(s, m, "No number specified");
15302       return 0;
15303    }
15304    p = find_channel(atoi(channel));
15305    if (!p) {
15306       astman_send_error(s, m, "No such channel");
15307       return 0;
15308    }
15309    if (!p->owner) {
15310       astman_send_error(s, m, "Channel does not have it's owner");
15311       return 0;
15312    }
15313    for (i = 0; i < strlen(number); i++) {
15314       struct ast_frame f = { AST_FRAME_DTMF, number[i] };
15315       dahdi_queue_frame(p, &f, NULL);
15316    }
15317    astman_send_ack(s, m, "DAHDIDialOffhook");
15318    return 0;
15319 }

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

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

15233 {
15234    struct dahdi_pvt *p = NULL;
15235    const char *channel = astman_get_header(m, "DAHDIChannel");
15236 
15237    if (ast_strlen_zero(channel)) {
15238       astman_send_error(s, m, "No channel specified");
15239       return 0;
15240    }
15241    p = find_channel(atoi(channel));
15242    if (!p) {
15243       astman_send_error(s, m, "No such channel");
15244       return 0;
15245    }
15246    p->dnd = 0;
15247    astman_send_ack(s, m, "DND Disabled");
15248    return 0;
15249 }

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

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

15214 {
15215    struct dahdi_pvt *p = NULL;
15216    const char *channel = astman_get_header(m, "DAHDIChannel");
15217 
15218    if (ast_strlen_zero(channel)) {
15219       astman_send_error(s, m, "No channel specified");
15220       return 0;
15221    }
15222    p = find_channel(atoi(channel));
15223    if (!p) {
15224       astman_send_error(s, m, "No such channel");
15225       return 0;
15226    }
15227    p->dnd = 1;
15228    astman_send_ack(s, m, "DND Enabled");
15229    return 0;
15230 }

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

Definition at line 14475 of file chan_dahdi.c.

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

Referenced by load_module().

14476 {
14477    if (dahdi_restart() != 0) {
14478       astman_send_error(s, m, "Failed rereading DAHDI configuration");
14479       return 1;
14480    }
14481    astman_send_ack(s, m, "DAHDIRestart: Success");
14482    return 0;
14483 }

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

Definition at line 15321 of file chan_dahdi.c.

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

Referenced by load_module().

15322 {
15323    struct dahdi_pvt *tmp = NULL;
15324    const char *id = astman_get_header(m, "ActionID");
15325    const char *dahdichannel = astman_get_header(m, "DAHDIChannel");
15326    char idText[256] = "";
15327    int channels = 0;
15328    int dahdichanquery = -1;
15329    if (!ast_strlen_zero(dahdichannel)) {
15330       dahdichanquery = atoi(dahdichannel);
15331    }
15332 
15333    astman_send_ack(s, m, "DAHDI channel status will follow");
15334    if (!ast_strlen_zero(id))
15335       snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id);
15336 
15337    ast_mutex_lock(&iflock);
15338 
15339    tmp = iflist;
15340    while (tmp) {
15341       if (tmp->channel > 0) {
15342          int alm = get_alarms(tmp);
15343 
15344          /* If a specific channel is queried for, only deliver status for that channel */
15345          if (dahdichanquery > 0 && tmp->channel != dahdichanquery)
15346             continue;
15347 
15348          channels++;
15349          if (tmp->owner) {
15350             /* Add data if we have a current call */
15351             astman_append(s,
15352                "Event: DAHDIShowChannels\r\n"
15353                "DAHDIChannel: %d\r\n"
15354                "Channel: %s\r\n"
15355                "Uniqueid: %s\r\n"
15356                "AccountCode: %s\r\n"
15357                "Signalling: %s\r\n"
15358                "SignallingCode: %d\r\n"
15359                "Context: %s\r\n"
15360                "DND: %s\r\n"
15361                "Alarm: %s\r\n"
15362                "%s"
15363                "\r\n",
15364                tmp->channel,
15365                tmp->owner->name,
15366                tmp->owner->uniqueid,
15367                tmp->owner->accountcode,
15368                sig2str(tmp->sig),
15369                tmp->sig,
15370                tmp->context,
15371                tmp->dnd ? "Enabled" : "Disabled",
15372                alarm2str(alm), idText);
15373          } else {
15374             astman_append(s,
15375                "Event: DAHDIShowChannels\r\n"
15376                "DAHDIChannel: %d\r\n"
15377                "Signalling: %s\r\n"
15378                "SignallingCode: %d\r\n"
15379                "Context: %s\r\n"
15380                "DND: %s\r\n"
15381                "Alarm: %s\r\n"
15382                "%s"
15383                "\r\n",
15384                tmp->channel, sig2str(tmp->sig), tmp->sig,
15385                tmp->context,
15386                tmp->dnd ? "Enabled" : "Disabled",
15387                alarm2str(alm), idText);
15388          }
15389       }
15390 
15391       tmp = tmp->next;
15392    }
15393 
15394    ast_mutex_unlock(&iflock);
15395 
15396    astman_append(s,
15397       "Event: DAHDIShowChannelsComplete\r\n"
15398       "%s"
15399       "Items: %d\r\n"
15400       "\r\n",
15401       idText,
15402       channels);
15403    return 0;
15404 }

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

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

15252 {
15253    struct dahdi_pvt *p = NULL;
15254    const char *channel = astman_get_header(m, "DAHDIChannel");
15255 
15256    if (ast_strlen_zero(channel)) {
15257       astman_send_error(s, m, "No channel specified");
15258       return 0;
15259    }
15260    p = find_channel(atoi(channel));
15261    if (!p) {
15262       astman_send_error(s, m, "No such channel");
15263       return 0;
15264    }
15265    dahdi_fake_event(p,TRANSFER);
15266    astman_send_ack(s, m, "DAHDITransfer");
15267    return 0;
15268 }

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

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

15271 {
15272    struct dahdi_pvt *p = NULL;
15273    const char *channel = astman_get_header(m, "DAHDIChannel");
15274 
15275    if (ast_strlen_zero(channel)) {
15276       astman_send_error(s, m, "No channel specified");
15277       return 0;
15278    }
15279    p = find_channel(atoi(channel));
15280    if (!p) {
15281       astman_send_error(s, m, "No such channel");
15282       return 0;
15283    }
15284    dahdi_fake_event(p,HANGUP);
15285    astman_send_ack(s, m, "DAHDIHangup");
15286    return 0;
15287 }

static char* alarm2str ( int  alm  )  [static]

Definition at line 2379 of file chan_dahdi.c.

References alarms, and ARRAY_LEN.

Referenced by action_dahdishowchannels(), and handle_alarms().

02380 {
02381    int x;
02382    for (x = 0; x < ARRAY_LEN(alarms); x++) {
02383       if (alarms[x].alarm & alm)
02384          return alarms[x].name;
02385    }
02386    return alm ? "Unknown Alarm" : "No Alarm";
02387 }

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

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

02176 {
02177    struct dahdi_bufferinfo bi;
02178    int res;
02179    if (p->subs[x].dfd >= 0) {
02180       ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
02181       return -1;
02182    }
02183 
02184    p->subs[x].dfd = dahdi_open("/dev/dahdi/pseudo");
02185    if (p->subs[x].dfd <= -1) {
02186       ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
02187       return -1;
02188    }
02189 
02190    res = ioctl(p->subs[x].dfd, DAHDI_GET_BUFINFO, &bi);
02191    if (!res) {
02192       bi.txbufpolicy = p->buf_policy;
02193       bi.rxbufpolicy = p->buf_policy;
02194       bi.numbufs = p->buf_no;
02195       res = ioctl(p->subs[x].dfd, DAHDI_SET_BUFINFO, &bi);
02196       if (res < 0) {
02197          ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
02198       }
02199    } else
02200       ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
02201 
02202    if (ioctl(p->subs[x].dfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
02203       ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].dfd, strerror(errno));
02204       dahdi_close_sub(p, x);
02205       p->subs[x].dfd = -1;
02206       return -1;
02207    }
02208    ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].dfd, p->subs[x].chan);
02209    return 0;
02210 }

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

12363 {
12364    if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
12365       snprintf(buf, size, "%s", number);
12366       return;
12367    }
12368    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
12369       if (size) {
12370          *buf = '\0';
12371       }
12372       return;
12373    }
12374    switch (plan) {
12375    case PRI_INTERNATIONAL_ISDN:     /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
12376       snprintf(buf, size, "%s%s", pri->internationalprefix, number);
12377       break;
12378    case PRI_NATIONAL_ISDN:       /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
12379       snprintf(buf, size, "%s%s", pri->nationalprefix, number);
12380       break;
12381    case PRI_LOCAL_ISDN:       /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
12382       snprintf(buf, size, "%s%s", pri->localprefix, number);
12383       break;
12384    case PRI_PRIVATE:       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
12385       snprintf(buf, size, "%s%s", pri->privateprefix, number);
12386       break;
12387    case PRI_UNKNOWN:       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
12388       snprintf(buf, size, "%s%s", pri->unknownprefix, number);
12389       break;
12390    default:          /* other Q.931 dialplan => don't twiddle with callingnum */
12391       snprintf(buf, size, "%s", number);
12392       break;
12393    }
12394 }

static int attempt_transfer ( struct dahdi_pvt p  )  [static]

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

Referenced by dahdi_handle_event().

05503 {
05504    /* In order to transfer, we need at least one of the channels to
05505       actually be in a call bridge.  We can't conference two applications
05506       together (but then, why would we want to?) */
05507    if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
05508       /* The three-way person we're about to transfer to could still be in MOH, so
05509          stop if now if appropriate */
05510       if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner))
05511          ast_queue_control(p->subs[SUB_THREEWAY].owner, AST_CONTROL_UNHOLD);
05512       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RINGING) {
05513          ast_indicate(ast_bridged_channel(p->subs[SUB_REAL].owner), AST_CONTROL_RINGING);
05514       }
05515       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
05516          tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
05517       }
05518        if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
05519          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05520                ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
05521          return -1;
05522       }
05523       /* Orphan the channel after releasing the lock */
05524       ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05525       unalloc_sub(p, SUB_THREEWAY);
05526    } else if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
05527       ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
05528       if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RINGING) {
05529          ast_indicate(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), AST_CONTROL_RINGING);
05530       }
05531       if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
05532          tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05533       }
05534       if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
05535          ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
05536                ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
05537          return -1;
05538       }
05539       /* Three-way is now the REAL */
05540       swap_subs(p, SUB_THREEWAY, SUB_REAL);
05541       ast_channel_unlock(p->subs[SUB_REAL].owner);
05542       unalloc_sub(p, SUB_THREEWAY);
05543       /* Tell the caller not to hangup */
05544       return 1;
05545    } else {
05546       ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
05547          p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
05548       p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05549       return -1;
05550    }
05551    return 0;
05552 }

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

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

10641 {
10642    int res;
10643    struct dahdi_params par;
10644 
10645    /* First, check group matching */
10646    if (groupmatch) {
10647       if ((p->group & groupmatch) != groupmatch)
10648          return 0;
10649       *groupmatched = 1;
10650    }
10651    /* Check to see if we have a channel match */
10652    if (channelmatch != -1) {
10653       if (p->channel != channelmatch)
10654          return 0;
10655       *channelmatched = 1;
10656    }
10657    /* We're at least busy at this point */
10658    if (busy) {
10659       if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
10660          *busy = 1;
10661    }
10662    /* If do not disturb, definitely not */
10663    if (p->dnd)
10664       return 0;
10665    /* If guard time, definitely not */
10666    if (p->guardtime && (time(NULL) < p->guardtime))
10667       return 0;
10668 
10669    if (p->locallyblocked || p->remotelyblocked)
10670       return 0;
10671 
10672    /* If no owner definitely available */
10673    if (!p->owner) {
10674 #ifdef HAVE_PRI
10675       /* Trust PRI */
10676       if (p->pri) {
10677          if (p->resetting || p->call)
10678             return 0;
10679          else
10680             return 1;
10681       }
10682 #endif
10683 #ifdef HAVE_SS7
10684       /* Trust SS7 */
10685       if (p->ss7) {
10686          if (p->ss7call)
10687             return 0;
10688          else
10689             return 1;
10690       }
10691 #endif
10692 #ifdef HAVE_OPENR2
10693       /* Trust MFC/R2 */
10694       if (p->mfcr2) {
10695          if (p->mfcr2call)
10696             return 0;
10697          else
10698             return 1;
10699       }
10700 #endif
10701       if (!(p->radio || (p->oprmode < 0)))
10702       {
10703          if (!p->sig || (p->sig == SIG_FXSLS))
10704             return 1;
10705          /* Check hook state */
10706          if (p->subs[SUB_REAL].dfd > -1) {
10707             memset(&par, 0, sizeof(par));
10708             res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
10709          } else {
10710             /* Assume not off hook on CVRS */
10711             res = 0;
10712             par.rxisoffhook = 0;
10713          }
10714          if (res) {
10715             ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
10716          } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
10717             /* When "onhook" that means no battery on the line, and thus
10718               it is out of service..., if it's on a TDM card... If it's a channel
10719               bank, there is no telling... */
10720             if (par.rxbits > -1)
10721                return 1;
10722             if (par.rxisoffhook)
10723                return 1;
10724             else
10725                return 0;
10726          } else if (par.rxisoffhook) {
10727             ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
10728             /* Not available when the other end is off hook */
10729 #ifdef DAHDI_CHECK_HOOKSTATE
10730             return 0;
10731 #else
10732             return 1;
10733 #endif
10734          }
10735       }
10736       return 1;
10737    }
10738 
10739    /* If it's not an FXO, forget about call wait */
10740    if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
10741       return 0;
10742 
10743    if (!p->callwaiting) {
10744       /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
10745       return 0;
10746    }
10747 
10748    if (p->subs[SUB_CALLWAIT].dfd > -1) {
10749       /* If there is already a call waiting call, then we can't take a second one */
10750       return 0;
10751    }
10752 
10753    if ((p->owner->_state != AST_STATE_UP) &&
10754       ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
10755       /* If the current call is not up, then don't allow the call */
10756       return 0;
10757    }
10758    if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
10759       /* Can't take a call wait when the three way calling hasn't been merged yet. */
10760       return 0;
10761    }
10762    /* We're cool */
10763    return 1;
10764 }

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

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

Referenced by process_dahdi().

15949 {
15950    char *c, *chan;
15951    int x, start, finish;
15952    struct dahdi_pvt *tmp;
15953 #ifdef HAVE_PRI
15954    struct dahdi_pri *pri;
15955    int trunkgroup, y;
15956 #endif
15957 
15958    if ((reload == 0) && (conf->chan.sig < 0) && !conf->is_sig_auto) {
15959       ast_log(LOG_ERROR, "Signalling must be specified before any channels are.\n");
15960       return -1;
15961    }
15962 
15963    c = ast_strdupa(value);
15964 
15965 #ifdef HAVE_PRI
15966    pri = NULL;
15967    if (iscrv) {
15968       if (sscanf(c, "%30d:%n", &trunkgroup, &y) != 1) {
15969          ast_log(LOG_WARNING, "CRV must begin with trunkgroup followed by a colon at line %d.\n", lineno);
15970          return -1;
15971       }
15972       if (trunkgroup < 1) {
15973          ast_log(LOG_WARNING, "CRV trunk group must be a positive number at line %d.\n", lineno);
15974          return -1;
15975       }
15976       c += y;
15977       for (y = 0; y < NUM_SPANS; y++) {
15978          if (pris[y].trunkgroup == trunkgroup) {
15979             pri = pris + y;
15980             break;
15981          }
15982       }
15983       if (!pri) {
15984          ast_log(LOG_WARNING, "No such trunk group %d at CRV declaration at line %d.\n", trunkgroup, lineno);
15985          return -1;
15986       }
15987    }
15988 #endif
15989 
15990    while ((chan = strsep(&c, ","))) {
15991       if (sscanf(chan, "%30d-%30d", &start, &finish) == 2) {
15992          /* Range */
15993       } else if (sscanf(chan, "%30d", &start)) {
15994          /* Just one */
15995          finish = start;
15996       } else if (!strcasecmp(chan, "pseudo")) {
15997          finish = start = CHAN_PSEUDO;
15998          if (found_pseudo)
15999             *found_pseudo = 1;
16000       } else {
16001          ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
16002          return -1;
16003       }
16004       if (finish < start) {
16005          ast_log(LOG_WARNING, "Sillyness: %d < %d\n", start, finish);
16006          x = finish;
16007          finish = start;
16008          start = x;
16009       }
16010 
16011       for (x = start; x <= finish; x++) {
16012 #ifdef HAVE_PRI
16013          tmp = mkintf(x, conf, pri, reload);
16014 #else
16015          tmp = mkintf(x, conf, NULL, reload);
16016 #endif
16017 
16018          if (tmp) {
16019 #ifdef HAVE_PRI
16020             if (pri)
16021                ast_verb(3, "%s CRV %d:%d, %s signalling\n", reload ? "Reconfigured" : "Registered", trunkgroup, x, sig2str(tmp->sig));
16022             else
16023 #endif
16024                ast_verb(3, "%s channel %d, %s signalling\n", reload ? "Reconfigured" : "Registered", x, sig2str(tmp->sig));
16025          } else {
16026             ast_log(LOG_ERROR, "Unable to %s channel '%s'\n",
16027                (reload == 1) ? "reconfigure" : "register", value);
16028             return -1;
16029          }
16030       }
16031    }
16032 
16033    return 0;
16034 }

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

Definition at line 13770 of file chan_dahdi.c.

References DCHAN_NOTINALARM, DCHAN_PROVISIONED, and DCHAN_UP.

Referenced by handle_pri_show_span(), and handle_pri_show_spans().

13771 {
13772    if (!s || len < 1) {
13773       return;
13774    }
13775    s[0] = '\0';
13776    if (status & DCHAN_PROVISIONED)
13777       strncat(s, "Provisioned, ", len - strlen(s) - 1);
13778    if (!(status & DCHAN_NOTINALARM))
13779       strncat(s, "In Alarm, ", len - strlen(s) - 1);
13780    if (status & DCHAN_UP)
13781       strncat(s, "Up", len - strlen(s) - 1);
13782    else
13783       strncat(s, "Down", len - strlen(s) - 1);
13784    if (active)
13785       strncat(s, ", Active", len - strlen(s) - 1);
13786    else
13787       strncat(s, ", Standby", len - strlen(s) - 1);
13788    s[len - 1] = '\0';
13789 }

static int bump_gains ( struct dahdi_pvt p  )  [static]

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

02837 {
02838    int res;
02839 
02840    /* Bump receive gain by value stored in cid_rxgain */
02841    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
02842    if (res) {
02843       ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
02844       return -1;
02845    }
02846 
02847    return 0;
02848 }

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

Definition at line 8911 of file chan_dahdi.c.

References AST_ALAW, AST_FORMAT_ULAW, and AST_MULAW.

Referenced by do_monitor(), and mwi_thread().

08912 {
08913    int x;
08914    int sum = 0;
08915 
08916    if (!len)
08917       return 0;
08918 
08919    for (x = 0; x < len; x++)
08920       sum += abs(law == AST_FORMAT_ULAW ? AST_MULAW(buf[x]) : AST_ALAW(buf[x]));
08921 
08922    return sum / len;
08923 }

static int check_for_conference ( struct dahdi_pvt p  )  [static]

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

05555 {
05556    struct dahdi_confinfo ci;
05557    /* Fine if we already have a master, etc */
05558    if (p->master || (p->confno > -1))
05559       return 0;
05560    memset(&ci, 0, sizeof(ci));
05561    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
05562       ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
05563       return 0;
05564    }
05565    /* If we have no master and don't have a confno, then
05566       if we're in a conference, it's probably a MeetMe room or
05567       some such, so don't let us 3-way out! */
05568    if ((p->subs[SUB_REAL].curconf.confno != ci.confno) || (p->subs[SUB_REAL].curconf.confmode != ci.confmode)) {
05569       ast_verb(3, "Avoiding 3-way call when in an external conference\n");
05570       return 1;
05571    }
05572    return 0;
05573 }

static unsigned char cid_pres2ss7pres ( int  cid_pres  )  [static]

Definition at line 3088 of file chan_dahdi.c.

Referenced by dahdi_call().

03089 {
03090     return (cid_pres >> 5) & 0x03;
03091 }

static unsigned char cid_pres2ss7screen ( int  cid_pres  )  [static]

Definition at line 3095 of file chan_dahdi.c.

Referenced by dahdi_call().

03096 {
03097    return cid_pres & 0x03;
03098 }

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

Definition at line 13662 of file chan_dahdi.c.

References complete_span_helper().

Referenced by handle_pri_debug(), and handle_pri_show_span().

13663 {
13664    return complete_span_helper(line,word,pos,state,3);
13665 }

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

Definition at line 13641 of file chan_dahdi.c.

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

Referenced by complete_span_4().

13642 {
13643    int which, span;
13644    char *ret = NULL;
13645 
13646    if (pos != rpos)
13647       return ret;
13648 
13649    for (which = span = 0; span < NUM_SPANS; span++) {
13650       if (pris[span].pri && ++which > state) {
13651          if (asprintf(&ret, "%d", span + 1) < 0) { /* user indexes start from 1 */
13652             ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
13653          }
13654          break;
13655       }
13656    }
13657    return ret;
13658 }

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

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

02479 {
02480    /* If the conference already exists, and we're already in it
02481       don't bother doing anything */
02482    struct dahdi_confinfo zi;
02483 
02484    memset(&zi, 0, sizeof(zi));
02485    zi.chan = 0;
02486 
02487    if (slavechannel > 0) {
02488       /* If we have only one slave, do a digital mon */
02489       zi.confmode = DAHDI_CONF_DIGITALMON;
02490       zi.confno = slavechannel;
02491    } else {
02492       if (!idx) {
02493          /* Real-side and pseudo-side both participate in conference */
02494          zi.confmode = DAHDI_CONF_REALANDPSEUDO | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER |
02495             DAHDI_CONF_PSEUDO_TALKER | DAHDI_CONF_PSEUDO_LISTENER;
02496       } else
02497          zi.confmode = DAHDI_CONF_CONF | DAHDI_CONF_TALKER | DAHDI_CONF_LISTENER;
02498       zi.confno = p->confno;
02499    }
02500    if ((zi.confno == c->curconf.confno) && (zi.confmode == c->curconf.confmode))
02501       return 0;
02502    if (c->dfd < 0)
02503       return 0;
02504    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02505       ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->dfd, zi.confmode, zi.confno, strerror(errno));
02506       return -1;
02507    }
02508    if (slavechannel < 1) {
02509       p->confno = zi.confno;
02510    }
02511    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02512    ast_debug(1, "Added %d to conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02513    return 0;
02514 }

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

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

02528 {
02529    struct dahdi_confinfo zi;
02530    if (/* Can't delete if there's no dfd */
02531       (c->dfd < 0) ||
02532       /* Don't delete from the conference if it's not our conference */
02533       !isourconf(p, c)
02534       /* Don't delete if we don't think it's conferenced at all (implied) */
02535       ) return 0;
02536    memset(&zi, 0, sizeof(zi));
02537    if (ioctl(c->dfd, DAHDI_SETCONF, &zi)) {
02538       ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->dfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
02539       return -1;
02540    }
02541    ast_debug(1, "Removed %d from conference %d/%d\n", c->dfd, c->curconf.confmode, c->curconf.confno);
02542    memcpy(&c->curconf, &zi, sizeof(c->curconf));
02543    return 0;
02544 }

static int dahdi_answer ( struct ast_channel ast  )  [static]

Definition at line 4718 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_DEBUG, LOG_WARNING, ast_channel::name, dahdi_pvt::oprmode, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::polaritydelaytv, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::radio, dahdi_pvt::ringt, dahdi_pvt::sig, SIG_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_MFCR2, 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.

04719 {
04720    struct dahdi_pvt *p = ast->tech_pvt;
04721    int res = 0;
04722    int idx;
04723    int oldstate = ast->_state;
04724    ast_setstate(ast, AST_STATE_UP);
04725    ast_mutex_lock(&p->lock);
04726    idx = dahdi_get_index(ast, p, 0);
04727    if (idx < 0)
04728       idx = SUB_REAL;
04729    /* nothing to do if a radio channel */
04730    if ((p->radio || (p->oprmode < 0))) {
04731       ast_mutex_unlock(&p->lock);
04732       return 0;
04733    }
04734    switch (p->sig) {
04735    case SIG_FXSLS:
04736    case SIG_FXSGS:
04737    case SIG_FXSKS:
04738       p->ringt = 0;
04739       /* Fall through */
04740    case SIG_EM:
04741    case SIG_EM_E1:
04742    case SIG_EMWINK:
04743    case SIG_FEATD:
04744    case SIG_FEATDMF:
04745    case SIG_FEATDMF_TA:
04746    case SIG_E911:
04747    case SIG_FGC_CAMA:
04748    case SIG_FGC_CAMAMF:
04749    case SIG_FEATB:
04750    case SIG_SF:
04751    case SIG_SFWINK:
04752    case SIG_SF_FEATD:
04753    case SIG_SF_FEATDMF:
04754    case SIG_SF_FEATB:
04755    case SIG_FXOLS:
04756    case SIG_FXOGS:
04757    case SIG_FXOKS:
04758       /* Pick up the line */
04759       ast_debug(1, "Took %s off hook\n", ast->name);
04760       if (p->hanguponpolarityswitch) {
04761          p->polaritydelaytv = ast_tvnow();
04762       }
04763       res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
04764       tone_zone_play_tone(p->subs[idx].dfd, -1);
04765       p->dialing = 0;
04766       if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
04767          if (oldstate == AST_STATE_RINGING) {
04768             ast_debug(1, "Finally swapping real and threeway\n");
04769             tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
04770             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04771             p->owner = p->subs[SUB_REAL].owner;
04772          }
04773       }
04774       if (p->sig & __DAHDI_SIG_FXS) {
04775          dahdi_enable_ec(p);
04776          dahdi_train_ec(p);
04777       }
04778       break;
04779 #ifdef HAVE_PRI
04780    case SIG_BRI:
04781    case SIG_BRI_PTMP:
04782    case SIG_PRI:
04783       /* Send a pri acknowledge */
04784       if (!pri_grab(p, p->pri)) {
04785          p->proceeding = 1;
04786          p->dialing = 0;
04787          res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
04788          pri_rel(p->pri);
04789       } else {
04790          ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04791          res = -1;
04792       }
04793       break;
04794 #endif
04795 #ifdef HAVE_SS7
04796    case SIG_SS7:
04797       if (!ss7_grab(p, p->ss7)) {
04798          p->proceeding = 1;
04799          res = isup_anm(p->ss7->ss7, p->ss7call);
04800          ss7_rel(p->ss7);
04801       } else {
04802          ast_log(LOG_WARNING, "Unable to grab SS7 on span %d\n", p->span);
04803          res = -1;
04804       }
04805       break;
04806 #endif
04807 #ifdef HAVE_OPENR2
04808    case SIG_MFCR2:
04809       if (!p->mfcr2_call_accepted) {
04810          /* The call was not accepted on offer nor the user, so it must be accepted now before answering,
04811             openr2_chan_answer_call will be called when the callback on_call_accepted is executed */
04812          p->mfcr2_answer_pending = 1;
04813          if (p->mfcr2_charge_calls) {
04814             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with charge before answering on chan %d\n", p->channel);
04815             openr2_chan_accept_call(p->r2chan, OR2_CALL_WITH_CHARGE);
04816          } else {
04817             ast_log(LOG_DEBUG, "Accepting MFC/R2 call with no charge before answering on chan %d\n", p->channel);
04818             openr2_chan_accept_call(p->r2chan, OR2_CALL_NO_CHARGE);
04819          }
04820       } else {
04821          ast_log(LOG_DEBUG, "Answering MFC/R2 call on chan %d\n", p->channel);
04822          dahdi_r2_answer(p);
04823       }
04824       break;
04825 #endif
04826    case 0:
04827       ast_mutex_unlock(&p->lock);
04828       return 0;
04829    default:
04830       ast_log(LOG_WARNING, "Don't know how to answer signalling %d (channel %d)\n", p->sig, p->channel);
04831       res = -1;
04832    }
04833    ast_mutex_unlock(&p->lock);
04834    return res;
04835 }

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 5156 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(), ast_channel::fds, ast_frame::frametype, dahdi_pvt::inconference, dahdi_subchannel::inthreeway, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, master, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pulsedial, dahdi_pvt::sig, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, ast_channel::tech_pvt, dahdi_pvt::transfer, and update_conf().

05157 {
05158    struct ast_channel *who;
05159    struct dahdi_pvt *p0, *p1, *op0, *op1;
05160    struct dahdi_pvt *master = NULL, *slave = NULL;
05161    struct ast_frame *f;
05162    int inconf = 0;
05163    int nothingok = 1;
05164    int ofd0, ofd1;
05165    int oi0, oi1, i0 = -1, i1 = -1, t0, t1;
05166    int os0 = -1, os1 = -1;
05167    int priority = 0;
05168    struct ast_channel *oc0, *oc1;
05169    enum ast_bridge_result res;
05170 
05171 #ifdef PRI_2BCT
05172    int triedtopribridge = 0;
05173    q931_call *q931c0 = NULL, *q931c1 = NULL;
05174 #endif
05175 
05176    /* For now, don't attempt to native bridge if either channel needs DTMF detection.
05177       There is code below to handle it properly until DTMF is actually seen,
05178       but due to currently unresolved issues it's ignored...
05179    */
05180 
05181    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
05182       return AST_BRIDGE_FAILED_NOWARN;
05183 
05184    ast_channel_lock(c0);
05185    while (ast_channel_trylock(c1)) {
05186       CHANNEL_DEADLOCK_AVOIDANCE(c0);
05187    }
05188 
05189    p0 = c0->tech_pvt;
05190    p1 = c1->tech_pvt;
05191    /* cant do pseudo-channels here */
05192    if (!p0 || (!p0->sig) || !p1 || (!p1->sig)) {
05193       ast_channel_unlock(c0);
05194       ast_channel_unlock(c1);
05195       return AST_BRIDGE_FAILED_NOWARN;
05196    }
05197 
05198    oi0 = dahdi_get_index(c0, p0, 0);
05199    oi1 = dahdi_get_index(c1, p1, 0);
05200    if ((oi0 < 0) || (oi1 < 0)) {
05201       ast_channel_unlock(c0);
05202       ast_channel_unlock(c1);
05203       return AST_BRIDGE_FAILED;
05204    }
05205 
05206    op0 = p0 = c0->tech_pvt;
05207    op1 = p1 = c1->tech_pvt;
05208    ofd0 = c0->fds[0];
05209    ofd1 = c1->fds[0];
05210    oc0 = p0->owner;
05211    oc1 = p1->owner;
05212 
05213    if (ast_mutex_trylock(&p0->lock)) {
05214       /* Don't block, due to potential for deadlock */
05215       ast_channel_unlock(c0);
05216       ast_channel_unlock(c1);
05217       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05218       return AST_BRIDGE_RETRY;
05219    }
05220    if (ast_mutex_trylock(&p1->lock)) {
05221       /* Don't block, due to potential for deadlock */
05222       ast_mutex_unlock(&p0->lock);
05223       ast_channel_unlock(c0);
05224       ast_channel_unlock(c1);
05225       ast_log(LOG_NOTICE, "Avoiding deadlock...\n");
05226       return AST_BRIDGE_RETRY;
05227    }
05228 
05229    if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05230       if (p0->owner && p1->owner) {
05231          /* If we don't have a call-wait in a 3-way, and we aren't in a 3-way, we can be master */
05232          if (!p0->subs[SUB_CALLWAIT].inthreeway && !p1->subs[SUB_REAL].inthreeway) {
05233             master = p0;
05234             slave = p1;
05235             inconf = 1;
05236          } else if (!p1->subs[SUB_CALLWAIT].inthreeway && !p0->subs[SUB_REAL].inthreeway) {
05237             master = p1;
05238             slave = p0;
05239             inconf = 1;
05240          } else {
05241             ast_log(LOG_WARNING, "Huh?  Both calls are callwaits or 3-ways?  That's clever...?\n");
05242             ast_log(LOG_WARNING, "p0: chan %d/%d/CW%d/3W%d, p1: chan %d/%d/CW%d/3W%d\n",
05243                p0->channel,
05244                oi0, (p0->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05245                p0->subs[SUB_REAL].inthreeway, p0->channel,
05246                oi0, (p1->subs[SUB_CALLWAIT].dfd > -1) ? 1 : 0,
05247                p1->subs[SUB_REAL].inthreeway);
05248          }
05249          nothingok = 0;
05250       }
05251    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_THREEWAY)) {
05252       if (p1->subs[SUB_THREEWAY].inthreeway) {
05253          master = p1;
05254          slave = p0;
05255          nothingok = 0;
05256       }
05257    } else if ((oi0 == SUB_THREEWAY) && (oi1 == SUB_REAL)) {
05258       if (p0->subs[SUB_THREEWAY].inthreeway) {
05259          master = p0;
05260          slave = p1;
05261          nothingok = 0;
05262       }
05263    } else if ((oi0 == SUB_REAL) && (oi1 == SUB_CALLWAIT)) {
05264       /* We have a real and a call wait.  If we're in a three way call, put us in it, otherwise,
05265          don't put us in anything */
05266       if (p1->subs[SUB_CALLWAIT].inthreeway) {
05267          master = p1;
05268          slave = p0;
05269          nothingok = 0;
05270       }
05271    } else if ((oi0 == SUB_CALLWAIT) && (oi1 == SUB_REAL)) {
05272       /* Same as previous */
05273       if (p0->subs[SUB_CALLWAIT].inthreeway) {
05274          master = p0;
05275          slave = p1;
05276          nothingok = 0;
05277       }
05278    }
05279    ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
05280       master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
05281    if (master && slave) {
05282       /* Stop any tones, or play ringtone as appropriate.  If they're bridged
05283          in an active threeway call with a channel that is ringing, we should
05284          indicate ringing. */
05285       if ((oi1 == SUB_THREEWAY) &&
05286          p1->subs[SUB_THREEWAY].inthreeway &&
05287          p1->subs[SUB_REAL].owner &&
05288          p1->subs[SUB_REAL].inthreeway &&
05289          (p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05290          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
05291          tone_zone_play_tone(p0->subs[oi0].dfd, DAHDI_TONE_RINGTONE);
05292          os1 = p1->subs[SUB_REAL].owner->_state;
05293       } else {
05294          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
05295          tone_zone_play_tone(p0->subs[oi0].dfd, -1);
05296       }
05297       if ((oi0 == SUB_THREEWAY) &&
05298          p0->subs[SUB_THREEWAY].inthreeway &&
05299          p0->subs[SUB_REAL].owner &&
05300          p0->subs[SUB_REAL].inthreeway &&
05301          (p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
05302          ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
05303          tone_zone_play_tone(p1->subs[oi1].dfd, DAHDI_TONE_RINGTONE);
05304          os0 = p0->subs[SUB_REAL].owner->_state;
05305       } else {
05306          ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
05307          tone_zone_play_tone(p1->subs[oi0].dfd, -1);
05308       }
05309       if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
05310          if (!p0->echocanbridged || !p1->echocanbridged) {
05311             /* Disable echo cancellation if appropriate */
05312             dahdi_disable_ec(p0);
05313             dahdi_disable_ec(p1);
05314          }
05315       }
05316       dahdi_link(slave, master);
05317       master->inconference = inconf;
05318    } else if (!nothingok)
05319       ast_log(LOG_WARNING, "Can't link %d/%s with %d/%s\n", p0->channel, subnames[oi0], p1->channel, subnames[oi1]);
05320 
05321    update_conf(p0);
05322    update_conf(p1);
05323    t0 = p0->subs[SUB_REAL].inthreeway;
05324    t1 = p1->subs[SUB_REAL].inthreeway;
05325 
05326    ast_mutex_unlock(&p0->lock);
05327    ast_mutex_unlock(&p1->lock);
05328 
05329    ast_channel_unlock(c0);
05330    ast_channel_unlock(c1);
05331 
05332    /* Native bridge failed */
05333    if ((!master || !slave) && !nothingok) {
05334       dahdi_enable_ec(p0);
05335       dahdi_enable_ec(p1);
05336       return AST_BRIDGE_FAILED;
05337    }
05338 
05339    ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
05340 
05341    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05342       disable_dtmf_detect(op0);
05343 
05344    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05345       disable_dtmf_detect(op1);
05346 
05347    for (;;) {
05348       struct ast_channel *c0_priority[2] = {c0, c1};
05349       struct ast_channel *c1_priority[2] = {c1, c0};
05350 
05351       /* Here's our main loop...  Start by locking things, looking for private parts,
05352          and then balking if anything is wrong */
05353 
05354       ast_channel_lock(c0);
05355       while (ast_channel_trylock(c1)) {
05356          CHANNEL_DEADLOCK_AVOIDANCE(c0);
05357       }
05358 
05359       p0 = c0->tech_pvt;
05360       p1 = c1->tech_pvt;
05361 
05362       if (op0 == p0)
05363          i0 = dahdi_get_index(c0, p0, 1);
05364       if (op1 == p1)
05365          i1 = dahdi_get_index(c1, p1, 1);
05366 
05367       ast_channel_unlock(c0);
05368       ast_channel_unlock(c1);
05369 
05370       if (!timeoutms ||
05371          (op0 != p0) ||
05372          (op1 != p1) ||
05373          (ofd0 != c0->fds[0]) ||
05374          (ofd1 != c1->fds[0]) ||
05375          (p0->subs[SUB_REAL].owner && (os0 > -1) && (os0 != p0->subs[SUB_REAL].owner->_state)) ||
05376          (p1->subs[SUB_REAL].owner && (os1 > -1) && (os1 != p1->subs[SUB_REAL].owner->_state)) ||
05377          (oc0 != p0->owner) ||
05378          (oc1 != p1->owner) ||
05379          (t0 != p0->subs[SUB_REAL].inthreeway) ||
05380          (t1 != p1->subs[SUB_REAL].inthreeway) ||
05381          (oi0 != i0) ||
05382          (oi1 != i1)) {
05383          ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
05384             op0->channel, oi0, op1->channel, oi1);
05385          res = AST_BRIDGE_RETRY;
05386          goto return_from_bridge;
05387       }
05388 
05389 #ifdef PRI_2BCT
05390       q931c0 = p0->call;
05391       q931c1 = p1->call;
05392       if (p0->transfer && p1->transfer
05393          && q931c0 && q931c1
05394          && !triedtopribridge) {
05395          pri_channel_bridge(q931c0, q931c1);
05396          triedtopribridge = 1;
05397       }
05398 #endif
05399 
05400       who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
05401       if (!who) {
05402          ast_debug(1, "Ooh, empty read...\n");
05403          continue;
05404       }
05405       f = ast_read(who);
05406       if (!f || (f->frametype == AST_FRAME_CONTROL)) {
05407          *fo = f;
05408          *rc = who;
05409          res = AST_BRIDGE_COMPLETE;
05410          goto return_from_bridge;
05411       }
05412       if (f->frametype == AST_FRAME_DTMF) {
05413          if ((who == c0) && p0->pulsedial) {
05414             ast_write(c1, f);
05415          } else if ((who == c1) && p1->pulsedial) {
05416             ast_write(c0, f);
05417          } else {
05418             *fo = f;
05419             *rc = who;
05420             res = AST_BRIDGE_COMPLETE;
05421             goto return_from_bridge;
05422          }
05423       }
05424       ast_frfree(f);
05425 
05426       /* Swap who gets priority */
05427       priority = !priority;
05428    }
05429 
05430 return_from_bridge:
05431    if (op0 == p0)
05432       dahdi_enable_ec(p0);
05433 
05434    if (op1 == p1)
05435       dahdi_enable_ec(p1);
05436 
05437    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0) && (oi0 == SUB_REAL))
05438       enable_dtmf_detect(op0);
05439 
05440    if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1) && (oi1 == SUB_REAL))
05441       enable_dtmf_detect(op1);
05442 
05443    dahdi_unlink(slave, master, 1);
05444 
05445    return res;
05446 }

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

Definition at line 3101 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_OFFHOOK, 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, CANPROGRESSDETECT, 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::dsp, 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_DEBUG, LOG_ERROR, LOG_WARNING, dahdi_pvt::logicalspan, dahdi_pvt::lspi_ident, MAX_CALLERID_SIZE, ast_channel::name, 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_MFCR2, 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, dahdi_pvt::waitfordialtone, dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

03102 {
03103    struct dahdi_pvt *p = ast->tech_pvt;
03104    int x, res, idx,mysig;
03105    char *c, *n, *l;
03106 #ifdef HAVE_PRI
03107    char *s = NULL;
03108 #endif
03109    char dest[256]; /* must be same length as p->dialdest */
03110    ast_mutex_lock(&p->lock);
03111    ast_copy_string(dest, rdest, sizeof(dest));
03112    ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
03113    if ((ast->_state == AST_STATE_BUSY)) {
03114       p->subs[SUB_REAL].needbusy = 1;
03115       ast_mutex_unlock(&p->lock);
03116       return 0;
03117    }
03118    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03119       ast_log(LOG_WARNING, "dahdi_call called on %s, neither down nor reserved\n", ast->name);
03120       ast_mutex_unlock(&p->lock);
03121       return -1;
03122    }
03123    p->waitingfordt.tv_sec = 0;
03124    p->dialednone = 0;
03125    if ((p->radio || (p->oprmode < 0)))  /* if a radio channel, up immediately */
03126    {
03127       /* Special pseudo -- automatically up */
03128       ast_setstate(ast, AST_STATE_UP);
03129       ast_mutex_unlock(&p->lock);
03130       return 0;
03131    }
03132    x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
03133    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
03134    if (res)
03135       ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
03136    p->outgoing = 1;
03137 
03138    if (IS_DIGITAL(ast->transfercapability)){
03139       set_actual_gain(p->subs[SUB_REAL].dfd, 0, 0, 0, p->law);
03140    } else {
03141       set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
03142    }  
03143 
03144    mysig = p->sig;
03145    if (p->outsigmod > -1)
03146       mysig = p->outsigmod;
03147 
03148    switch (mysig) {
03149    case SIG_FXOLS:
03150    case SIG_FXOGS:
03151    case SIG_FXOKS:
03152       if (p->owner == ast) {
03153          /* Normal ring, on hook */
03154 
03155          /* Don't send audio while on hook, until the call is answered */
03156          p->dialing = 1;
03157          if (p->use_callerid) {
03158             /* Generate the Caller-ID spill if desired */
03159             if (p->cidspill) {
03160                ast_log(LOG_WARNING, "cidspill already exists??\n");
03161                ast_free(p->cidspill);
03162             }
03163             p->callwaitcas = 0;
03164             if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
03165                p->cidlen = ast_callerid_generate(p->cidspill, ast->cid.cid_name, ast->cid.cid_num, AST_LAW(p));
03166                p->cidpos = 0;
03167                send_callerid(p);
03168             }
03169          }
03170          /* Choose proper cadence */
03171          if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
03172             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
03173                ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
03174             p->cidrings = cidrings[p->distinctivering - 1];
03175          } else {
03176             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, NULL))
03177                ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
03178             p->cidrings = p->sendcalleridafter;
03179          }
03180 
03181          /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
03182          c = strchr(dest, '/');
03183          if (c)
03184             c++;
03185          if (c && (strlen(c) < p->stripmsd)) {
03186             ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03187             c = NULL;
03188          }
03189          if (c) {
03190             p->dop.op = DAHDI_DIAL_OP_REPLACE;
03191             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
03192             ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
03193          } else {
03194             p->dop.dialstr[0] = '\0';
03195          }
03196          x = DAHDI_RING;
03197          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
03198             ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
03199             ast_mutex_unlock(&p->lock);
03200             return -1;
03201          }
03202          p->dialing = 1;
03203       } else {
03204          /* Call waiting call */
03205          p->callwaitrings = 0;
03206          if (ast->cid.cid_num)
03207             ast_copy_string(p->callwait_num, ast->cid.cid_num, sizeof(p->callwait_num));
03208          else
03209             p->callwait_num[0] = '\0';
03210          if (ast->cid.cid_name)
03211             ast_copy_string(p->callwait_name, ast->cid.cid_name, sizeof(p->callwait_name));
03212          else
03213             p->callwait_name[0] = '\0';
03214          /* Call waiting tone instead */
03215          if (dahdi_callwait(ast)) {
03216             ast_mutex_unlock(&p->lock);
03217             return -1;
03218          }
03219          /* Make ring-back */
03220          if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
03221             ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
03222       }
03223       n = ast->cid.cid_name;
03224       l = ast->cid.cid_num;
03225       if (l)
03226          ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
03227       else
03228          p->lastcid_num[0] = '\0';
03229       if (n)
03230          ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
03231       else
03232          p->lastcid_name[0] = '\0';
03233       ast_setstate(ast, AST_STATE_RINGING);
03234       idx = dahdi_get_index(ast, p, 0);
03235       if (idx > -1) {
03236          p->subs[idx].needringing = 1;
03237       }
03238       break;
03239    case SIG_FXSLS:
03240    case SIG_FXSGS:
03241    case SIG_FXSKS:
03242       if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
03243          ast_debug(1, "Ignore possible polarity reversal on line seizure\n");
03244          p->polaritydelaytv = ast_tvnow();
03245       }
03246       /* fall through */
03247    case SIG_EMWINK:
03248    case SIG_EM:
03249    case SIG_EM_E1:
03250    case SIG_FEATD:
03251    case SIG_FEATDMF:
03252    case SIG_E911:
03253    case SIG_FGC_CAMA:
03254    case SIG_FGC_CAMAMF:
03255    case SIG_FEATB:
03256    case SIG_SFWINK:
03257    case SIG_SF:
03258    case SIG_SF_FEATD:
03259    case SIG_SF_FEATDMF:
03260    case SIG_FEATDMF_TA:
03261    case SIG_SF_FEATB:
03262       c = strchr(dest, '/');
03263       if (c)
03264          c++;
03265       else
03266          c = "";
03267       if (strlen(c) < p->stripmsd) {
03268          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03269          ast_mutex_unlock(&p->lock);
03270          return -1;
03271       }
03272 #ifdef HAVE_PRI
03273       /* Start the trunk, if not GR-303 */
03274       if (!p->pri) {
03275 #endif
03276          x = DAHDI_START;
03277          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03278          if (res < 0) {
03279             if (errno != EINPROGRESS) {
03280                ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
03281                ast_mutex_unlock(&p->lock);
03282                return -1;
03283             }
03284          }
03285 #ifdef HAVE_PRI
03286       }
03287 #endif
03288       ast_debug(1, "Dialing '%s'\n", c);
03289       p->dop.op = DAHDI_DIAL_OP_REPLACE;
03290 
03291       c += p->stripmsd;
03292 
03293       switch (mysig) {
03294       case SIG_FEATD:
03295          l = ast->cid.cid_num;
03296          if (l)
03297             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
03298          else
03299             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
03300          break;
03301       case SIG_FEATDMF:
03302          l = ast->cid.cid_num;
03303          if (l)
03304             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
03305          else
03306             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
03307          break;
03308       case SIG_FEATDMF_TA:
03309       {
03310          const char *cic, *ozz;
03311 
03312          /* If you have to go through a Tandem Access point you need to use this */
03313          ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
03314          if (!ozz)
03315             ozz = defaultozz;
03316          cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
03317          if (!cic)
03318             cic = defaultcic;
03319          if (!ozz || !cic) {
03320             ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
03321             ast_mutex_unlock(&p->lock);
03322             return -1;
03323          }
03324          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
03325          snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
03326          p->whichwink = 0;
03327       }
03328          break;
03329       case SIG_E911:
03330          ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
03331          break;
03332       case SIG_FGC_CAMA:
03333          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
03334          break;
03335       case SIG_FGC_CAMAMF:
03336       case SIG_FEATB:
03337          snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
03338          break;
03339       default:
03340          if (p->pulse)
03341             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
03342          else
03343             snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
03344          break;
03345       }
03346 
03347       if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
03348          memset(p->echorest, 'w', sizeof(p->echorest) - 1);
03349          strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
03350          p->echorest[sizeof(p->echorest) - 1] = '\0';
03351          p->echobreak = 1;
03352          p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
03353       } else
03354          p->echobreak = 0;
03355 
03356       /* waitfordialtone ? */
03357 #ifdef HAVE_PRI
03358       if (!p->pri) {
03359 #endif
03360          if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
03361             ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
03362             gettimeofday(&p->waitingfordt,NULL);
03363             ast_setstate(ast, AST_STATE_OFFHOOK);
03364             break;
03365          }
03366 #ifdef HAVE_PRI
03367       }
03368 #endif
03369       if (!res) {
03370          if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
03371             int saveerr = errno;
03372 
03373             x = DAHDI_ONHOOK;
03374             ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
03375             ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
03376             ast_mutex_unlock(&p->lock);
03377             return -1;
03378          }
03379       } else
03380          ast_debug(1, "Deferring dialing...\n");
03381 
03382       p->dialing = 1;
03383       if (ast_strlen_zero(c))
03384          p->dialednone = 1;
03385       ast_setstate(ast, AST_STATE_DIALING);
03386       break;
03387    case 0:
03388       /* Special pseudo -- automatically up*/
03389       ast_setstate(ast, AST_STATE_UP);
03390       break;
03391    case SIG_PRI:
03392    case SIG_BRI:
03393    case SIG_BRI_PTMP:
03394    case SIG_SS7:
03395    case SIG_MFCR2:
03396       /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
03397       p->dialdest[0] = '\0';
03398       p->dialing = 1;
03399       break;
03400    default:
03401       ast_debug(1, "not yet implemented\n");
03402       ast_mutex_unlock(&p->lock);
03403       return -1;
03404    }
03405 #ifdef HAVE_SS7
03406    if (p->ss7) {
03407       char ss7_called_nai;
03408       int called_nai_strip;
03409       char ss7_calling_nai;
03410       int calling_nai_strip;
03411       const char *charge_str = NULL;
03412       const char *gen_address = NULL;
03413       const char *gen_digits = NULL;
03414       const char *gen_dig_type = NULL;
03415       const char *gen_dig_scheme = NULL;
03416       const char *gen_name = NULL;
03417       const char *jip_digits = NULL;
03418       const char *lspi_ident = NULL;
03419       const char *rlt_flag = NULL;
03420       const char *call_ref_id = NULL;
03421       const char *call_ref_pc = NULL;
03422       const char *send_far = NULL;
03423 
03424       c = strchr(dest, '/');
03425       if (c) {
03426          c++;
03427       } else {
03428          c = "";
03429       }
03430       if (strlen(c) < p->stripmsd) {
03431          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03432          ast_mutex_unlock(&p->lock);
03433          return -1;
03434       }
03435 
03436       if (!p->hidecallerid) {
03437          l = ast->cid.cid_num;
03438       } else {
03439          l = NULL;
03440       }
03441 
03442       if (ss7_grab(p, p->ss7)) {
03443          ast_log(LOG_WARNING, "Failed to grab SS7!\n");
03444          ast_mutex_unlock(&p->lock);
03445          return -1;
03446       }
03447       p->digital = IS_DIGITAL(ast->transfercapability);
03448       p->ss7call = isup_new_call(p->ss7->ss7);
03449 
03450       if (!p->ss7call) {
03451          ss7_rel(p->ss7);
03452          ast_mutex_unlock(&p->lock);
03453          ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
03454          return -1;
03455       }
03456 
03457       called_nai_strip = 0;
03458       ss7_called_nai = p->ss7->called_nai;
03459       if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
03460          if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03461             called_nai_strip = strlen(p->ss7->internationalprefix);
03462             ss7_called_nai = SS7_NAI_INTERNATIONAL;
03463          } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03464             called_nai_strip = strlen(p->ss7->nationalprefix);
03465             ss7_called_nai = SS7_NAI_NATIONAL;
03466          } else {
03467             ss7_called_nai = SS7_NAI_SUBSCRIBER;
03468          }
03469       }
03470       isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
03471 
03472       calling_nai_strip = 0;
03473       ss7_calling_nai = p->ss7->calling_nai;
03474       if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
03475          if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
03476             calling_nai_strip = strlen(p->ss7->internationalprefix);
03477             ss7_calling_nai = SS7_NAI_INTERNATIONAL;
03478          } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
03479             calling_nai_strip = strlen(p->ss7->nationalprefix);
03480             ss7_calling_nai = SS7_NAI_NATIONAL;
03481          } else {
03482             ss7_calling_nai = SS7_NAI_SUBSCRIBER;
03483          }
03484       }
03485       isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
03486          p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
03487          p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
03488 
03489       isup_set_oli(p->ss7call, ast->cid.cid_ani2);
03490       isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
03491 
03492       ast_channel_lock(ast);
03493       /* Set the charge number if it is set */
03494       charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
03495       if (charge_str)
03496          isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
03497 
03498       gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
03499       if (gen_address)
03500          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 */
03501 
03502       gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
03503       gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
03504       gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
03505       if (gen_digits)
03506          isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
03507 
03508       gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
03509       if (gen_name)
03510          isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
03511 
03512       jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
03513       if (jip_digits)
03514          isup_set_jip_digits(p->ss7call, jip_digits);
03515 
03516       lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
03517       if (lspi_ident)
03518          isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
03519 
03520       rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
03521       if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
03522          isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
03523       }
03524 
03525       call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
03526       call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
03527       if (call_ref_id && call_ref_pc) {
03528          isup_set_callref(p->ss7call, atoi(call_ref_id),
03529                 call_ref_pc ? atoi(call_ref_pc) : 0);
03530       }
03531 
03532       send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
03533       if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
03534          (isup_far(p->ss7->ss7, p->ss7call));
03535 
03536       ast_channel_unlock(ast);
03537 
03538       isup_iam(p->ss7->ss7, p->ss7call);
03539       ast_setstate(ast, AST_STATE_DIALING);
03540       ss7_rel(p->ss7);
03541    }
03542 #endif /* HAVE_SS7 */
03543 #ifdef HAVE_OPENR2
03544    if (p->mfcr2) {
03545       openr2_calling_party_category_t chancat;
03546       int callres = 0;
03547       char *c, *l;
03548 
03549       c = strchr(dest, '/');
03550       if (c) {
03551          c++;
03552       } else {
03553          c = "";
03554       }
03555       if (!p->hidecallerid) {
03556          l = ast->cid.cid_num;
03557       } else {
03558          l = NULL;
03559       }
03560       if (strlen(c) < p->stripmsd) {
03561          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03562          ast_mutex_unlock(&p->lock);
03563          return -1;
03564       }
03565       p->dialing = 1;
03566       ast_channel_lock(ast);
03567       chancat = dahdi_r2_get_channel_category(ast);
03568       ast_channel_unlock(ast);
03569       callres = openr2_chan_make_call(p->r2chan, l, (c + p->stripmsd), chancat);
03570       if (-1 == callres) {
03571          ast_mutex_unlock(&p->lock);
03572          ast_log(LOG_ERROR, "unable to make new MFC/R2 call!\n");
03573          return -1;
03574       }
03575       ast_setstate(ast, AST_STATE_DIALING);
03576    }
03577 #endif /* HAVE_OPENR2 */
03578 #ifdef HAVE_PRI
03579    if (p->pri) {
03580       struct pri_sr *sr;
03581 #ifdef SUPPORT_USERUSER
03582       const char *useruser;
03583 #endif
03584       int pridialplan;
03585       int dp_strip;
03586       int prilocaldialplan;
03587       int ldp_strip;
03588       int exclusive;
03589       const char *rr_str;
03590       int redirect_reason;
03591 
03592       c = strchr(dest, '/');
03593       if (c) {
03594          c++;
03595       } else {
03596          c = "";
03597       }
03598 
03599       l = NULL;
03600       n = NULL;
03601       if (!p->hidecallerid) {
03602          l = ast->cid.cid_num;
03603          if (!p->hidecalleridname) {
03604             n = ast->cid.cid_name;
03605          }
03606       }
03607 
03608       if (strlen(c) < p->stripmsd) {
03609          ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
03610          ast_mutex_unlock(&p->lock);
03611          return -1;
03612       }
03613       if (mysig != SIG_FXSKS) {
03614          p->dop.op = DAHDI_DIAL_OP_REPLACE;
03615          s = strchr(c + p->stripmsd, 'w');
03616          if (s) {
03617             if (strlen(s) > 1)
03618                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
03619             else
03620                p->dop.dialstr[0] = '\0';
03621             *s = '\0';
03622          } else {
03623             p->dop.dialstr[0] = '\0';
03624          }
03625       }
03626       if (pri_grab(p, p->pri)) {
03627          ast_log(LOG_WARNING, "Failed to grab PRI!\n");
03628          ast_mutex_unlock(&p->lock);
03629          return -1;
03630       }
03631       if (!(p->call = pri_new_call(p->pri->pri))) {
03632          ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
03633          pri_rel(p->pri);
03634          ast_mutex_unlock(&p->lock);
03635          return -1;
03636       }
03637       if (!(sr = pri_sr_new())) {
03638          ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
03639          pri_rel(p->pri);
03640          ast_mutex_unlock(&p->lock);
03641       }
03642       if (p->bearer || (mysig == SIG_FXSKS)) {
03643          if (p->bearer) {
03644             ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
03645             p->bearer->call = p->call;
03646          } else
03647             ast_debug(1, "I'm being setup with no bearer right now...\n");
03648 
03649          pri_set_crv(p->pri->pri, p->call, p->channel, 0);
03650       }
03651       p->digital = IS_DIGITAL(ast->transfercapability);
03652 
03653       /* Should the picked channel be used exclusively? */
03654       if (p->priexclusive || p->pri->nodetype == PRI_NETWORK) {
03655          exclusive = 1;
03656       } else {
03657          exclusive = 0;
03658       }
03659 
03660       pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
03661       pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
03662          (p->digital ? -1 :
03663             ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
03664       if (p->pri->facilityenable)
03665          pri_facility_enable(p->pri->pri);
03666 
03667       ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
03668 
03669       dp_strip = 0;
03670       pridialplan = p->pri->dialplan - 1;
03671       if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
03672          if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03673             if (pridialplan == -2) {
03674                dp_strip = strlen(p->pri->internationalprefix);
03675             }
03676             pridialplan = PRI_INTERNATIONAL_ISDN;
03677          } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03678             if (pridialplan == -2) {
03679                dp_strip = strlen(p->pri->nationalprefix);
03680             }
03681             pridialplan = PRI_NATIONAL_ISDN;
03682          } else {
03683             pridialplan = PRI_LOCAL_ISDN;
03684          }
03685       }
03686       while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
03687          switch (c[p->stripmsd]) {
03688          case 'U':
03689             pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
03690             break;
03691          case 'I':
03692             pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
03693             break;
03694          case 'N':
03695             pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
03696             break;
03697          case 'L':
03698             pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
03699             break;
03700          case 'S':
03701             pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
03702             break;
03703          case 'V':
03704             pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
03705             break;
03706          case 'R':
03707             pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
03708             break;
03709          case 'u':
03710             pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
03711             break;
03712          case 'e':
03713             pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
03714             break;
03715          case 'x':
03716             pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
03717             break;
03718          case 'f':
03719             pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
03720             break;
03721          case 'n':
03722             pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
03723             break;
03724          case 'p':
03725             pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
03726             break;
03727          case 'r':
03728             pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
03729             break;
03730          default:
03731             if (isalpha(c[p->stripmsd])) {
03732                ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
03733                   c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
03734             }
03735             break;
03736          }
03737          c++;
03738       }
03739       pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
03740 
03741       ldp_strip = 0;
03742       prilocaldialplan = p->pri->localdialplan - 1;
03743       if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
03744          if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
03745             if (prilocaldialplan == -2) {
03746                ldp_strip = strlen(p->pri->internationalprefix);
03747             }
03748             prilocaldialplan = PRI_INTERNATIONAL_ISDN;
03749          } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
03750             if (prilocaldialplan == -2) {
03751                ldp_strip = strlen(p->pri->nationalprefix);
03752             }
03753             prilocaldialplan = PRI_NATIONAL_ISDN;
03754          } else {
03755             prilocaldialplan = PRI_LOCAL_ISDN;
03756          }
03757       }
03758       if (l != NULL) {
03759          while (*l > '9' && *l != '*' && *l != '#') {
03760             switch (*l) {
03761             case 'U':
03762                prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
03763                break;
03764             case 'I':
03765                prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
03766                break;
03767             case 'N':
03768                prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
03769                break;
03770             case 'L':
03771                prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
03772                break;
03773             case 'S':
03774                prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
03775                break;
03776             case 'V':
03777                prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
03778                break;
03779             case 'R':
03780                prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
03781                break;
03782             case 'u':
03783                prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
03784                break;
03785             case 'e':
03786                prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
03787                break;
03788             case 'x':
03789                prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
03790                break;
03791             case 'f':
03792                prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
03793                break;
03794             case 'n':
03795                prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
03796                break;
03797             case 'p':
03798                prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
03799                break;
03800             case 'r':
03801                prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
03802                break;
03803             default:
03804                if (isalpha(*l)) {
03805                   ast_log(LOG_WARNING,
03806                      "Unrecognized prilocaldialplan %s modifier: %c\n",
03807                      *l > 'Z' ? "NPI" : "TON", *l);
03808                }
03809                break;
03810             }
03811             l++;
03812          }
03813       }
03814       pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
03815          p->use_callingpres ? ast->cid.cid_pres : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
03816       if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
03817          if (!strcasecmp(rr_str, "UNKNOWN"))
03818             redirect_reason = 0;
03819          else if (!strcasecmp(rr_str, "BUSY"))
03820             redirect_reason = 1;
03821          else if (!strcasecmp(rr_str, "NO_REPLY") || !strcasecmp(rr_str, "NOANSWER"))
03822          /* the NOANSWER is to match diversion-reason from chan_sip, (which never reads PRIREDIRECTREASON) */
03823             redirect_reason = 2;
03824          else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
03825             redirect_reason = 15;
03826          else
03827             redirect_reason = PRI_REDIR_UNCONDITIONAL;
03828       } else
03829          redirect_reason = PRI_REDIR_UNCONDITIONAL;
03830       pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
03831 
03832 #ifdef SUPPORT_USERUSER
03833       /* User-user info */
03834       useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
03835       if (useruser)
03836          pri_sr_set_useruser(sr, useruser);
03837 #endif
03838 
03839       if (pri_setup(p->pri->pri, p->call, sr)) {
03840          ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
03841             c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
03842          pri_rel(p->pri);
03843          ast_mutex_unlock(&p->lock);
03844          pri_sr_free(sr);
03845          return -1;
03846       }
03847       pri_sr_free(sr);
03848       ast_setstate(ast, AST_STATE_DIALING);
03849       pri_rel(p->pri);
03850    }
03851 #endif
03852    ast_mutex_unlock(&p->lock);
03853    return 0;
03854 }

static int dahdi_callwait ( struct ast_channel ast  )  [static]

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

03060 {
03061    struct dahdi_pvt *p = ast->tech_pvt;
03062    p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
03063    if (p->cidspill) {
03064       ast_log(LOG_WARNING, "Spill already exists?!?\n");
03065       ast_free(p->cidspill);
03066    }
03067    if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
03068       return -1;
03069    save_conference(p);
03070    /* Silence */
03071    memset(p->cidspill, 0x7f, 2400 + 600 + READ_SIZE * 4);
03072    if (!p->callwaitrings && p->callwaitingcallerid) {
03073       ast_gen_cas(p->cidspill, 1, 2400 + 680, AST_LAW(p));
03074       p->callwaitcas = 1;
03075       p->cidlen = 2400 + 680 + READ_SIZE * 4;
03076    } else {
03077       ast_gen_cas(p->cidspill, 1, 2400, AST_LAW(p));
03078       p->callwaitcas = 0;
03079       p->cidlen = 2400 + READ_SIZE * 4;
03080    }
03081    p->cidpos = 0;
03082    send_callerid(p);
03083 
03084    return 0;
03085 }

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

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

Referenced by process_dahdi(), and setup_dahdi().

01267 {
01268    /* recall that if a field is not included here it is initialized
01269     * to 0 or equivalent
01270     */
01271    struct dahdi_chan_conf conf = {
01272 #ifdef HAVE_PRI
01273       .pri = {
01274          .nsf = PRI_NSF_NONE,
01275          .switchtype = PRI_SWITCH_NI2,
01276          .dialplan = PRI_UNKNOWN + 1,
01277          .localdialplan = PRI_NATIONAL_ISDN + 1,
01278          .nodetype = PRI_CPE,
01279          .qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL,
01280 
01281          .minunused = 2,
01282          .idleext = "",
01283          .idledial = "",
01284          .internationalprefix = "",
01285          .nationalprefix = "",
01286          .localprefix = "",
01287          .privateprefix = "",
01288          .unknownprefix = "",
01289          .resetinterval = -1,
01290       },
01291 #endif
01292 #ifdef HAVE_SS7
01293       .ss7 = {
01294          .called_nai = SS7_NAI_NATIONAL,
01295          .calling_nai = SS7_NAI_NATIONAL,
01296          .internationalprefix = "",
01297          .nationalprefix = "",
01298          .subscriberprefix = "",
01299          .unknownprefix = ""
01300       },
01301 #endif
01302 #ifdef HAVE_OPENR2
01303       .mfcr2 = {
01304          .variant = OR2_VAR_ITU,
01305          .mfback_timeout = -1,
01306          .metering_pulse_timeout = -1,
01307          .max_ani = 10,
01308          .max_dnis = 4,
01309          .get_ani_first = -1,
01310 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
01311          .skip_category_request = -1,
01312 #endif
01313          .call_files = 0,
01314          .allow_collect_calls = 0,
01315          .charge_calls = 1,
01316          .accept_on_offer = 1,
01317          .forced_release = 0,
01318          .double_answer = 0,
01319          .immediate_accept = -1,
01320          .logdir = "",
01321          .r2proto_file = "",
01322          .loglevel = OR2_LOG_ERROR | OR2_LOG_WARNING,
01323          .category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER
01324       },
01325 #endif
01326       .chan = {
01327          .context = "default",
01328          .cid_num = "",
01329          .cid_name = "",
01330          .mohinterpret = "default",
01331          .mohsuggest = "",
01332          .parkinglot = "",
01333          .transfertobusy = 1,
01334 
01335          .cid_signalling = CID_SIG_BELL,
01336          .cid_start = CID_START_RING,
01337          .dahditrcallerid = 0,
01338          .use_callerid = 1,
01339          .sig = -1,
01340          .outsigmod = -1,
01341 
01342          .cid_rxgain = +5.0,
01343 
01344          .tonezone = -1,
01345 
01346          .echocancel.head.tap_length = 1,
01347 
01348          .busycount = 3,
01349 
01350          .accountcode = "",
01351 
01352          .mailbox = "",
01353 
01354 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
01355          .mwisend_fsk = 1,
01356 #endif
01357          .polarityonanswerdelay = 600,
01358 
01359          .sendcalleridafter = DEFAULT_CIDRINGS,
01360 
01361          .buf_policy = DAHDI_POLICY_IMMEDIATE,
01362          .buf_no = numbufs,
01363          .usefaxbuffers = 0,
01364          .faxbuf_policy = DAHDI_POLICY_IMMEDIATE,
01365          .faxbuf_no = numbufs,
01366       },
01367       .timing = {
01368          .prewinktime = -1,
01369          .preflashtime = -1,
01370          .winktime = -1,
01371          .flashtime = -1,
01372          .starttime = -1,
01373          .rxwinktime = -1,
01374          .rxflashtime = -1,
01375          .debouncetime = -1
01376       },
01377       .is_sig_auto = 1,
01378       .smdi_port = "/dev/ttyS0",
01379    };
01380 
01381    return conf;
01382 }

static void dahdi_close ( int  fd  )  [static]

Definition at line 2137 of file chan_dahdi.c.

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

02138 {
02139    if (fd > 0)
02140       close(fd);
02141 }

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

Definition at line 2150 of file chan_dahdi.c.

References dahdi_close(), and dahdi_pri::fds.

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

02151 {
02152    dahdi_close(pri->fds[fd_num]);
02153    pri->fds[fd_num] = -1;
02154 }

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

Definition at line 2158 of file chan_dahdi.c.

References dahdi_close(), and dahdi_ss7::fds.

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

02159 {
02160    dahdi_close(ss7->fds[fd_num]);
02161    ss7->fds[fd_num] = -1;
02162 }

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

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

02144 {
02145    dahdi_close(chan_pvt->subs[sub_num].dfd);
02146    chan_pvt->subs[sub_num].dfd = -1;
02147 }

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

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

02881 {
02882    int x, y, res;
02883    x = muted;
02884    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
02885       y = 1;
02886       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &y);
02887       if (res)
02888          ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
02889    }
02890    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_CONFMUTE, &x);
02891    if (res < 0)
02892       ast_log(LOG_WARNING, "DAHDI confmute(%d) failed on channel %d: %s\n", muted, p->channel, strerror(errno));
02893    return res;
02894 }

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

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

14288 {
14289    int channel;
14290    int ret;
14291    switch (cmd) {
14292    case CLI_INIT:
14293       e->command = "dahdi destroy channel";
14294       e->usage =
14295          "Usage: dahdi destroy channel <chan num>\n"
14296          "  DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
14297       return NULL;
14298    case CLI_GENERATE:
14299       return NULL;
14300    }
14301    if (a->argc != 4)
14302       return CLI_SHOWUSAGE;
14303 
14304    channel = atoi(a->argv[3]);
14305    ret = dahdi_destroy_channel_bynum(channel);
14306    return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
14307 }

static int dahdi_destroy_channel_bynum ( int  channel  )  [static]

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

09250 {
09251    struct dahdi_pvt *tmp = NULL;
09252    struct dahdi_pvt *prev = NULL;
09253 
09254    tmp = iflist;
09255    while (tmp) {
09256       if (tmp->channel == channel) {
09257          int x = DAHDI_FLASH;
09258          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 */
09259          destroy_channel(prev, tmp, 1);
09260          ast_module_unref(ast_module_info->self);
09261          return RESULT_SUCCESS;
09262       }
09263       prev = tmp;
09264       tmp = tmp->next;
09265    }
09266    return RESULT_FAILURE;
09267 }

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

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

02246 {
02247    struct dahdi_pvt *pvt;
02248    int idx;
02249    int dtmf = -1;
02250 
02251    pvt = chan->tech_pvt;
02252 
02253    ast_mutex_lock(&pvt->lock);
02254 
02255    idx = dahdi_get_index(chan, pvt, 0);
02256 
02257    if ((idx != SUB_REAL) || !pvt->owner)
02258       goto out;
02259 
02260 #ifdef HAVE_PRI
02261    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02262          && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
02263       if (pvt->setup_ack) {
02264          if (!pri_grab(pvt, pvt->pri)) {
02265             pri_information(pvt->pri->pri, pvt->call, digit);
02266             pri_rel(pvt->pri);
02267          } else
02268             ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
02269       } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
02270          int res;
02271          ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
02272          res = strlen(pvt->dialdest);
02273          pvt->dialdest[res++] = digit;
02274          pvt->dialdest[res] = '\0';
02275       }
02276       goto out;
02277    }
02278 #endif
02279    if ((dtmf = digit_to_dtmfindex(digit)) == -1)
02280       goto out;
02281 
02282    if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
02283       int res;
02284       struct dahdi_dialoperation zo = {
02285          .op = DAHDI_DIAL_OP_APPEND,
02286       };
02287 
02288       zo.dialstr[0] = 'T';
02289       zo.dialstr[1] = digit;
02290       zo.dialstr[2] = '\0';
02291       if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
02292          ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
02293       else
02294          pvt->dialing = 1;
02295    } else {
02296       ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
02297       pvt->dialing = 1;
02298       pvt->begindigit = digit;
02299    }
02300 
02301 out:
02302    ast_mutex_unlock(&pvt->lock);
02303 
02304    return 0;
02305 }

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

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

02308 {
02309    struct dahdi_pvt *pvt;
02310    int res = 0;
02311    int idx;
02312    int x;
02313 
02314    pvt = chan->tech_pvt;
02315 
02316    ast_mutex_lock(&pvt->lock);
02317 
02318    idx = dahdi_get_index(chan, pvt, 0);
02319 
02320    if ((idx != SUB_REAL) || !pvt->owner || pvt->pulse)
02321       goto out;
02322 
02323 #ifdef HAVE_PRI
02324    /* This means that the digit was already sent via PRI signalling */
02325    if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
02326          && !pvt->begindigit)
02327       goto out;
02328 #endif
02329 
02330    if (pvt->begindigit) {
02331       x = -1;
02332       ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
02333       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &x);
02334       pvt->dialing = 0;
02335       pvt->begindigit = 0;
02336    }
02337 
02338 out:
02339    ast_mutex_unlock(&pvt->lock);
02340 
02341    return res;
02342 }

static void dahdi_disable_ec ( struct dahdi_pvt p  )  [static]

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

02710 {
02711    int res;
02712 
02713    if (p->echocanon) {
02714       struct dahdi_echocanparams ecp = { .tap_length = 0 };
02715 
02716       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
02717 
02718       if (res)
02719          ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
02720       else
02721          ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
02722    }
02723 
02724    p->echocanon = 0;
02725 }

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

07663 {
07664    /* Do not disturb */
07665    dahdichan->dnd = on;
07666    ast_verb(3, "%s DND on channel %d\n",
07667          on? "Enabled" : "Disabled",
07668          dahdichan->channel);
07669    manager_event(EVENT_FLAG_SYSTEM, "DNDState",
07670          "Channel: DAHDI/%d\r\n"
07671          "Status: %s\r\n", dahdichan->channel,
07672          on? "enabled" : "disabled");
07673 }

static void dahdi_enable_ec ( struct dahdi_pvt p  )  [static]

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

02661 {
02662    int x;
02663    int res;
02664    if (!p)
02665       return;
02666    if (p->echocanon) {
02667       ast_debug(1, "Echo cancellation already on\n");
02668       return;
02669    }
02670    if (p->digital) {
02671       ast_debug(1, "Echo cancellation isn't required on digital connection\n");
02672       return;
02673    }
02674    if (p->echocancel.head.tap_length) {
02675       if ((p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP) || (p->sig == SIG_PRI) || (p->sig == SIG_SS7)) {
02676          x = 1;
02677          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x);
02678          if (res)
02679             ast_log(LOG_WARNING, "Unable to enable audio mode on channel %d (%s)\n", p->channel, strerror(errno));
02680       }
02681       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOCANCEL_PARAMS, &p->echocancel);
02682       if (res) {
02683          ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d (%s)\n", p->channel, strerror(errno));
02684       } else {
02685          p->echocanon = 1;
02686          ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
02687       }
02688    } else
02689       ast_debug(1, "No echo cancellation requested\n");
02690 }

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

Definition at line 6707 of file chan_dahdi.c.

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

06708 {
06709    struct dahdi_pvt *p = ast->tech_pvt;
06710    struct ast_frame *f;
06711    ast_mutex_lock(&p->lock);
06712    f = __dahdi_exception(ast);
06713    ast_mutex_unlock(&p->lock);
06714    return f;
06715 }

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

Definition at line 15185 of file chan_dahdi.c.

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

Referenced by action_transfer(), and action_transferhangup().

15186 {
15187    if (p) {
15188       switch (mode) {
15189          case TRANSFER:
15190             p->fake_event = DAHDI_EVENT_WINKFLASH;
15191             break;
15192          case HANGUP:
15193             p->fake_event = DAHDI_EVENT_ONHOOK;
15194             break;
15195          default:
15196             ast_log(LOG_WARNING, "I don't know how to handle transfer event with this: %d on channel %s\n",mode, p->owner->name);
15197       }
15198    }
15199    return 0;
15200 }

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

Definition at line 5448 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, ast_channel::name, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::subs, ast_channel::tech_pvt, and update_conf().

05449 {
05450    struct dahdi_pvt *p = newchan->tech_pvt;
05451    int x;
05452    ast_mutex_lock(&p->lock);
05453    ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
05454    if (p->owner == oldchan) {
05455       p->owner = newchan;
05456    }
05457    for (x = 0; x < 3; x++)
05458       if (p->subs[x].owner == oldchan) {
05459          if (!x)
05460             dahdi_unlink(NULL, p, 0);
05461          p->subs[x].owner = newchan;
05462       }
05463    if (newchan->_state == AST_STATE_RINGING)
05464       dahdi_indicate(newchan, AST_CONTROL_RINGING, NULL, 0);
05465    update_conf(p);
05466    ast_mutex_unlock(&p->lock);
05467    return 0;
05468 }

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

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

05026 {
05027    struct dahdi_pvt *p = chan->tech_pvt;
05028 
05029    if (!strcasecmp(data, "rxgain")) {
05030       ast_mutex_lock(&p->lock);
05031       snprintf(buf, len, "%f", p->rxgain);
05032       ast_mutex_unlock(&p->lock);
05033    } else if (!strcasecmp(data, "txgain")) {
05034       ast_mutex_lock(&p->lock);
05035       snprintf(buf, len, "%f", p->txgain);
05036       ast_mutex_unlock(&p->lock);
05037    } else {
05038       ast_copy_string(buf, "", len);
05039    }
05040    return 0;
05041 }

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

Avoid the silly dahdi_getevent which ignores a bunch of events.

Definition at line 376 of file chan_dahdi.c.

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

00377 {
00378    int j;
00379    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00380       return -1;
00381    return j;
00382 }

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

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

01504 {
01505    int res;
01506    if (p->subs[SUB_REAL].owner == ast)
01507       res = 0;
01508    else if (p->subs[SUB_CALLWAIT].owner == ast)
01509       res = 1;
01510    else if (p->subs[SUB_THREEWAY].owner == ast)
01511       res = 2;
01512    else {
01513       res = -1;
01514       if (!nullok)
01515          ast_log(LOG_WARNING, "Unable to get index, and nullok is not asserted\n");
01516    }
01517    return res;
01518 }

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

Definition at line 5607 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::bufsize, 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(), dahdi_subchannel::dfd, errno, ast_channel::exten, dahdi_subchannel::f, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, dahdi_pvt::faxbuffersinuse, dahdi_pvt::faxhandled, ast_frame::frametype, dahdi_pvt::lock, LOG_NOTICE, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, pbx_builtin_setvar_helper(), S_OR, send_cwcidspill(), ast_frame::subclass, dahdi_pvt::subs, ast_channel::tech_pvt, and dahdi_pvt::usefaxbuffers.

Referenced by dahdi_handle_event(), and dahdi_read().

05608 {
05609    struct dahdi_pvt *p = ast->tech_pvt;
05610    struct ast_frame *f = *dest;
05611 
05612    ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
05613 
05614    if (p->confirmanswer) {
05615       ast_debug(1, "Confirm answer on %s!\n", ast->name);
05616       /* Upon receiving a DTMF digit, consider this an answer confirmation instead
05617          of a DTMF digit */
05618       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05619       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05620       *dest = &p->subs[idx].f;
05621       /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
05622       p->confirmanswer = 0;
05623    } else if (p->callwaitcas) {
05624       if ((f->subclass == 'A') || (f->subclass == 'D')) {
05625          ast_debug(1, "Got some DTMF, but it's for the CAS\n");
05626          if (p->cidspill)
05627             ast_free(p->cidspill);
05628          send_cwcidspill(p);
05629       }
05630       p->callwaitcas = 0;
05631       p->subs[idx].f.frametype = AST_FRAME_NULL;
05632       p->subs[idx].f.subclass = 0;
05633       *dest = &p->subs[idx].f;
05634    } else if (f->subclass == 'f') {
05635       /* Fax tone -- Handle and return NULL */
05636       if ((p->callprogress & CALLPROGRESS_FAX) && !p->faxhandled) {
05637          /* If faxbuffers are configured, use them for the fax transmission */
05638          if (p->usefaxbuffers && !p->faxbuffersinuse) {
05639             struct dahdi_bufferinfo bi = {
05640                .txbufpolicy = p->faxbuf_policy,
05641                .bufsize = p->bufsize,
05642                .numbufs = p->faxbuf_no
05643             };
05644             int res;
05645 
05646             if ((res = ioctl(p->subs[idx].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
05647                ast_log(LOG_WARNING, "Channel '%s' unable to set faxbuffer policy, reason: %s\n", ast->name, strerror(errno));
05648             } else {
05649                p->faxbuffersinuse = 1;
05650             }
05651          }
05652          p->faxhandled = 1;
05653          if (strcmp(ast->exten, "fax")) {
05654             const char *target_context = S_OR(ast->macrocontext, ast->context);
05655 
05656             /* We need to unlock 'ast' here because ast_exists_extension has the
05657              * potential to start autoservice on the channel. Such action is prone
05658              * to deadlock.
05659              */
05660             ast_mutex_unlock(&p->lock);
05661             ast_channel_unlock(ast);
05662             if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
05663                ast_channel_lock(ast);
05664                ast_mutex_lock(&p->lock);
05665                ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
05666                /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
05667                pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
05668                if (ast_async_goto(ast, target_context, "fax", 1))
05669                   ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
05670             } else {
05671                ast_channel_lock(ast);
05672                ast_mutex_lock(&p->lock);
05673                ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
05674             }
05675          } else {
05676             ast_debug(1, "Already in a fax extension, not redirecting\n");
05677          }
05678       } else {
05679          ast_debug(1, "Fax already handled\n");
05680       }
05681       dahdi_confmute(p, 0);
05682       p->subs[idx].f.frametype = AST_FRAME_NULL;
05683       p->subs[idx].f.subclass = 0;
05684       *dest = &p->subs[idx].f;
05685    }
05686 }

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 5699 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, 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, dahdi_pvt::fake_event, dahdi_pvt::finaldial, dahdi_pvt::flashtime, ast_frame::frametype, dahdi_pvt::fxsoffhookstate, 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, ast_channel::name, 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_MFCR2, 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(), dahdi_pvt::waitingfordt, and dahdi_pvt::whichwink.

Referenced by __dahdi_exception().

05700 {
05701    int res, x;
05702    int idx, mysig;
05703    char *c;
05704    struct dahdi_pvt *p = ast->tech_pvt;
05705    pthread_t threadid;
05706    struct ast_channel *chan;
05707    struct ast_frame *f;
05708 
05709    idx = dahdi_get_index(ast, p, 0);
05710    mysig = p->sig;
05711    if (p->outsigmod > -1)
05712       mysig = p->outsigmod;
05713    p->subs[idx].f.frametype = AST_FRAME_NULL;
05714    p->subs[idx].f.subclass = 0;
05715    p->subs[idx].f.datalen = 0;
05716    p->subs[idx].f.samples = 0;
05717    p->subs[idx].f.mallocd = 0;
05718    p->subs[idx].f.offset = 0;
05719    p->subs[idx].f.src = "dahdi_handle_event";
05720    p->subs[idx].f.data.ptr = NULL;
05721    f = &p->subs[idx].f;
05722 
05723    if (idx < 0)
05724       return &p->subs[idx].f;
05725    if (p->fake_event) {
05726       res = p->fake_event;
05727       p->fake_event = 0;
05728    } else
05729       res = dahdi_get_event(p->subs[idx].dfd);
05730 
05731    ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, idx);
05732 
05733    if (res & (DAHDI_EVENT_PULSEDIGIT | DAHDI_EVENT_DTMFUP)) {
05734       p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
05735       ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
05736 #ifdef HAVE_PRI
05737       if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
05738          /* absorb event */
05739       } else {
05740 #endif
05741          dahdi_confmute(p, 0);
05742          p->subs[idx].f.frametype = AST_FRAME_DTMF_END;
05743          p->subs[idx].f.subclass = res & 0xff;
05744 #ifdef HAVE_PRI
05745       }
05746 #endif
05747       dahdi_handle_dtmfup(ast, idx, &f);
05748       return f;
05749    }
05750 
05751    if (res & DAHDI_EVENT_DTMFDOWN) {
05752       ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
05753       /* Mute conference */
05754       dahdi_confmute(p, 1);
05755       p->subs[idx].f.frametype = AST_FRAME_DTMF_BEGIN;
05756       p->subs[idx].f.subclass = res & 0xff;
05757       return &p->subs[idx].f;
05758    }
05759 
05760    switch (res) {
05761       case DAHDI_EVENT_EC_DISABLED:
05762          ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
05763          p->echocanon = 0;
05764          break;
05765       case DAHDI_EVENT_BITSCHANGED:
05766 #ifdef HAVE_OPENR2
05767          if (p->sig != SIG_MFCR2) {
05768             ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05769          } else {
05770             ast_log(LOG_DEBUG, "bits changed in chan %d\n", p->channel);
05771             openr2_chan_handle_cas(p->r2chan);
05772          }
05773 #else
05774          ast_log(LOG_WARNING, "Received bits changed on %s signalling?\n", sig2str(p->sig));
05775 #endif
05776       case DAHDI_EVENT_PULSE_START:
05777          /* Stop tone if there's a pulse start and the PBX isn't started */
05778          if (!ast->pbx)
05779             tone_zone_play_tone(p->subs[idx].dfd, -1);
05780          break;
05781       case DAHDI_EVENT_DIALCOMPLETE:
05782 #ifdef HAVE_OPENR2
05783          if ((p->sig & SIG_MFCR2) && p->r2chan && ast->_state != AST_STATE_UP) {
05784             /* we don't need to do anything for this event for R2 signaling
05785                if the call is being setup */
05786             break;
05787          }
05788 #endif
05789          if (p->inalarm) break;
05790          if ((p->radio || (p->oprmode < 0))) break;
05791          if (ioctl(p->subs[idx].dfd,DAHDI_DIALING,&x) == -1) {
05792             ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
05793             return NULL;
05794          }
05795          if (!x) { /* if not still dialing in driver */
05796             dahdi_enable_ec(p);
05797             if (p->echobreak) {
05798                dahdi_train_ec(p);
05799                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
05800                p->dop.op = DAHDI_DIAL_OP_REPLACE;
05801                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
05802                p->echobreak = 0;
05803             } else {
05804                p->dialing = 0;
05805                if ((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) {
05806                   /* if thru with dialing after offhook */
05807                   if (ast->_state == AST_STATE_DIALING_OFFHOOK) {
05808                      ast_setstate(ast, AST_STATE_UP);
05809                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05810                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05811                      break;
05812                   } else { /* if to state wait for offhook to dial rest */
05813                      /* we now wait for off hook */
05814                      ast_setstate(ast,AST_STATE_DIALING_OFFHOOK);
05815                   }
05816                }
05817                if (ast->_state == AST_STATE_DIALING) {
05818                   if ((p->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
05819                      ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
05820                   } else if (p->confirmanswer || (!p->dialednone
05821                      && ((mysig == SIG_EM) || (mysig == SIG_EM_E1)
05822                         || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD)
05823                         || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF)
05824                         || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA)
05825                         || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB)
05826                         || (mysig == SIG_SF) || (mysig == SIG_SFWINK)
05827                         || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF)
05828                         || (mysig == SIG_SF_FEATB)))) {
05829                      ast_setstate(ast, AST_STATE_RINGING);
05830                   } else if (!p->answeronpolarityswitch) {
05831                      ast_setstate(ast, AST_STATE_UP);
05832                      p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05833                      p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
05834                      /* If aops=0 and hops=1, this is necessary */
05835                      p->polarity = POLARITY_REV;
05836                   } else {
05837                      /* Start clean, so we can catch the change to REV polarity when party answers */
05838                      p->polarity = POLARITY_IDLE;
05839                   }
05840                }
05841             }
05842          }
05843          break;
05844       case DAHDI_EVENT_ALARM:
05845 #ifdef HAVE_PRI
05846          if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
05847             if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
05848                /* T309 is not enabled : hangup calls when alarm occurs */
05849                if (p->call) {
05850                   if (p->pri && p->pri->pri) {
05851                      if (!pri_grab(p, p->pri)) {
05852                         pri_hangup(p->pri->pri, p->call, -1);
05853                         pri_destroycall(p->pri->pri, p->call);
05854                         p->call = NULL;
05855                         pri_rel(p->pri);
05856                      } else
05857                         ast_log(LOG_WARNING, "Failed to grab PRI!\n");
05858                   } else
05859                      ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
05860                }
05861                if (p->owner)
05862                   p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
05863             }
05864          }
05865          if (p->bearer)
05866             p->bearer->inalarm = 1;
05867          else
05868 #endif
05869          p->inalarm = 1;
05870          res = get_alarms(p);
05871          handle_alarms(p, res);
05872 #ifdef HAVE_PRI
05873          if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
05874             /* fall through intentionally */
05875          } else {
05876             break;
05877          }
05878 #endif
05879 #ifdef HAVE_SS7
05880          if (p->sig == SIG_SS7)
05881             break;
05882 #endif
05883 #ifdef HAVE_OPENR2
05884          if (p->sig == SIG_MFCR2)
05885             break;
05886 #endif
05887       case DAHDI_EVENT_ONHOOK:
05888          if (p->radio) {
05889             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
05890             p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
05891             break;
05892          }
05893          if (p->oprmode < 0)
05894          {
05895             if (p->oprmode != -1) break;
05896             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
05897             {
05898                /* Make sure it starts ringing */
05899                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
05900                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RING);
05901                save_conference(p->oprpeer);
05902                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
05903             }
05904             break;
05905          }
05906          switch (p->sig) {
05907          case SIG_FXOLS:
05908          case SIG_FXOGS:
05909          case SIG_FXOKS:
05910             p->onhooktime = time(NULL);
05911             p->fxsoffhookstate = 0;
05912             p->msgstate = -1;
05913             /* Check for some special conditions regarding call waiting */
05914             if (idx == SUB_REAL) {
05915                /* The normal line was hung up */
05916                if (p->subs[SUB_CALLWAIT].owner) {
05917                   /* There's a call waiting call, so ring the phone, but make it unowned in the mean time */
05918                   swap_subs(p, SUB_CALLWAIT, SUB_REAL);
05919                   ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
05920                   unalloc_sub(p, SUB_CALLWAIT);
05921 #if 0
05922                   p->subs[idx].needanswer = 0;
05923                   p->subs[idx].needringing = 0;
05924 #endif
05925                   p->callwaitingrepeat = 0;
05926                   p->cidcwexpire = 0;
05927                   p->owner = NULL;
05928                   /* Don't start streaming audio yet if the incoming call isn't up yet */
05929                   if (p->subs[SUB_REAL].owner->_state != AST_STATE_UP)
05930                      p->dialing = 1;
05931                   dahdi_ring_phone(p);
05932                } else if (p->subs[SUB_THREEWAY].owner) {
05933                   unsigned int mssinceflash;
05934                   /* Here we have to retain the lock on both the main channel, the 3-way channel, and
05935                      the private structure -- not especially easy or clean */
05936                   while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
05937                      /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
05938                      DLA_UNLOCK(&p->lock);
05939                      CHANNEL_DEADLOCK_AVOIDANCE(ast);
05940                      /* We can grab ast and p in that order, without worry.  We should make sure
05941                         nothing seriously bad has happened though like some sort of bizarre double
05942                         masquerade! */
05943                      DLA_LOCK(&p->lock);
05944                      if (p->owner != ast) {
05945                         ast_log(LOG_WARNING, "This isn't good...\n");
05946                         return NULL;
05947                      }
05948                   }
05949                   if (!p->subs[SUB_THREEWAY].owner) {
05950                      ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
05951                      return NULL;
05952                   }
05953                   mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
05954                   ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
05955                   if (mssinceflash < MIN_MS_SINCE_FLASH) {
05956                      /* It hasn't been long enough since the last flashook.  This is probably a bounce on
05957                         hanging up.  Hangup both channels now */
05958                      if (p->subs[SUB_THREEWAY].owner)
05959                         ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY].owner, AST_CAUSE_NO_ANSWER);
05960                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05961                      ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
05962                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05963                   } else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
05964                      if (p->transfer) {
05965                         /* In any case this isn't a threeway call anymore */
05966                         p->subs[SUB_REAL].inthreeway = 0;
05967                         p->subs[SUB_THREEWAY].inthreeway = 0;
05968                         /* Only attempt transfer if the phone is ringing; why transfer to busy tone eh? */
05969                         if (!p->transfertobusy && ast->_state == AST_STATE_BUSY) {
05970                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05971                            /* Swap subs and dis-own channel */
05972                            swap_subs(p, SUB_THREEWAY, SUB_REAL);
05973                            p->owner = NULL;
05974                            /* Ring the phone */
05975                            dahdi_ring_phone(p);
05976                         } else {
05977                            if ((res = attempt_transfer(p)) < 0) {
05978                               p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05979                               if (p->subs[SUB_THREEWAY].owner)
05980                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05981                            } else if (res) {
05982                               /* Don't actually hang up at this point */
05983                               if (p->subs[SUB_THREEWAY].owner)
05984                                  ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05985                               break;
05986                            }
05987                         }
05988                      } else {
05989                         p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
05990                         if (p->subs[SUB_THREEWAY].owner)
05991                            ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05992                      }
05993                   } else {
05994                      ast_channel_unlock(p->subs[SUB_THREEWAY].owner);
05995                      /* Swap subs and dis-own channel */
05996                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
05997                      p->owner = NULL;
05998                      /* Ring the phone */
05999                      dahdi_ring_phone(p);
06000                   }
06001                }
06002             } else {
06003                ast_log(LOG_WARNING, "Got a hangup and my index is %d?\n", idx);
06004             }
06005             /* Fall through */
06006          default:
06007             dahdi_disable_ec(p);
06008             return NULL;
06009          }
06010          break;
06011       case DAHDI_EVENT_RINGOFFHOOK:
06012          if (p->inalarm) break;
06013          if (p->oprmode < 0)
06014          {
06015             if ((p->sig == SIG_FXOLS) || (p->sig == SIG_FXOKS) || (p->sig == SIG_FXOGS))
06016             {
06017                /* Make sure it stops ringing */
06018                dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06019                tone_zone_play_tone(p->oprpeer->subs[SUB_REAL].dfd, -1);
06020                restore_conference(p->oprpeer);
06021             }
06022             break;
06023          }
06024          if (p->radio)
06025          {
06026             p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06027             p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06028             break;
06029          }
06030          /* for E911, its supposed to wait for offhook then dial
06031             the second half of the dial string */
06032          if (((mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF)) && (ast->_state == AST_STATE_DIALING_OFFHOOK)) {
06033             c = strchr(p->dialdest, '/');
06034             if (c)
06035                c++;
06036             else
06037                c = p->dialdest;
06038             if (*c) snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*0%s#", c);
06039             else ast_copy_string(p->dop.dialstr,"M*2#", sizeof(p->dop.dialstr));
06040             if (strlen(p->dop.dialstr) > 4) {
06041                memset(p->echorest, 'w', sizeof(p->echorest) - 1);
06042                strcpy(p->echorest + (p->echotraining / 401) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
06043                p->echorest[sizeof(p->echorest) - 1] = '\0';
06044                p->echobreak = 1;
06045                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
06046             } else
06047                p->echobreak = 0;
06048             if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
06049                int saveerr = errno;
06050 
06051                x = DAHDI_ONHOOK;
06052                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
06053                ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
06054                return NULL;
06055                }
06056             p->dialing = 1;
06057             return &p->subs[idx].f;
06058          }
06059          switch (p->sig) {
06060          case SIG_FXOLS:
06061          case SIG_FXOGS:
06062          case SIG_FXOKS:
06063             p->fxsoffhookstate = 1;
06064             switch (ast->_state) {
06065             case AST_STATE_RINGING:
06066                dahdi_enable_ec(p);
06067                dahdi_train_ec(p);
06068                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06069                p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06070                /* Make sure it stops ringing */
06071                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06072                ast_debug(1, "channel %d answered\n", p->channel);
06073                if (p->cidspill) {
06074                   /* Cancel any running CallerID spill */
06075                   ast_free(p->cidspill);
06076                   p->cidspill = NULL;
06077                }
06078                p->dialing = 0;
06079                p->callwaitcas = 0;
06080                if (p->confirmanswer) {
06081                   /* Ignore answer if "confirm answer" is enabled */
06082                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06083                   p->subs[idx].f.subclass = 0;
06084                } else if (!ast_strlen_zero(p->dop.dialstr)) {
06085                   /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
06086                   res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06087                   if (res < 0) {
06088                      ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06089                      p->dop.dialstr[0] = '\0';
06090                      return NULL;
06091                   } else {
06092                      ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
06093                      p->subs[idx].f.frametype = AST_FRAME_NULL;
06094                      p->subs[idx].f.subclass = 0;
06095                      p->dialing = 1;
06096                   }
06097                   p->dop.dialstr[0] = '\0';
06098                   ast_setstate(ast, AST_STATE_DIALING);
06099                } else
06100                   ast_setstate(ast, AST_STATE_UP);
06101                return &p->subs[idx].f;
06102             case AST_STATE_DOWN:
06103                ast_setstate(ast, AST_STATE_RING);
06104                ast->rings = 1;
06105                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06106                p->subs[idx].f.subclass = AST_CONTROL_OFFHOOK;
06107                ast_debug(1, "channel %d picked up\n", p->channel);
06108                return &p->subs[idx].f;
06109             case AST_STATE_UP:
06110                /* Make sure it stops ringing */
06111                dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
06112                /* Okay -- probably call waiting*/
06113                if (ast_bridged_channel(p->owner))
06114                   ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
06115                p->subs[idx].needunhold = 1;
06116                break;
06117             case AST_STATE_RESERVED:
06118                /* Start up dialtone */
06119                if (has_voicemail(p))
06120                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
06121                else
06122                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
06123                break;
06124             default:
06125                ast_log(LOG_WARNING, "FXO phone off hook in weird state %d??\n", ast->_state);
06126             }
06127             break;
06128          case SIG_FXSLS:
06129          case SIG_FXSGS:
06130          case SIG_FXSKS:
06131             if (ast->_state == AST_STATE_RING) {
06132                p->ringt = p->ringt_base;
06133             }
06134 
06135             /* If we get a ring then we cannot be in
06136              * reversed polarity. So we reset to idle */
06137             ast_debug(1, "Setting IDLE polarity due "
06138                "to ring. Old polarity was %d\n",
06139                p->polarity);
06140             p->polarity = POLARITY_IDLE;
06141 
06142             /* Fall through */
06143          case SIG_EM:
06144          case SIG_EM_E1:
06145          case SIG_EMWINK:
06146          case SIG_FEATD:
06147          case SIG_FEATDMF:
06148          case SIG_FEATDMF_TA:
06149          case SIG_E911:
06150          case SIG_FGC_CAMA:
06151          case SIG_FGC_CAMAMF:
06152          case SIG_FEATB:
06153          case SIG_SF:
06154          case SIG_SFWINK:
06155          case SIG_SF_FEATD:
06156          case SIG_SF_FEATDMF:
06157          case SIG_SF_FEATB:
06158             if (ast->_state == AST_STATE_PRERING)
06159                ast_setstate(ast, AST_STATE_RING);
06160             if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
06161                ast_debug(1, "Ring detected\n");
06162                p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06163                p->subs[idx].f.subclass = AST_CONTROL_RING;
06164             } else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
06165                ast_debug(1, "Line answered\n");
06166                if (p->confirmanswer) {
06167                   p->subs[idx].f.frametype = AST_FRAME_NULL;
06168                   p->subs[idx].f.subclass = 0;
06169                } else {
06170                   p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06171                   p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06172                   ast_setstate(ast, AST_STATE_UP);
06173                }
06174             } else if (ast->_state != AST_STATE_RING)
06175                ast_log(LOG_WARNING, "Ring/Off-hook in strange state %d on channel %d\n", ast->_state, p->channel);
06176             break;
06177          default:
06178             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06179          }
06180          break;
06181       case DAHDI_EVENT_RINGBEGIN:
06182          switch (p->sig) {
06183          case SIG_FXSLS:
06184          case SIG_FXSGS:
06185          case SIG_FXSKS:
06186             if (ast->_state == AST_STATE_RING) {
06187                p->ringt = p->ringt_base;
06188             }
06189             break;
06190          }
06191          break;
06192       case DAHDI_EVENT_RINGEROFF:
06193          if (p->inalarm) break;
06194          if ((p->radio || (p->oprmode < 0))) break;
06195          ast->rings++;
06196          if ((ast->rings > p->cidrings) && (p->cidspill)) {
06197             ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
06198             ast_free(p->cidspill);
06199             p->cidspill = NULL;
06200             p->callwaitcas = 0;
06201          }
06202          p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06203          p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06204          break;
06205       case DAHDI_EVENT_RINGERON:
06206          break;
06207       case DAHDI_EVENT_NOALARM:
06208          p->inalarm = 0;
06209 #ifdef HAVE_PRI
06210          /* Extremely unlikely but just in case */
06211          if (p->bearer)
06212             p->bearer->inalarm = 0;
06213 #endif
06214          ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
06215          manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
06216                         "Channel: %d\r\n", p->channel);
06217          break;
06218       case DAHDI_EVENT_WINKFLASH:
06219          if (p->inalarm) break;
06220          if (p->radio) break;
06221          if (p->oprmode < 0) break;
06222          if (p->oprmode > 1)
06223          {
06224             struct dahdi_params par;
06225 
06226             memset(&par, 0, sizeof(par));
06227             if (ioctl(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par) != -1)
06228             {
06229                if (!par.rxisoffhook)
06230                {
06231                   /* Make sure it stops ringing */
06232                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RINGOFF);
06233                   dahdi_set_hook(p->oprpeer->subs[SUB_REAL].dfd, DAHDI_RING);
06234                   save_conference(p);
06235                   tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06236                }
06237             }
06238             break;
06239          }
06240          /* Remember last time we got a flash-hook */
06241          p->flashtime = ast_tvnow();
06242          switch (mysig) {
06243          case SIG_FXOLS:
06244          case SIG_FXOGS:
06245          case SIG_FXOKS:
06246             ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
06247                idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
06248             p->callwaitcas = 0;
06249 
06250             if (idx != SUB_REAL) {
06251                ast_log(LOG_WARNING, "Got flash hook with index %d on channel %d?!?\n", idx, p->channel);
06252                goto winkflashdone;
06253             }
06254 
06255             if (p->subs[SUB_CALLWAIT].owner) {
06256                /* Swap to call-wait */
06257                swap_subs(p, SUB_REAL, SUB_CALLWAIT);
06258                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
06259                p->owner = p->subs[SUB_REAL].owner;
06260                ast_debug(1, "Making %s the new owner\n", p->owner->name);
06261                if (p->owner->_state == AST_STATE_RINGING) {
06262                   ast_setstate(p->owner, AST_STATE_UP);
06263                   p->subs[SUB_REAL].needanswer = 1;
06264                }
06265                p->callwaitingrepeat = 0;
06266                p->cidcwexpire = 0;
06267                /* Start music on hold if appropriate */
06268                if (!p->subs[SUB_CALLWAIT].inthreeway && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
06269                   ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
06270                      S_OR(p->mohsuggest, NULL),
06271                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06272                }
06273                p->subs[SUB_CALLWAIT].needhold = 1;
06274                if (ast_bridged_channel(p->subs[SUB_REAL].owner)) {
06275                   ast_queue_control_data(p->subs[SUB_REAL].owner, AST_CONTROL_HOLD,
06276                      S_OR(p->mohsuggest, NULL),
06277                      !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06278                }
06279                p->subs[SUB_REAL].needunhold = 1;
06280             } else if (!p->subs[SUB_THREEWAY].owner) {
06281                if (!p->threewaycalling) {
06282                   /* Just send a flash if no 3-way calling */
06283                   p->subs[SUB_REAL].needflash = 1;
06284                   goto winkflashdone;
06285                } else if (!check_for_conference(p)) {
06286                   char cid_num[256];
06287                   char cid_name[256];
06288 
06289                   cid_num[0] = 0;
06290                   cid_name[0] = 0;
06291                   if (p->dahditrcallerid && p->owner) {
06292                      if (p->owner->cid.cid_num)
06293                         ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
06294                      if (p->owner->cid.cid_name)
06295                         ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
06296                   }
06297                   /* XXX This section needs much more error checking!!! XXX */
06298                   /* Start a 3-way call if feasible */
06299                   if (!((ast->pbx) ||
06300                      (ast->_state == AST_STATE_UP) ||
06301                      (ast->_state == AST_STATE_RING))) {
06302                      ast_debug(1, "Flash when call not up or ringing\n");
06303                      goto winkflashdone;
06304                   }
06305                   if (alloc_sub(p, SUB_THREEWAY)) {
06306                      ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
06307                      goto winkflashdone;
06308                   }
06309                   /* Make new channel */
06310                   chan = dahdi_new(p, AST_STATE_RESERVED, 0, SUB_THREEWAY, 0, 0);
06311                   if (p->dahditrcallerid) {
06312                      if (!p->origcid_num)
06313                         p->origcid_num = ast_strdup(p->cid_num);
06314                      if (!p->origcid_name)
06315                         p->origcid_name = ast_strdup(p->cid_name);
06316                      ast_copy_string(p->cid_num, cid_num, sizeof(p->cid_num));
06317                      ast_copy_string(p->cid_name, cid_name, sizeof(p->cid_name));
06318                   }
06319                   /* Swap things around between the three-way and real call */
06320                   swap_subs(p, SUB_THREEWAY, SUB_REAL);
06321                   /* Disable echo canceller for better dialing */
06322                   dahdi_disable_ec(p);
06323                   res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_DIALRECALL);
06324                   if (res)
06325                      ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
06326                   p->owner = chan;
06327                   if (!chan) {
06328                      ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
06329                   } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
06330                      ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
06331                      res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
06332                      dahdi_enable_ec(p);
06333                      ast_hangup(chan);
06334                   } else {
06335                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06336                      int way3bridge = 0, cdr3way = 0;
06337 
06338                      if (!other) {
06339                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06340                      } else
06341                         way3bridge = 1;
06342 
06343                      if (p->subs[SUB_THREEWAY].owner->cdr)
06344                         cdr3way = 1;
06345 
06346                      ast_verb(3, "Started three way call on channel %d\n", p->channel);
06347 
06348                      /* Start music on hold if appropriate */
06349                      if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
06350                         ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
06351                            S_OR(p->mohsuggest, NULL),
06352                            !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
06353                      }
06354                      p->subs[SUB_THREEWAY].needhold = 1;
06355                   }
06356                }
06357             } else {
06358                /* Already have a 3 way call */
06359                if (p->subs[SUB_THREEWAY].inthreeway) {
06360                   /* Call is already up, drop the last person */
06361                   ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
06362                   /* If the primary call isn't answered yet, use it */
06363                   if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
06364                      /* Swap back -- we're dropping the real 3-way that isn't finished yet*/
06365                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06366                      p->owner = p->subs[SUB_REAL].owner;
06367                   }
06368                   /* Drop the last call and stop the conference */
06369                   ast_verb(3, "Dropping three-way call on %s\n", p->subs[SUB_THREEWAY].owner->name);
06370                   p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06371                   p->subs[SUB_REAL].inthreeway = 0;
06372                   p->subs[SUB_THREEWAY].inthreeway = 0;
06373                } else {
06374                   /* Lets see what we're up to */
06375                   if (((ast->pbx) || (ast->_state == AST_STATE_UP)) &&
06376                      (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
06377                      int otherindex = SUB_THREEWAY;
06378                      struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
06379                      int way3bridge = 0, cdr3way = 0;
06380 
06381                      if (!other) {
06382                         other = ast_bridged_channel(p->subs[SUB_REAL].owner);
06383                      } else
06384                         way3bridge = 1;
06385 
06386                      if (p->subs[SUB_THREEWAY].owner->cdr)
06387                         cdr3way = 1;
06388 
06389                      ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
06390                      /* Put them in the threeway, and flip */
06391                      p->subs[SUB_THREEWAY].inthreeway = 1;
06392                      p->subs[SUB_REAL].inthreeway = 1;
06393                      if (ast->_state == AST_STATE_UP) {
06394                         swap_subs(p, SUB_THREEWAY, SUB_REAL);
06395                         otherindex = SUB_REAL;
06396                      }
06397                      if (p->subs[otherindex].owner && ast_bridged_channel(p->subs[otherindex].owner))
06398                         ast_queue_control(p->subs[otherindex].owner, AST_CONTROL_UNHOLD);
06399                      p->subs[otherindex].needunhold = 1;
06400                      p->owner = p->subs[SUB_REAL].owner;
06401                      if (ast->_state == AST_STATE_RINGING) {
06402                         ast_debug(1, "Enabling ringtone on real and threeway\n");
06403                         res = tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
06404                         res = tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, DAHDI_TONE_RINGTONE);
06405                      }
06406                   } else {
06407                      ast_verb(3, "Dumping incomplete call on on %s\n", p->subs[SUB_THREEWAY].owner->name);
06408                      swap_subs(p, SUB_THREEWAY, SUB_REAL);
06409                      p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
06410                      p->owner = p->subs[SUB_REAL].owner;
06411                      if (p->subs[SUB_REAL].owner && ast_bridged_channel(p->subs[SUB_REAL].owner))
06412                         ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
06413                      p->subs[SUB_REAL].needunhold = 1;
06414                      dahdi_enable_ec(p);
06415                   }
06416                }
06417             }
06418 winkflashdone:
06419             update_conf(p);
06420             break;
06421          case SIG_EM:
06422          case SIG_EM_E1:
06423          case SIG_FEATD:
06424          case SIG_SF:
06425          case SIG_SFWINK:
06426          case SIG_SF_FEATD:
06427          case SIG_FXSLS:
06428          case SIG_FXSGS:
06429             if (option_debug) {
06430                if (p->dialing)
06431                   ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
06432                else
06433                   ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
06434             }
06435             break;
06436          case SIG_FEATDMF_TA:
06437             switch (p->whichwink) {
06438             case 0:
06439                ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06440                snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
06441                break;
06442             case 1:
06443                ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
06444                break;
06445             case 2:
06446                ast_log(LOG_WARNING, "Received unexpected wink on channel of type SIG_FEATDMF_TA\n");
06447                return NULL;
06448             }
06449             p->whichwink++;
06450             /* Fall through */
06451          case SIG_FEATDMF:
06452          case SIG_E911:
06453          case SIG_FGC_CAMAMF:
06454          case SIG_FGC_CAMA:
06455          case SIG_FEATB:
06456          case SIG_SF_FEATDMF:
06457          case SIG_SF_FEATB:
06458          case SIG_EMWINK:
06459             /* FGD MF and EMWINK *Must* wait for wink */
06460             if (!ast_strlen_zero(p->dop.dialstr)) {
06461                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06462                if (res < 0) {
06463                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06464                   p->dop.dialstr[0] = '\0';
06465                   return NULL;
06466                } else
06467                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06468             }
06469             p->dop.dialstr[0] = '\0';
06470             break;
06471          default:
06472             ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
06473          }
06474          break;
06475       case DAHDI_EVENT_HOOKCOMPLETE:
06476          if (p->inalarm) break;
06477          if ((p->radio || (p->oprmode < 0))) break;
06478          if (p->waitingfordt.tv_sec) break;
06479          switch (mysig) {
06480          case SIG_FXSLS:  /* only interesting for FXS */
06481          case SIG_FXSGS:
06482          case SIG_FXSKS:
06483          case SIG_EM:
06484          case SIG_EM_E1:
06485          case SIG_EMWINK:
06486          case SIG_FEATD:
06487          case SIG_SF:
06488          case SIG_SFWINK:
06489          case SIG_SF_FEATD:
06490             if (!ast_strlen_zero(p->dop.dialstr)) {
06491                res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
06492                if (res < 0) {
06493                   ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
06494                   p->dop.dialstr[0] = '\0';
06495                   return NULL;
06496                } else
06497                   ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
06498             }
06499             p->dop.dialstr[0] = '\0';
06500             p->dop.op = DAHDI_DIAL_OP_REPLACE;
06501             break;
06502          case SIG_FEATDMF:
06503          case SIG_FEATDMF_TA:
06504          case SIG_E911:
06505          case SIG_FGC_CAMA:
06506          case SIG_FGC_CAMAMF:
06507          case SIG_FEATB:
06508          case SIG_SF_FEATDMF:
06509          case SIG_SF_FEATB:
06510             ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
06511             break;
06512          default:
06513             break;
06514          }
06515          break;
06516       case DAHDI_EVENT_POLARITY:
06517          /*
06518           * If we get a Polarity Switch event, this could be
06519           * due to line seizure, remote end connect or remote end disconnect.
06520           *
06521           * Check to see if we should change the polarity state and
06522           * mark the channel as UP or if this is an indication
06523           * of remote end disconnect.
06524           */
06525 
06526          if (p->polarityonanswerdelay > 0) {
06527             /* check if event is not too soon after OffHook or Answer */
06528             if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
06529                switch (ast->_state) {
06530                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06531                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06532                   if (p->answeronpolarityswitch) {
06533                      ast_debug(1, "Answering on polarity switch! channel %d\n", p->channel);
06534                      ast_setstate(p->owner, AST_STATE_UP);
06535                      p->polarity = POLARITY_REV;
06536                      if (p->hanguponpolarityswitch) {
06537                         p->polaritydelaytv = ast_tvnow();
06538                      }
06539                   } else {
06540                      ast_debug(1, "Ignore Answer on polarity switch, channel %d\n", p->channel);
06541                   }
06542                   break;
06543 
06544                case AST_STATE_UP:         /*!< Line is up */
06545                case AST_STATE_RING:       /*!< Line is ringing */
06546                   if (p->hanguponpolarityswitch) {
06547                      ast_debug(1, "HangingUp on polarity switch! channel %d\n", p->channel);
06548                      ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
06549                      p->polarity = POLARITY_IDLE;
06550                   } else {
06551                      ast_debug(1, "Ignore Hangup on polarity switch, channel %d\n", p->channel);
06552                   }
06553                   break;
06554 
06555                case AST_STATE_DOWN:       /*!< Channel is down and available */
06556                case AST_STATE_RESERVED:      /*!< Channel is down, but reserved */
06557                case AST_STATE_OFFHOOK:       /*!< Channel is off hook */
06558                case AST_STATE_BUSY:       /*!< Line is busy */
06559                case AST_STATE_DIALING_OFFHOOK:     /*!< Digits (or equivalent) have been dialed while offhook */
06560                case AST_STATE_PRERING:       /*!< Channel has detected an incoming call and is waiting for ring */
06561                default:
06562                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06563                      ast_debug(1, "Ignoring Polarity switch on channel %d, state %d\n", p->channel, ast->_state);
06564                   }
06565                }
06566 
06567             } else {
06568                /* event is too soon after OffHook or Answer */
06569                switch (ast->_state) {
06570                case AST_STATE_DIALING:       /*!< Digits (or equivalent) have been dialed */
06571                case AST_STATE_RINGING:       /*!< Remote end is ringing */
06572                   if (p->answeronpolarityswitch) {
06573                      ast_debug(1, "Polarity switch detected but NOT answering (too close to OffHook event) on channel %d, state %d\n", p->channel, ast->_state);
06574                   }
06575                   break;
06576 
06577                case AST_STATE_UP:         /*!< Line is up */
06578                case AST_STATE_RING:       /*!< Line is ringing */
06579                   if (p->hanguponpolarityswitch) {
06580                      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);
06581                   }
06582                   break;
06583 
06584                default: 
06585                   if (p->answeronpolarityswitch || p->hanguponpolarityswitch) {
06586                      ast_debug(1, "Polarity switch detected (too close to previous event) on channel %d, state %d\n", p->channel, ast->_state);
06587                   }
06588                }
06589             }
06590          }
06591 
06592          /* Added more log_debug information below to provide a better indication of what is going on */
06593          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) );
06594          break;
06595       default:
06596          ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
06597    }
06598    return &p->subs[idx].f;
06599 }

static int dahdi_hangup ( struct ast_channel ast  )  [static]

Definition at line 4313 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::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, 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::faxbuffersinuse, dahdi_pvt::faxhandled, dahdi_pvt::fxsoffhookstate, dahdi_pvt::guardtime, ast_channel::hangupcause, dahdi_pvt::hidecallerid, iflist, iflock, dahdi_pvt::ignoredtmf, dahdi_subchannel::inthreeway, dahdi_pvt::law, dahdi_subchannel::linear, dahdi_pvt::lock, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mohsuggest, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needringing, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_pvt::oprmode, dahdi_pvt::origcid_name, dahdi_pvt::origcid_num, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_subchannel::owner, pbx_builtin_getvar_helper(), dahdi_pvt::permcallwaiting, dahdi_pvt::permhidecallerid, dahdi_pvt::polarity, POLARITY_IDLE, dahdi_pvt::prev, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::proceeding, dahdi_pvt::progress, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::rdnis, dahdi_pvt::realcall, reset_conf(), restart_monitor(), dahdi_pvt::restartpending, restore_gains(), dahdi_pvt::ringt, dahdi_pvt::rlt, S_OR, dahdi_pvt::setup_ack, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXOGS, SIG_FXOKS, SIG_FXOLS, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_MFCR2, 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(), update_conf(), and dahdi_pvt::waitingfordt.

Referenced by pri_dchannel().

04314 {
04315    int res;
04316    int idx,x, law;
04317    /*static int restore_gains(struct dahdi_pvt *p);*/
04318    struct dahdi_pvt *p = ast->tech_pvt;
04319    struct dahdi_pvt *tmp = NULL;
04320    struct dahdi_pvt *prev = NULL;
04321    struct dahdi_params par;
04322 
04323    ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
04324    if (!ast->tech_pvt) {
04325       ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
04326       return 0;
04327    }
04328 
04329    ast_mutex_lock(&p->lock);
04330 
04331    idx = dahdi_get_index(ast, p, 1);
04332 
04333    if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04334       x = 1;
04335       ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04336       p->cid_num[0] = '\0';
04337       p->cid_name[0] = '\0';
04338    }
04339 
04340    x = 0;
04341    dahdi_confmute(p, 0);
04342    p->muting = 0;
04343    restore_gains(p);
04344    if (p->origcid_num) {
04345       ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
04346       ast_free(p->origcid_num);
04347       p->origcid_num = NULL;
04348    }
04349    if (p->origcid_name) {
04350       ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
04351       ast_free(p->origcid_name);
04352       p->origcid_name = NULL;
04353    }
04354    if (p->dsp)
04355       ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
04356    p->exten[0] = '\0';
04357 
04358    ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
04359       p->channel, idx, p->subs[SUB_REAL].dfd, p->subs[SUB_CALLWAIT].dfd, p->subs[SUB_THREEWAY].dfd);
04360    p->ignoredtmf = 0;
04361 
04362    if (idx > -1) {
04363       /* Real channel, do some fixup */
04364       p->subs[idx].owner = NULL;
04365       p->subs[idx].needanswer = 0;
04366       p->subs[idx].needflash = 0;
04367       p->subs[idx].needringing = 0;
04368       p->subs[idx].needbusy = 0;
04369       p->subs[idx].needcongestion = 0;
04370       p->subs[idx].linear = 0;
04371       p->subs[idx].needcallerid = 0;
04372       p->polarity = POLARITY_IDLE;
04373       dahdi_setlinear(p->subs[idx].dfd, 0);
04374       if (idx == SUB_REAL) {
04375          if ((p->subs[SUB_CALLWAIT].dfd > -1) && (p->subs[SUB_THREEWAY].dfd > -1)) {
04376             ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
04377             if (p->subs[SUB_CALLWAIT].inthreeway) {
04378                /* We had flipped over to answer a callwait and now it's gone */
04379                ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
04380                /* Move to the call-wait, but un-own us until they flip back. */
04381                swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04382                unalloc_sub(p, SUB_CALLWAIT);
04383                p->owner = NULL;
04384             } else {
04385                /* The three way hung up, but we still have a call wait */
04386                ast_debug(1, "We were in the threeway and have a callwait still.  Ditching the threeway.\n");
04387                swap_subs(p, SUB_THREEWAY, SUB_REAL);
04388                unalloc_sub(p, SUB_THREEWAY);
04389                if (p->subs[SUB_REAL].inthreeway) {
04390                   /* This was part of a three way call.  Immediately make way for
04391                      another call */
04392                   ast_debug(1, "Call was complete, setting owner to former third call\n");
04393                   p->owner = p->subs[SUB_REAL].owner;
04394                } else {
04395                   /* This call hasn't been completed yet...  Set owner to NULL */
04396                   ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04397                   p->owner = NULL;
04398                }
04399                p->subs[SUB_REAL].inthreeway = 0;
04400             }
04401          } else if (p->subs[SUB_CALLWAIT].dfd > -1) {
04402             /* Move to the call-wait and switch back to them. */
04403             swap_subs(p, SUB_CALLWAIT, SUB_REAL);
04404             unalloc_sub(p, SUB_CALLWAIT);
04405             p->owner = p->subs[SUB_REAL].owner;
04406             if (p->owner->_state != AST_STATE_UP)
04407                p->subs[SUB_REAL].needanswer = 1;
04408             if (ast_bridged_channel(p->subs[SUB_REAL].owner))
04409                ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
04410          } else if (p->subs[SUB_THREEWAY].dfd > -1) {
04411             swap_subs(p, SUB_THREEWAY, SUB_REAL);
04412             unalloc_sub(p, SUB_THREEWAY);
04413             if (p->subs[SUB_REAL].inthreeway) {
04414                /* This was part of a three way call.  Immediately make way for
04415                   another call */
04416                ast_debug(1, "Call was complete, setting owner to former third call\n");
04417                p->owner = p->subs[SUB_REAL].owner;
04418             } else {
04419                /* This call hasn't been completed yet...  Set owner to NULL */
04420                ast_debug(1, "Call was incomplete, setting owner to NULL\n");
04421                p->owner = NULL;
04422             }
04423             p->subs[SUB_REAL].inthreeway = 0;
04424          }
04425       } else if (idx == SUB_CALLWAIT) {
04426          /* Ditch the holding callwait call, and immediately make it availabe */
04427          if (p->subs[SUB_CALLWAIT].inthreeway) {
04428             /* This is actually part of a three way, placed on hold.  Place the third part
04429                on music on hold now */
04430             if (p->subs[SUB_THREEWAY].owner && ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
04431                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
04432                   S_OR(p->mohsuggest, NULL),
04433                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04434             }
04435             p->subs[SUB_THREEWAY].inthreeway = 0;
04436             /* Make it the call wait now */
04437             swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
04438             unalloc_sub(p, SUB_THREEWAY);
04439          } else
04440             unalloc_sub(p, SUB_CALLWAIT);
04441       } else if (idx == SUB_THREEWAY) {
04442          if (p->subs[SUB_CALLWAIT].inthreeway) {
04443             /* The other party of the three way call is currently in a call-wait state.
04444                Start music on hold for them, and take the main guy out of the third call */
04445             if (p->subs[SUB_CALLWAIT].owner && ast_bridged_channel(p->subs[SUB_CALLWAIT].owner)) {
04446                ast_queue_control_data(p->subs[SUB_CALLWAIT].owner, AST_CONTROL_HOLD,
04447                   S_OR(p->mohsuggest, NULL),
04448                   !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
04449             }
04450             p->subs[SUB_CALLWAIT].inthreeway = 0;
04451          }
04452          p->subs[SUB_REAL].inthreeway = 0;
04453          /* If this was part of a three way call index, let us make
04454             another three way call */
04455          unalloc_sub(p, SUB_THREEWAY);
04456       } else {
04457          /* This wasn't any sort of call, but how are we an index? */
04458          ast_log(LOG_WARNING, "Index found but not any type of call?\n");
04459       }
04460    }
04461 
04462    if (!p->subs[SUB_REAL].owner && !p->subs[SUB_CALLWAIT].owner && !p->subs[SUB_THREEWAY].owner) {
04463       p->owner = NULL;
04464       p->ringt = 0;
04465       p->distinctivering = 0;
04466       p->confirmanswer = 0;
04467       p->cidrings = 1;
04468       p->outgoing = 0;
04469       p->digital = 0;
04470       p->faxhandled = 0;
04471       p->pulsedial = 0;
04472       p->onhooktime = time(NULL);
04473 #if defined(HAVE_PRI) || defined(HAVE_SS7)
04474       p->proceeding = 0;
04475       p->dialing = 0;
04476       p->progress = 0;
04477       p->alerting = 0;
04478       p->setup_ack = 0;
04479       p->rlt = 0;
04480 #endif
04481       if (p->dsp) {
04482          ast_dsp_free(p->dsp);
04483          p->dsp = NULL;
04484       }
04485 
04486       if (p->faxbuffersinuse) {
04487          /* faxbuffers are in use, revert them */
04488          struct dahdi_bufferinfo bi = {
04489             .txbufpolicy = p->buf_policy,
04490             .rxbufpolicy = p->buf_policy,
04491             .bufsize = p->bufsize,
04492             .numbufs = p->buf_no
04493          };
04494          int bpres;
04495 
04496          if ((bpres = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi)) < 0) {
04497             ast_log(LOG_WARNING, "Channel '%s' unable to revert faxbuffer policy: %s\n", ast->name, strerror(errno));
04498          }
04499          p->faxbuffersinuse = 0;
04500       }
04501 
04502       law = DAHDI_LAW_DEFAULT;
04503       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
04504       if (res < 0)
04505          ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
04506       /* Perform low level hangup if no owner left */
04507 #ifdef HAVE_SS7
04508       if (p->ss7) {
04509          if (p->ss7call) {
04510             if (!ss7_grab(p, p->ss7)) {
04511                if (!p->alreadyhungup) {
04512                   const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
04513                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04514 
04515                   if (cause) {
04516                      if (atoi(cause))
04517                         icause = atoi(cause);
04518                   }
04519                   isup_rel(p->ss7->ss7, p->ss7call, icause);
04520                   ss7_rel(p->ss7);
04521                   p->alreadyhungup = 1;
04522                } else
04523                   ast_log(LOG_WARNING, "Trying to hangup twice!\n");
04524             } else {
04525                ast_log(LOG_WARNING, "Unable to grab SS7 on CIC %d\n", p->cic);
04526                res = -1;
04527             }
04528          }
04529       }
04530 #endif
04531 #ifdef HAVE_OPENR2
04532       p->cid_num[0] = '\0';
04533       p->cid_name[0] = '\0';
04534       if (p->mfcr2 && p->mfcr2call && openr2_chan_get_direction(p->r2chan) != OR2_DIR_STOPPED) {
04535          ast_log(LOG_DEBUG, "disconnecting MFC/R2 call on chan %d\n", p->channel);
04536          /* If it's an incoming call, check the mfcr2_forced_release setting */
04537          if (openr2_chan_get_direction(p->r2chan) == OR2_DIR_BACKWARD && p->mfcr2_forced_release) {
04538             dahdi_r2_disconnect_call(p, OR2_CAUSE_FORCED_RELEASE);
04539          } else {
04540             const char *r2causestr = pbx_builtin_getvar_helper(ast, "MFCR2_CAUSE");
04541             int r2cause_user = r2causestr ? atoi(r2causestr) : 0;
04542             openr2_call_disconnect_cause_t r2cause = r2cause_user ? dahdi_ast_cause_to_r2_cause(r2cause_user)
04543                                                              : dahdi_ast_cause_to_r2_cause(ast->hangupcause);
04544             dahdi_r2_disconnect_call(p, r2cause);
04545          }
04546       } else if (p->mfcr2call) {
04547          ast_log(LOG_DEBUG, "Clearing call request on channel %d\n", p->channel);
04548          /* since ast_request() was called but not ast_call() we have not yet dialed
04549          and the openr2 stack will not call on_call_end callback, we need to unset
04550          the mfcr2call flag and bump the monitor count so the monitor thread can take
04551          care of this channel events from now on */
04552          p->mfcr2call = 0;
04553       }
04554 #endif
04555 #ifdef HAVE_PRI
04556       if (p->pri) {
04557 #ifdef SUPPORT_USERUSER
04558          const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
04559 #endif
04560 
04561          /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
04562          if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
04563             if (!pri_grab(p, p->pri)) {
04564                if (p->alreadyhungup) {
04565                   ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
04566 
04567 #ifdef SUPPORT_USERUSER
04568                   pri_call_set_useruser(p->call, useruser);
04569 #endif
04570 
04571                   pri_hangup(p->pri->pri, p->call, -1);
04572                   p->call = NULL;
04573                   if (p->bearer)
04574                      p->bearer->call = NULL;
04575                } else {
04576                   const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
04577                   int icause = ast->hangupcause ? ast->hangupcause : -1;
04578                   ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
04579 
04580 #ifdef SUPPORT_USERUSER
04581                   pri_call_set_useruser(p->call, useruser);
04582 #endif
04583 
04584                   p->alreadyhungup = 1;
04585                   if (p->bearer)
04586                      p->bearer->alreadyhungup = 1;
04587                   if (cause) {
04588                      if (atoi(cause))
04589                         icause = atoi(cause);
04590                   }
04591                   pri_hangup(p->pri->pri, p->call, icause);
04592                }
04593                if (res < 0)
04594                   ast_log(LOG_WARNING, "pri_disconnect failed\n");
04595                pri_rel(p->pri);
04596             } else {
04597                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
04598                res = -1;
04599             }
04600          } else {
04601             if (p->bearer)
04602                ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
04603             p->call = NULL;
04604             res = 0;
04605          }
04606       }
04607 #endif
04608       if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
04609          && (p->sig != SIG_BRI)
04610          && (p->sig != SIG_BRI_PTMP))
04611          && (p->sig != SIG_MFCR2))
04612          res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
04613       if (res < 0) {
04614          ast_log(LOG_WARNING, "Unable to hangup line %s\n", ast->name);
04615       }
04616       switch (p->sig) {
04617       case SIG_FXOGS:
04618       case SIG_FXOLS:
04619       case SIG_FXOKS:
04620          memset(&par, 0, sizeof(par));
04621          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
04622          if (!res) {
04623 #if 0
04624             ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
04625 #endif
04626             /* If they're off hook, try playing congestion */
04627             if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
04628                tone_zone_play_tone(p->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
04629             else
04630                tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04631             p->fxsoffhookstate = par.rxisoffhook;
04632          }
04633          break;
04634       case SIG_FXSGS:
04635       case SIG_FXSLS:
04636       case SIG_FXSKS:
04637          /* Make sure we're not made available for at least two seconds assuming
04638             we were actually used for an inbound or outbound call. */
04639          if (ast->_state != AST_STATE_RESERVED) {
04640             time(&p->guardtime);
04641             p->guardtime += 2;
04642          }
04643          break;
04644       default:
04645          tone_zone_play_tone(p->subs[SUB_REAL].dfd, -1);
04646       }
04647       if (p->cidspill)
04648          ast_free(p->cidspill);
04649       if (p->sig)
04650          dahdi_disable_ec(p);
04651       x = 0;
04652       ast_channel_setoption(ast,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
04653       ast_channel_setoption(ast,AST_OPTION_TDD,&x,sizeof(char),0);
04654       p->didtdd = 0;
04655       p->cidspill = NULL;
04656       p->callwaitcas = 0;
04657       p->callwaiting = p->permcallwaiting;
04658       p->hidecallerid = p->permhidecallerid;
04659       p->waitingfordt.tv_sec = 0;
04660       p->dialing = 0;
04661       p->rdnis[0] = '\0';
04662       update_conf(p);
04663       reset_conf(p);
04664       /* Restore data mode */
04665       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
04666          x = 0;
04667          ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
04668       }
04669 #ifdef HAVE_PRI
04670       if (p->bearer) {
04671          ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
04672          /* Free up the bearer channel as well, and
04673             don't use its file descriptor anymore */
04674          update_conf(p->bearer);
04675          reset_conf(p->bearer);
04676          p->bearer->owner = NULL;
04677          p->bearer->realcall = NULL;
04678          p->bearer = NULL;
04679          p->subs[SUB_REAL].dfd = -1;
04680          p->pri = NULL;
04681       }
04682 #endif
04683       if (num_restart_pending == 0)
04684          restart_monitor();
04685    }
04686 
04687    p->callwaitingrepeat = 0;
04688    p->cidcwexpire = 0;
04689    p->oprmode = 0;
04690    ast->tech_pvt = NULL;
04691    ast_mutex_unlock(&p->lock);
04692    ast_module_unref(ast_module_info->self);
04693    ast_verb(3, "Hungup '%s'\n", ast->name);
04694 
04695    ast_mutex_lock(&iflock);
04696 
04697    if (p->restartpending) {
04698       num_restart_pending--;
04699    }
04700 
04701    tmp = iflist;
04702    prev = NULL;
04703    if (p->destroy) {
04704       while (tmp) {
04705          if (tmp == p) {
04706             destroy_channel(prev, tmp, 0);
04707             break;
04708          } else {
04709             prev = tmp;
04710             tmp = tmp->next;
04711          }
04712       }
04713    }
04714    ast_mutex_unlock(&iflock);
04715    return 0;
04716 }

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

Definition at line 7170 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, ast_channel::name, dahdi_pvt::outgoing, dahdi_pri::pri, dahdi_pvt::pri, pri_grab(), pri_rel(), dahdi_pvt::priindication_oob, dahdi_pvt::prioffset, dahdi_pvt::proceeding, dahdi_pvt::progress, PVT_TO_CHANNEL, dahdi_pvt::radio, dahdi_pvt::rlt, dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_FXSGS, SIG_FXSKS, SIG_FXSLS, SIG_PRI, SIG_SS7, dahdi_pvt::span, 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().

07171 {
07172    struct dahdi_pvt *p = chan->tech_pvt;
07173    int res=-1;
07174    int idx;
07175    int func = DAHDI_FLASH;
07176    ast_mutex_lock(&p->lock);
07177    idx = dahdi_get_index(chan, p, 0);
07178    ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
07179 #ifdef HAVE_OPENR2
07180    if (p->mfcr2 && !p->mfcr2_call_accepted) {
07181       ast_mutex_unlock(&p->lock);
07182       /* if this is an R2 call and the call is not yet accepted, we don't want the
07183          tone indications to mess up with the MF tones */
07184       return 0;
07185    }
07186 #endif
07187    if (idx == SUB_REAL) {
07188       switch (condition) {
07189       case AST_CONTROL_BUSY:
07190 #ifdef HAVE_PRI
07191          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07192             chan->hangupcause = AST_CAUSE_USER_BUSY;
07193             chan->_softhangup |= AST_SOFTHANGUP_DEV;
07194             res = 0;
07195          } else if (!p->progress &&
07196                ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07197                && p->pri && !p->outgoing) {
07198             if (p->pri->pri) {
07199                if (!pri_grab(p, p->pri)) {
07200 #ifdef HAVE_PRI_PROG_W_CAUSE
07201                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */
07202 #else
07203                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07204 #endif
07205                   pri_rel(p->pri);
07206                }
07207                else
07208                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07209             }
07210             p->progress = 1;
07211             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07212          } else
07213 #endif
07214             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
07215          break;
07216       case AST_CONTROL_RINGING:
07217 #ifdef HAVE_PRI
07218          if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07219                && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07220             if (p->pri->pri) {
07221                if (!pri_grab(p, p->pri)) {
07222                   pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07223                   pri_rel(p->pri);
07224                }
07225                else
07226                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07227             }
07228             p->alerting = 1;
07229          }
07230 
07231 #endif
07232 #ifdef HAVE_SS7
07233          if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
07234             if (p->ss7->ss7) {
07235                ss7_grab(p, p->ss7);
07236 
07237                if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07238                   p->rlt = 1;
07239                if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
07240                   isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
07241                p->alerting = 1;
07242                ss7_rel(p->ss7);
07243             }
07244          }
07245 #endif
07246 
07247          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_RINGTONE);
07248 
07249          if (chan->_state != AST_STATE_UP) {
07250             if ((chan->_state != AST_STATE_RING) ||
07251                ((p->sig != SIG_FXSKS) &&
07252              (p->sig != SIG_FXSLS) &&
07253              (p->sig != SIG_FXSGS)))
07254             ast_setstate(chan, AST_STATE_RINGING);
07255          }
07256          break;
07257       case AST_CONTROL_PROCEEDING:
07258          ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
07259 #ifdef HAVE_PRI
07260          if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07261                && p->pri && !p->outgoing) {
07262             if (p->pri->pri) {
07263                if (!pri_grab(p, p->pri)) {
07264                   pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07265                   pri_rel(p->pri);
07266                }
07267                else
07268                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07269             }
07270             p->proceeding = 1;
07271             p->dialing = 0;
07272          }
07273 #endif
07274 #ifdef HAVE_SS7
07275          /* This IF sends the FAR for an answered ALEG call */
07276          if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
07277             if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
07278                p->rlt = 1;
07279          }
07280 
07281          if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
07282             if (p->ss7->ss7) {
07283                ss7_grab(p, p->ss7);
07284                isup_acm(p->ss7->ss7, p->ss7call);
07285                p->proceeding = 1;
07286                ss7_rel(p->ss7);
07287 
07288             }
07289          }
07290 #endif
07291          /* don't continue in ast_indicate */
07292          res = 0;
07293          break;
07294       case AST_CONTROL_PROGRESS:
07295          ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
07296 #ifdef HAVE_PRI
07297          p->digital = 0;   /* Digital-only calls isn't allows any inband progress messages */
07298          if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07299                && p->pri && !p->outgoing) {
07300             if (p->pri->pri) {
07301                if (!pri_grab(p, p->pri)) {
07302 #ifdef HAVE_PRI_PROG_W_CAUSE
07303                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
07304 #else
07305                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07306 #endif
07307                   pri_rel(p->pri);
07308                }
07309                else
07310                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07311             }
07312             p->progress = 1;
07313          }
07314 #endif
07315 #ifdef HAVE_SS7
07316          if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
07317             if (p->ss7->ss7) {
07318                ss7_grab(p, p->ss7);
07319                isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
07320                p->progress = 1;
07321                ss7_rel(p->ss7);
07322                /* enable echo canceler here on SS7 calls */
07323                dahdi_enable_ec(p);
07324 
07325             }
07326          }
07327 #endif
07328          /* don't continue in ast_indicate */
07329          res = 0;
07330          break;
07331       case AST_CONTROL_CONGESTION:
07332          chan->hangupcause = AST_CAUSE_CONGESTION;
07333 #ifdef HAVE_PRI
07334          if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
07335             chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
07336             chan->_softhangup |= AST_SOFTHANGUP_DEV;
07337             res = 0;
07338          } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
07339                && p->pri && !p->outgoing) {
07340             if (p->pri) {
07341                if (!pri_grab(p, p->pri)) {
07342 #ifdef HAVE_PRI_PROG_W_CAUSE
07343                   pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
07344 #else
07345                   pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
07346 #endif
07347                   pri_rel(p->pri);
07348                } else
07349                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07350             }
07351             p->progress = 1;
07352             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07353          } else
07354 #endif
07355             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
07356          break;
07357       case AST_CONTROL_HOLD:
07358 #ifdef HAVE_PRI
07359          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07360             if (!pri_grab(p, p->pri)) {
07361                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
07362                pri_rel(p->pri);
07363             } else
07364                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07365          } else
07366 #endif
07367             ast_moh_start(chan, data, p->mohinterpret);
07368          break;
07369       case AST_CONTROL_UNHOLD:
07370 #ifdef HAVE_PRI
07371          if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
07372             if (!pri_grab(p, p->pri)) {
07373                res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
07374                pri_rel(p->pri);
07375             } else
07376                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07377          } else
07378 #endif
07379             ast_moh_stop(chan);
07380          break;
07381       case AST_CONTROL_RADIO_KEY:
07382          if (p->radio)
07383             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_OFFHOOK);
07384          res = 0;
07385          break;
07386       case AST_CONTROL_RADIO_UNKEY:
07387          if (p->radio)
07388             res = dahdi_set_hook(p->subs[idx].dfd, DAHDI_RINGOFF);
07389          res = 0;
07390          break;
07391       case AST_CONTROL_FLASH:
07392          /* flash hookswitch */
07393          if (ISTRUNK(p) && (p->sig != SIG_PRI)) {
07394             /* Clear out the dial buffer */
07395             p->dop.dialstr[0] = '\0';
07396             if ((ioctl(p->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
07397                ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
07398                   chan->name, strerror(errno));
07399             } else
07400                res = 0;
07401          } else
07402             res = 0;
07403          break;
07404       case AST_CONTROL_SRCUPDATE:
07405          res = 0;
07406          break;
07407       case -1:
07408          res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07409          break;
07410       }
07411    } else
07412       res = 0;
07413    ast_mutex_unlock(&p->lock);
07414    return res;
07415 }

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

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

05100                                                                           {
05101    int x;
05102    if (!slave || !master) {
05103       ast_log(LOG_WARNING, "Tried to link to/from NULL??\n");
05104       return;
05105    }
05106    for (x = 0; x < MAX_SLAVES; x++) {
05107       if (!master->slaves[x]) {
05108          master->slaves[x] = slave;
05109          break;
05110       }
05111    }
05112    if (x >= MAX_SLAVES) {
05113       ast_log(LOG_WARNING, "Replacing slave %d with new slave, %d\n", master->slaves[MAX_SLAVES - 1]->channel, slave->channel);
05114       master->slaves[MAX_SLAVES - 1] = slave;
05115    }
05116    if (slave->master)
05117       ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
05118    slave->master = master;
05119 
05120    ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
05121 }

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

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

11222 {
11223    if (p->loopedback != enable) {
11224       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_LOOPBACK, &enable)) {
11225          ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
11226          return;
11227       }
11228       p->loopedback = enable;
11229    }
11230 }

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 7417 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_buffer(), 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, DSP_FEATURE_WAITDIALTONE, 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::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, SUB_REAL, dahdi_pvt::subs, ast_channel::tech, ast_channel::tech_pvt, ast_channel::transfercapability, dahdi_pri::trunkgroup, ast_variable::value, dahdi_pvt::vars, dahdi_pvt::waitfordialtone, and ast_channel::writeformat.

Referenced by dahdi_handle_event(), dahdi_request(), handle_init_event(), mwi_thread(), pri_dchannel(), and ss7_start_call().

07418 {
07419    struct ast_channel *tmp;
07420    int deflaw;
07421    int res;
07422    int x,y;
07423    int features;
07424    struct ast_str *chan_name;
07425    struct ast_variable *v;
07426    struct dahdi_params ps;
07427    if (i->subs[idx].owner) {
07428       ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[idx]);
07429       return NULL;
07430    }
07431    y = 1;
07432    chan_name = ast_str_alloca(32);
07433    do {
07434 #ifdef HAVE_PRI
07435       if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
07436          ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
07437       else
07438 #endif
07439       if (i->channel == CHAN_PSEUDO)
07440          ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
07441       else
07442          ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
07443       for (x = 0; x < 3; x++) {
07444          if ((idx != x) && i->subs[x].owner && !strcasecmp(ast_str_buffer(chan_name), i->subs[x].owner->name + 6))
07445             break;
07446       }
07447       y++;
07448    } while (x < 3);
07449    tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "DAHDI/%s", ast_str_buffer(chan_name));
07450    if (!tmp)
07451       return NULL;
07452    tmp->tech = &dahdi_tech;
07453    memset(&ps, 0, sizeof(ps));
07454    ps.channo = i->channel;
07455    res = ioctl(i->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps);
07456    if (res) {
07457       ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
07458       ps.curlaw = DAHDI_LAW_MULAW;
07459    }
07460    if (ps.curlaw == DAHDI_LAW_ALAW)
07461       deflaw = AST_FORMAT_ALAW;
07462    else
07463       deflaw = AST_FORMAT_ULAW;
07464    if (law) {
07465       if (law == DAHDI_LAW_ALAW)
07466          deflaw = AST_FORMAT_ALAW;
07467       else
07468          deflaw = AST_FORMAT_ULAW;
07469    }
07470    ast_channel_set_fd(tmp, 0, i->subs[idx].dfd);
07471    tmp->nativeformats = deflaw;
07472    /* Start out assuming ulaw since it's smaller :) */
07473    tmp->rawreadformat = deflaw;
07474    tmp->readformat = deflaw;
07475    tmp->rawwriteformat = deflaw;
07476    tmp->writeformat = deflaw;
07477    i->subs[idx].linear = 0;
07478    dahdi_setlinear(i->subs[idx].dfd, i->subs[idx].linear);
07479    features = 0;
07480    if (idx == SUB_REAL) {
07481       if (i->busydetect && CANBUSYDETECT(i))
07482          features |= DSP_FEATURE_BUSY_DETECT;
07483       if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
07484          features |= DSP_FEATURE_CALL_PROGRESS;
07485       if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
07486          features |= DSP_FEATURE_WAITDIALTONE;
07487       if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
07488          (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
07489          features |= DSP_FEATURE_FAX_DETECT;
07490       }
07491       x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
07492       if (ioctl(i->subs[idx].dfd, DAHDI_TONEDETECT, &x)) {
07493          i->hardwaredtmf = 0;
07494          features |= DSP_FEATURE_DIGIT_DETECT;
07495       } else if (NEED_MFDETECT(i)) {
07496          i->hardwaredtmf = 1;
07497          features |= DSP_FEATURE_DIGIT_DETECT;
07498       }
07499    }
07500    if (features) {
07501       if (i->dsp) {
07502          ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
07503       } else {
07504          if (i->channel != CHAN_PSEUDO)
07505             i->dsp = ast_dsp_new();
07506          else
07507             i->dsp = NULL;
07508          if (i->dsp) {
07509             i->dsp_features = features;
07510 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07511             /* We cannot do progress detection until receives PROGRESS message */
07512             if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
07513                /* Remember requested DSP features, don't treat
07514                   talking as ANSWER */
07515                i->dsp_features = features & ~DSP_PROGRESS_TALK;
07516                features = 0;
07517             }
07518 #endif
07519             ast_dsp_set_features(i->dsp, features);
07520             ast_dsp_set_digitmode(i->dsp, DSP_DIGITMODE_DTMF | i->dtmfrelax);
07521             if (!ast_strlen_zero(progzone))
07522                ast_dsp_set_call_progress_zone(i->dsp, progzone);
07523             if (i->busydetect && CANBUSYDETECT(i)) {
07524                ast_dsp_set_busy_count(i->dsp, i->busycount);
07525                ast_dsp_set_busy_pattern(i->dsp, i->busy_tonelength, i->busy_quietlength);
07526             }
07527          }
07528       }
07529    }
07530 
07531    if (state == AST_STATE_RING)
07532       tmp->rings = 1;
07533    tmp->tech_pvt = i;
07534    if ((i->sig == SIG_FXOKS) || (i->sig == SIG_FXOGS) || (i->sig == SIG_FXOLS)) {
07535       /* Only FXO signalled stuff can be picked up */
07536       tmp->callgroup = i->callgroup;
07537       tmp->pickupgroup = i->pickupgroup;
07538    }
07539    if (!ast_strlen_zero(i->parkinglot))
07540       ast_string_field_set(tmp, parkinglot, i->parkinglot);
07541    if (!ast_strlen_zero(i->language))
07542       ast_string_field_set(tmp, language, i->language);
07543    if (!i->owner)
07544       i->owner = tmp;
07545    if (!ast_strlen_zero(i->accountcode))
07546       ast_string_field_set(tmp, accountcode, i->accountcode);
07547    if (i->amaflags)
07548       tmp->amaflags = i->amaflags;
07549    i->subs[idx].owner = tmp;
07550    ast_copy_string(tmp->context, i->context, sizeof(tmp->context));
07551    ast_string_field_set(tmp, call_forward, i->call_forward);
07552    /* If we've been told "no ADSI" then enforce it */
07553    if (!i->adsi)
07554       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
07555    if (!ast_strlen_zero(i->exten))
07556       ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
07557    if (!ast_strlen_zero(i->rdnis))
07558       tmp->cid.cid_rdnis = ast_strdup(i->rdnis);
07559    if (!ast_strlen_zero(i->dnid))
07560       tmp->cid.cid_dnid = ast_strdup(i->dnid);
07561 
07562    /* Don't use ast_set_callerid() here because it will
07563     * generate a needless NewCallerID event */
07564 #ifdef PRI_ANI
07565    if (!ast_strlen_zero(i->cid_ani))
07566       tmp->cid.cid_ani = ast_strdup(i->cid_ani);
07567    else
07568       tmp->cid.cid_ani = ast_strdup(i->cid_num);
07569 #else
07570    tmp->cid.cid_ani = ast_strdup(i->cid_num);
07571 #endif
07572    tmp->cid.cid_pres = i->callingpres;
07573    tmp->cid.cid_ton = i->cid_ton;
07574    tmp->cid.cid_ani2 = i->cid_ani2;
07575 #if defined(HAVE_PRI) || defined(HAVE_SS7)
07576    tmp->transfercapability = transfercapability;
07577    pbx_builtin_setvar_helper(tmp, "TRANSFERCAPABILITY", ast_transfercapability2str(transfercapability));
07578    if (transfercapability & AST_TRANS_CAP_DIGITAL)
07579       i->digital = 1;
07580    /* Assume calls are not idle calls unless we're told differently */
07581    i->isidlecall = 0;
07582    i->alreadyhungup = 0;
07583 #endif
07584    /* clear the fake event in case we posted one before we had ast_channel */
07585    i->fake_event = 0;
07586    /* Assure there is no confmute on this channel */
07587    dahdi_confmute(i, 0);
07588    i->muting = 0;
07589    /* Configure the new channel jb */
07590    ast_jb_configure(tmp, &global_jbconf);
07591 
07592    ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
07593 
07594    for (v = i->vars ; v ; v = v->next)
07595       pbx_builtin_setvar_helper(tmp, v->name, v->value);
07596 
07597    if (startpbx) {
07598 #ifdef HAVE_OPENR2
07599       if (i->mfcr2call) {
07600          pbx_builtin_setvar_helper(tmp, "MFCR2_CATEGORY", openr2_proto_get_category_string(i->mfcr2_recvd_category));
07601       }
07602 #endif
07603       if (ast_pbx_start(tmp)) {
07604          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
07605          ast_hangup(tmp);
07606          i->owner = NULL;
07607          return NULL;
07608       }
07609    }
07610 
07611    ast_module_ref(ast_module_info->self);
07612    return tmp;
07613 }

static int dahdi_open ( char *  fn  )  [static]

Definition at line 2090 of file chan_dahdi.c.

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

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

02091 {
02092    int fd;
02093    int isnum;
02094    int chan = 0;
02095    int bs;
02096    int x;
02097    isnum = 1;
02098    for (x = 0; x < strlen(fn); x++) {
02099       if (!isdigit(fn[x])) {
02100          isnum = 0;
02101          break;
02102       }
02103    }
02104    if (isnum) {
02105       chan = atoi(fn);
02106       if (chan < 1) {
02107          ast_log(LOG_WARNING, "Invalid channel number '%s'\n", fn);
02108          return -1;
02109       }
02110       fn = "/dev/dahdi/channel";
02111    }
02112    fd = open(fn, O_RDWR | O_NONBLOCK);
02113    if (fd < 0) {
02114       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", fn, strerror(errno));
02115       return -1;
02116    }
02117    if (chan) {
02118       if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
02119          x = errno;
02120          close(fd);
02121          errno = x;
02122          ast_log(LOG_WARNING, "Unable to specify channel %d: %s\n", chan, strerror(errno));
02123          return -1;
02124       }
02125    }
02126    bs = READ_SIZE;
02127    if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
02128       ast_log(LOG_WARNING, "Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
02129       x = errno;
02130       close(fd);
02131       errno = x;
02132       return -1;
02133    }
02134    return fd;
02135 }

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

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

12257 {
12258    int x, y;
12259    int dchan = -1, span = -1;
12260    int dchancount = 0;
12261 
12262    if (pri) {
12263       for (x = 0; x < NUM_SPANS; x++) {
12264          for (y = 0; y < NUM_DCHANS; y++) {
12265             if (pris[x].dchans[y])
12266                dchancount++;
12267 
12268             if (pris[x].dchans[y] == pri)
12269                dchan = y;
12270          }
12271          if (dchan >= 0) {
12272             span = x;
12273             break;
12274          }
12275          dchancount = 0;
12276       }
12277       if ((dchancount > 1) && (span > -1))
12278          ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
12279       else
12280          ast_log(LOG_ERROR, "%s", s);
12281    } else
12282       ast_log(LOG_ERROR, "%s", s);
12283 
12284    ast_mutex_lock(&pridebugfdlock);
12285 
12286    if (pridebugfd >= 0) {
12287       if (write(pridebugfd, s, strlen(s)) < 0) {
12288          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12289       }
12290    }
12291 
12292    ast_mutex_unlock(&pridebugfdlock);
12293 }

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

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

12216 {
12217    int x, y;
12218    int dchan = -1, span = -1;
12219    int dchancount = 0;
12220 
12221    if (pri) {
12222       for (x = 0; x < NUM_SPANS; x++) {
12223          for (y = 0; y < NUM_DCHANS; y++) {
12224             if (pris[x].dchans[y])
12225                dchancount++;
12226 
12227             if (pris[x].dchans[y] == pri)
12228                dchan = y;
12229          }
12230          if (dchan >= 0) {
12231             span = x;
12232             break;
12233          }
12234          dchancount = 0;
12235       }
12236       if (dchancount > 1 && (span > -1))
12237          ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
12238       else
12239          ast_verbose("%s", s);
12240    } else
12241       ast_verbose("%s", s);
12242 
12243    ast_mutex_lock(&pridebugfdlock);
12244 
12245    if (pridebugfd >= 0) {
12246       if (write(pridebugfd, s, strlen(s)) < 0) {
12247          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
12248       }
12249    }
12250 
12251    ast_mutex_unlock(&pridebugfdlock);
12252 }

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

Definition at line 1544 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_pri::pri, 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().

01545 {
01546 #ifdef HAVE_PRI
01547    struct dahdi_pri *pri = (struct dahdi_pri*) data;
01548 #endif
01549 #ifdef HAVE_SS7
01550    struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
01551 #endif
01552    /* We must unlock the PRI to avoid the possibility of a deadlock */
01553 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01554    if (data) {
01555       switch (p->sig) {
01556 #ifdef HAVE_PRI
01557       case SIG_BRI:
01558       case SIG_BRI_PTMP:
01559       case SIG_PRI:
01560          ast_mutex_unlock(&pri->lock);
01561          break;
01562 #endif
01563 #ifdef HAVE_SS7
01564       case SIG_SS7:
01565          ast_mutex_unlock(&ss7->lock);
01566          break;
01567 #endif
01568       default:
01569          break;
01570       }
01571    }
01572 #endif
01573    for (;;) {
01574       if (p->owner) {
01575          if (ast_channel_trylock(p->owner)) {
01576             DEADLOCK_AVOIDANCE(&p->lock);
01577          } else {
01578             ast_queue_frame(p->owner, f);
01579             ast_channel_unlock(p->owner);
01580             break;
01581          }
01582       } else
01583          break;
01584    }
01585 #if defined(HAVE_PRI) || defined(HAVE_SS7)
01586    if (data) {
01587       switch (p->sig) {
01588 #ifdef HAVE_PRI
01589       case SIG_BRI:
01590       case SIG_BRI_PTMP:
01591       case SIG_PRI:
01592          ast_mutex_lock(&pri->lock);
01593          break;
01594 #endif
01595 #ifdef HAVE_SS7
01596       case SIG_SS7:
01597          ast_mutex_lock(&ss7->lock);
01598          break;
01599 #endif
01600       default:
01601          break;
01602       }
01603    }
01604 #endif
01605 }

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

Definition at line 6717 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_get_tcount(), ast_dsp_get_tstate(), ast_dsp_process(), ast_dsp_set_features(), 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_null_frame, ast_set_callerid(), ast_set_flag, ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), 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::dop, dahdi_pvt::dsp, DSP_FEATURE_WAITDIALTONE, dahdi_pvt::dsp_features, DSP_TONE_STATE_DIALTONE, DSP_TONE_STATE_RINGING, errno, dahdi_subchannel::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_DEBUG, LOG_WARNING, ast_frame::mallocd, dahdi_pvt::muting, ast_channel::name, dahdi_subchannel::needanswer, dahdi_subchannel::needbusy, dahdi_subchannel::needcallerid, dahdi_subchannel::needcongestion, dahdi_subchannel::needflash, dahdi_subchannel::needhold, dahdi_subchannel::needringing, dahdi_subchannel::needunhold, ast_frame::offset, dahdi_pvt::oprmode, dahdi_pvt::outgoing, dahdi_pri::overlapdial, dahdi_pvt::owner, dahdi_pvt::pri, dahdi_pvt::proceeding, ast_frame::ptr, dahdi_pvt::pulsedial, dahdi_pvt::radio, ast_channel::rawreadformat, READ_SIZE, restore_conference(), ast_channel::rings, dahdi_pvt::ringt, S_OR, ast_frame::samples, send_callerid(), dahdi_pvt::sig, SIG_BRI, SIG_BRI_PTMP, SIG_PRI, ast_frame::src, SUB_CALLWAIT, SUB_REAL, ast_frame::subclass, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_feed(), ast_channel::tech_pvt, dahdi_pvt::waitfordialtone, and dahdi_pvt::waitingfordt.

06718 {
06719    struct dahdi_pvt *p = ast->tech_pvt;
06720    int res;
06721    int idx;
06722    void *readbuf;
06723    struct ast_frame *f;
06724 
06725    while (ast_mutex_trylock(&p->lock)) {
06726       CHANNEL_DEADLOCK_AVOIDANCE(ast);
06727    }
06728 
06729    idx = dahdi_get_index(ast, p, 0);
06730 
06731    /* Hang up if we don't really exist */
06732    if (idx < 0)   {
06733       ast_log(LOG_WARNING, "We dont exist?\n");
06734       ast_mutex_unlock(&p->lock);
06735       return NULL;
06736    }
06737 
06738    if ((p->radio || (p->oprmode < 0)) && p->inalarm) {
06739       ast_mutex_unlock(&p->lock);
06740       return NULL;
06741    }
06742 
06743    p->subs[idx].f.frametype = AST_FRAME_NULL;
06744    p->subs[idx].f.datalen = 0;
06745    p->subs[idx].f.samples = 0;
06746    p->subs[idx].f.mallocd = 0;
06747    p->subs[idx].f.offset = 0;
06748    p->subs[idx].f.subclass = 0;
06749    p->subs[idx].f.delivery = ast_tv(0,0);
06750    p->subs[idx].f.src = "dahdi_read";
06751    p->subs[idx].f.data.ptr = NULL;
06752 
06753    /* make sure it sends initial key state as first frame */
06754    if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
06755    {
06756       struct dahdi_params ps;
06757 
06758       memset(&ps, 0, sizeof(ps));
06759       ps.channo = p->channel;
06760       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
06761          ast_mutex_unlock(&p->lock);
06762          return NULL;
06763       }
06764       p->firstradio = 1;
06765       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06766       if (ps.rxisoffhook)
06767       {
06768          p->subs[idx].f.subclass = AST_CONTROL_RADIO_KEY;
06769       }
06770       else
06771       {
06772          p->subs[idx].f.subclass = AST_CONTROL_RADIO_UNKEY;
06773       }
06774       ast_mutex_unlock(&p->lock);
06775       return &p->subs[idx].f;
06776    }
06777    if (p->ringt == 1) {
06778       ast_mutex_unlock(&p->lock);
06779       return NULL;
06780    }
06781    else if (p->ringt > 0)
06782       p->ringt--;
06783 
06784 #ifdef HAVE_OPENR2
06785    if (p->mfcr2) {
06786       openr2_chan_process_event(p->r2chan);
06787    }
06788 #endif
06789 
06790    if (p->subs[idx].needringing) {
06791       /* Send ringing frame if requested */
06792       p->subs[idx].needringing = 0;
06793       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06794       p->subs[idx].f.subclass = AST_CONTROL_RINGING;
06795       ast_setstate(ast, AST_STATE_RINGING);
06796       ast_mutex_unlock(&p->lock);
06797       return &p->subs[idx].f;
06798    }
06799 
06800    if (p->subs[idx].needbusy) {
06801       /* Send busy frame if requested */
06802       p->subs[idx].needbusy = 0;
06803       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06804       p->subs[idx].f.subclass = AST_CONTROL_BUSY;
06805       ast_mutex_unlock(&p->lock);
06806       return &p->subs[idx].f;
06807    }
06808 
06809    if (p->subs[idx].needcongestion) {
06810       /* Send congestion frame if requested */
06811       p->subs[idx].needcongestion = 0;
06812       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06813       p->subs[idx].f.subclass = AST_CONTROL_CONGESTION;
06814       ast_mutex_unlock(&p->lock);
06815       return &p->subs[idx].f;
06816    }
06817 
06818    if (p->subs[idx].needcallerid) {
06819       ast_set_callerid(ast, S_OR(p->lastcid_num, NULL),
06820                      S_OR(p->lastcid_name, NULL),
06821                      S_OR(p->lastcid_num, NULL)
06822                      );
06823       p->subs[idx].needcallerid = 0;
06824    }
06825 
06826    if (p->subs[idx].needanswer) {
06827       /* Send answer frame if requested */
06828       p->subs[idx].needanswer = 0;
06829       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06830       p->subs[idx].f.subclass = AST_CONTROL_ANSWER;
06831       ast_mutex_unlock(&p->lock);
06832       return &p->subs[idx].f;
06833    }
06834 #ifdef HAVE_OPENR2
06835    if (p->mfcr2 && openr2_chan_get_read_enabled(p->r2chan)) {
06836       /* openr2 took care of reading and handling any event
06837         (needanswer, needbusy etc), if we continue we will read()
06838         twice, lets just return a null frame. This should only
06839         happen when openr2 is dialing out */
06840       ast_mutex_unlock(&p->lock);
06841       return &ast_null_frame;
06842    }
06843 #endif
06844 
06845    if (p->subs[idx].needflash) {
06846       /* Send answer frame if requested */
06847       p->subs[idx].needflash = 0;
06848       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06849       p->subs[idx].f.subclass = AST_CONTROL_FLASH;
06850       ast_mutex_unlock(&p->lock);
06851       return &p->subs[idx].f;
06852    }
06853 
06854    if (p->subs[idx].needhold) {
06855       /* Send answer frame if requested */
06856       p->subs[idx].needhold = 0;
06857       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06858       p->subs[idx].f.subclass = AST_CONTROL_HOLD;
06859       ast_mutex_unlock(&p->lock);
06860       ast_debug(1, "Sending hold on '%s'\n", ast->name);
06861       return &p->subs[idx].f;
06862    }
06863 
06864    if (p->subs[idx].needunhold) {
06865       /* Send answer frame if requested */
06866       p->subs[idx].needunhold = 0;
06867       p->subs[idx].f.frametype = AST_FRAME_CONTROL;
06868       p->subs[idx].f.subclass = AST_CONTROL_UNHOLD;
06869       ast_mutex_unlock(&p->lock);
06870       ast_debug(1, "Sending unhold on '%s'\n", ast->name);
06871       return &p->subs[idx].f;
06872    }
06873 
06874    if (ast->rawreadformat == AST_FORMAT_SLINEAR) {
06875       if (!p->subs[idx].linear) {
06876          p->subs[idx].linear = 1;
06877          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06878          if (res)
06879             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to linear mode.\n", p->channel, idx);
06880       }
06881    } else if ((ast->rawreadformat == AST_FORMAT_ULAW) ||
06882       (ast->rawreadformat == AST_FORMAT_ALAW)) {
06883       if (p->subs[idx].linear) {
06884          p->subs[idx].linear = 0;
06885          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
06886          if (res)
06887             ast_log(LOG_WARNING, "Unable to set channel %d (index %d) to companded mode.\n", p->channel, idx);
06888       }
06889    } else {
06890       ast_log(LOG_WARNING, "Don't know how to read frames in format %s\n", ast_getformatname(ast->rawreadformat));
06891       ast_mutex_unlock(&p->lock);
06892       return NULL;
06893    }
06894    readbuf = ((unsigned char *)p->subs[idx].buffer) + AST_FRIENDLY_OFFSET;
06895    CHECK_BLOCKING(ast);
06896    res = read(p->subs[idx].dfd, readbuf, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06897    ast_clear_flag(ast, AST_FLAG_BLOCKING);
06898    /* Check for hangup */
06899    if (res < 0) {
06900       f = NULL;
06901       if (res == -1) {
06902          if (errno == EAGAIN) {
06903             /* Return "NULL" frame if there is nobody there */
06904             ast_mutex_unlock(&p->lock);
06905             return &p->subs[idx].f;
06906          } else if (errno == ELAST) {
06907             f = __dahdi_exception(ast);
06908          } else
06909             ast_log(LOG_WARNING, "dahdi_rec: %s\n", strerror(errno));
06910       }
06911       ast_mutex_unlock(&p->lock);
06912       return f;
06913    }
06914    if (res != (p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE)) {
06915       ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[idx].linear ? READ_SIZE * 2 : READ_SIZE);
06916       f = __dahdi_exception(ast);
06917       ast_mutex_unlock(&p->lock);
06918       return f;
06919    }
06920    if (p->tdd) { /* if in TDD mode, see if we receive that */
06921       int c;
06922 
06923       c = tdd_feed(p->tdd,readbuf,READ_SIZE);
06924       if (c < 0) {
06925          ast_debug(1,"tdd_feed failed\n");
06926          ast_mutex_unlock(&p->lock);
06927          return NULL;
06928       }
06929       if (c) { /* if a char to return */
06930          p->subs[idx].f.subclass = 0;
06931          p->subs[idx].f.frametype = AST_FRAME_TEXT;
06932          p->subs[idx].f.mallocd = 0;
06933          p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06934          p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET;
06935          p->subs[idx].f.datalen = 1;
06936          *((char *) p->subs[idx].f.data.ptr) = c;
06937          ast_mutex_unlock(&p->lock);
06938          return &p->subs[idx].f;
06939       }
06940    }
06941    /* Ensure the CW timer decrements only on a single subchannel */
06942    if (p->callwaitingrepeat && dahdi_get_index(ast, p, 1) == SUB_REAL) {
06943       p->callwaitingrepeat--;
06944    }
06945    if (p->cidcwexpire)
06946       p->cidcwexpire--;
06947    /* Repeat callwaiting */
06948    if (p->callwaitingrepeat == 1) {
06949       p->callwaitrings++;
06950       dahdi_callwait(ast);
06951    }
06952    /* Expire CID/CW */
06953    if (p->cidcwexpire == 1) {
06954       ast_verb(3, "CPE does not support Call Waiting Caller*ID.\n");
06955       restore_conference(p);
06956    }
06957    if (p->subs[idx].linear) {
06958       p->subs[idx].f.datalen = READ_SIZE * 2;
06959    } else
06960       p->subs[idx].f.datalen = READ_SIZE;
06961 
06962    /* Handle CallerID Transmission */
06963    if ((p->owner == ast) && p->cidspill &&((ast->_state == AST_STATE_UP) || (ast->rings == p->cidrings))) {
06964       send_callerid(p);
06965    }
06966 
06967    p->subs[idx].f.frametype = AST_FRAME_VOICE;
06968    p->subs[idx].f.subclass = ast->rawreadformat;
06969    p->subs[idx].f.samples = READ_SIZE;
06970    p->subs[idx].f.mallocd = 0;
06971    p->subs[idx].f.offset = AST_FRIENDLY_OFFSET;
06972    p->subs[idx].f.data.ptr = p->subs[idx].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[idx].buffer[0]);
06973 #if 0
06974    ast_debug(1, "Read %d of voice on %s\n", p->subs[idx].f.datalen, ast->name);
06975 #endif
06976    if (p->dialing || /* Transmitting something */
06977       (idx && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
06978       ((idx == SUB_CALLWAIT) && !p->subs[SUB_CALLWAIT].inthreeway) /* Inactive and non-confed call-wait */
06979       ) {
06980       /* Whoops, we're still dialing, or in a state where we shouldn't transmit....
06981          don't send anything */
06982       p->subs[idx].f.frametype = AST_FRAME_NULL;
06983       p->subs[idx].f.subclass = 0;
06984       p->subs[idx].f.samples = 0;
06985       p->subs[idx].f.mallocd = 0;
06986       p->subs[idx].f.offset = 0;
06987       p->subs[idx].f.data.ptr = NULL;
06988       p->subs[idx].f.datalen= 0;
06989    }
06990    if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
06991       /* Perform busy detection etc on the dahdi line */
06992       int mute;
06993 
06994       f = ast_dsp_process(ast, p->dsp, &p->subs[idx].f);
06995 
06996       /* Check if DSP code thinks we should be muting this frame and mute the conference if so */
06997       mute = ast_dsp_was_muted(p->dsp);
06998       if (p->muting != mute) {
06999          p->muting = mute;
07000          dahdi_confmute(p, mute);
07001       }
07002 
07003       if (f) {
07004          if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_BUSY)) {
07005             if ((ast->_state == AST_STATE_UP) && !p->outgoing) {
07006                /* Treat this as a "hangup" instead of a "busy" on the assumption that
07007                   a busy */
07008                f = NULL;
07009             }
07010          } else if (f->frametype == AST_FRAME_DTMF) {
07011 #ifdef HAVE_PRI
07012             if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
07013                ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
07014                (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
07015                /* Don't accept in-band DTMF when in overlap dial mode */
07016                f->frametype = AST_FRAME_NULL;
07017                f->subclass = 0;
07018             }
07019 #endif
07020             /* DSP clears us of being pulse */
07021             p->pulsedial = 0;
07022          } else if (p->waitingfordt.tv_sec) {
07023             if (ast_tvdiff_ms(ast_tvnow(), p->waitingfordt) >= p->waitfordialtone ) {
07024                p->waitingfordt.tv_sec = 0;
07025                ast_log(LOG_WARNING, "Never saw dialtone on channel %d\n", p->channel);
07026                f=NULL;
07027             } else if (f->frametype == AST_FRAME_VOICE) {
07028                f->frametype = AST_FRAME_NULL;
07029                f->subclass = 0;
07030                if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE || ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_RINGING) && ast_dsp_get_tcount(p->dsp) > 9) {
07031                   p->waitingfordt.tv_sec = 0;
07032                   p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
07033                   ast_dsp_set_features(p->dsp, p->dsp_features);
07034                   ast_log(LOG_DEBUG, "Got 10 samples of dialtone!\n");
07035                   if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
07036                      res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
07037                      if (res < 0) {
07038                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
07039                         p->dop.dialstr[0] = '\0';
07040                         ast_mutex_unlock(&p->lock);
07041                         return NULL;
07042                      } else {
07043                         ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
07044                         p->dialing = 1;
07045                         p->dop.dialstr[0] = '\0';
07046                         p->dop.op = DAHDI_DIAL_OP_REPLACE;
07047                         ast_setstate(ast, AST_STATE_DIALING);
07048                      }
07049                   }
07050                }
07051             }
07052          }
07053       }
07054    } else
07055       f = &p->subs[idx].f;
07056 
07057    if (f && (f->frametype == AST_FRAME_DTMF))
07058       dahdi_handle_dtmfup(ast, idx, &f);
07059 
07060    /* If we have a fake_event, trigger exception to handle it */
07061    if (p->fake_event)
07062       ast_set_flag(ast, AST_FLAG_EXCEPTION);
07063 
07064    ast_mutex_unlock(&p->lock);
07065    return f;
07066 }

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

Definition at line 10834 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_TRANS_CAP_DIGITAL, ast_verbose, available(), dahdi_pvt::bearer, ast_channel::cdrflags, CHAN_PSEUDO, dahdi_pvt::channel, dahdi_pvt::confirmanswer, dahdi_pri::crvend, dahdi_pri::crvs, dahdi_new(), dahdi_subchannel::dfd, dahdi_pvt::digital, dahdi_pvt::distinctivering, duplicate_pseudo(), iflist, iflock, dahdi_pvt::inalarm, dahdi_pvt::lock, dahdi_pri::lock, lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_channel::name, dahdi_pvt::next, NUM_SPANS, dahdi_pvt::outgoing, dahdi_pvt::owner, dahdi_pvt::prev, dahdi_pvt::pri, dahdi_pri::pri, pri_assign_bearer(), pri_find_empty_chan(), pris, dahdi_pri::pvts, restart_monitor(), s, dahdi_pvt::sig, SIG_FXSKS, dahdi_pri::span, SUB_CALLWAIT, SUB_REAL, dahdi_pvt::subs, and ast_channel::transfercapability.

Referenced by pri_dchannel().

10835 {
10836    ast_group_t groupmatch = 0;
10837    int channelmatch = -1;
10838    int roundrobin = 0;
10839    int callwait = 0;
10840    int busy = 0;
10841    struct dahdi_pvt *p;
10842    struct ast_channel *tmp = NULL;
10843    char *dest=NULL;
10844    int x;
10845    char *s;
10846    char opt=0;
10847    int res=0, y=0;
10848    int backwards = 0;
10849 #ifdef HAVE_PRI
10850    int crv;
10851    int bearer = -1;
10852    int trunkgroup;
10853    struct dahdi_pri *pri=NULL;
10854 #endif
10855    struct dahdi_pvt *exitpvt, *start, *end;
10856    ast_mutex_t *lock;
10857    int channelmatched = 0;
10858    int groupmatched = 0;
10859 
10860    /*
10861     * data is ---v
10862     * Dial(DAHDI/pseudo[/extension])
10863     * Dial(DAHDI/<channel#>[c|r<cadance#>|d][/extension])
10864     * Dial(DAHDI/<trunk_group#>:<crv#>[c|r<cadance#>|d][/extension])
10865     * Dial(DAHDI/(g|G|r|R)<group#(0-63)>[c|r<cadance#>|d][/extension])
10866     *
10867     * g - channel group allocation search forward
10868     * G - channel group allocation search backward
10869     * r - channel group allocation round robin search forward
10870     * R - channel group allocation round robin search backward
10871     *
10872     * c - Wait for DTMF digit to confirm answer
10873     * r<cadance#> - Set distintive ring cadance number
10874     * d - Force bearer capability for ISDN/SS7 call to digital.
10875     */
10876 
10877    /* Assume we're locking the iflock */
10878    lock = &iflock;
10879    start = iflist;
10880    end = ifend;
10881    if (data) {
10882       dest = ast_strdupa((char *)data);
10883    } else {
10884       ast_log(LOG_WARNING, "Channel requested with no data\n");
10885       return NULL;
10886    }
10887    if (toupper(dest[0]) == 'G' || toupper(dest[0])=='R') {
10888       /* Retrieve the group number */
10889       char *stringp;
10890 
10891       stringp = dest + 1;
10892       s = strsep(&stringp, "/");
10893       if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10894          ast_log(LOG_WARNING, "Unable to determine group for data %s\n", (char *)data);
10895          return NULL;
10896       }
10897       groupmatch = ((ast_group_t) 1 << x);
10898       if (toupper(dest[0]) == 'G') {
10899          if (dest[0] == 'G') {
10900             backwards = 1;
10901             p = ifend;
10902          } else
10903             p = iflist;
10904       } else {
10905          if (dest[0] == 'R') {
10906             backwards = 1;
10907             p = round_robin[x]?round_robin[x]->prev:ifend;
10908             if (!p)
10909                p = ifend;
10910          } else {
10911             p = round_robin[x]?round_robin[x]->next:iflist;
10912             if (!p)
10913                p = iflist;
10914          }
10915          roundrobin = 1;
10916       }
10917    } else {
10918       char *stringp;
10919 
10920       stringp = dest;
10921       s = strsep(&stringp, "/");
10922       p = iflist;
10923       if (!strcasecmp(s, "pseudo")) {
10924          /* Special case for pseudo */
10925          x = CHAN_PSEUDO;
10926          channelmatch = x;
10927       }
10928 #ifdef HAVE_PRI
10929       else if ((res = sscanf(s, "%30d:%30d%1c%30d", &trunkgroup, &crv, &opt, &y)) > 1) {
10930          if ((trunkgroup < 1) || (crv < 1)) {
10931             ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
10932             return NULL;
10933          }
10934          res--;
10935          for (x = 0; x < NUM_SPANS; x++) {
10936             if (pris[x].trunkgroup == trunkgroup) {
10937                pri = pris + x;
10938                lock = &pri->lock;
10939                start = pri->crvs;
10940                end = pri->crvend;
10941                break;
10942             }
10943          }
10944          if (!pri) {
10945             ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
10946             return NULL;
10947          }
10948          channelmatch = crv;
10949          p = pris[x].crvs;
10950       }
10951 #endif
10952       else if ((res = sscanf(s, "%30d%1c%30d", &x, &opt, &y)) < 1) {
10953          ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
10954          return NULL;
10955       } else {
10956          channelmatch = x;
10957       }
10958    }
10959    /* Search for an unowned channel */
10960    ast_mutex_lock(lock);
10961    exitpvt = p;
10962    while (p && !tmp) {
10963       if (roundrobin)
10964          round_robin[x] = p;
10965 #if 0
10966       ast_verbose("name = %s, %d, %d, %llu\n",p->owner ? p->owner->name : "<none>", p->channel, channelmatch, groupmatch);
10967 #endif
10968 
10969       if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
10970          ast_debug(1, "Using channel %d\n", p->channel);
10971          if (p->inalarm)
10972             goto next;
10973 
10974          callwait = (p->owner != NULL);
10975 #ifdef HAVE_PRI
10976          if (pri && (p->subs[SUB_REAL].dfd < 0)) {
10977             if (p->sig != SIG_FXSKS) {
10978                /* Gotta find an actual channel to use for this
10979                   CRV if this isn't a callwait */
10980                bearer = pri_find_empty_chan(pri, 0);
10981                if (bearer < 0) {
10982                   ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
10983                   p = NULL;
10984                   break;
10985                }
10986                pri_assign_bearer(p, pri, pri->pvts[bearer]);
10987             } else {
10988                if (alloc_sub(p, 0)) {
10989                   ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
10990                   p = NULL;
10991                   break;
10992                } else
10993                   ast_debug(1, "Allocated placeholder pseudo channel\n");
10994 
10995                p->pri = pri;
10996             }
10997          }
10998 #endif
10999 #ifdef HAVE_OPENR2
11000          if (p->mfcr2) {
11001             ast_mutex_lock(&p->lock);
11002             if (p->mfcr2call) {
11003                ast_mutex_unlock(&p->lock);
11004                ast_log(LOG_DEBUG, "Yay!, someone just beat us in the race for channel %d.\n", p->channel);
11005                goto next;
11006             }
11007             p->mfcr2call = 1;
11008             ast_mutex_unlock(&p->lock);
11009          }
11010 #endif
11011          if (p->channel == CHAN_PSEUDO) {
11012             p = duplicate_pseudo(p);
11013             if (!p) {
11014                break;
11015             }
11016          }
11017          if (p->owner) {
11018             if (alloc_sub(p, SUB_CALLWAIT)) {
11019                p = NULL;
11020                break;
11021             }
11022          }
11023          p->outgoing = 1;
11024          tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
11025          if (!tmp) {
11026             p->outgoing = 0;
11027          }
11028 #ifdef HAVE_PRI
11029          if (p->bearer) {
11030             /* Log owner to bearer channel, too */
11031             p->bearer->owner = tmp;
11032          }
11033 #endif
11034          /* Make special notes */
11035          if (res > 1) {
11036             if (opt == 'c') {
11037                /* Confirm answer */
11038                p->confirmanswer = 1;
11039             } else if (opt == 'r') {
11040                /* Distinctive ring */
11041                if (res < 3)
11042                   ast_log(LOG_WARNING, "Distinctive ring missing identifier in '%s'\n", (char *)data);
11043                else
11044                   p->distinctivering = y;
11045             } else if (opt == 'd') {
11046                /* If this is an ISDN call, make it digital */
11047                p->digital = 1;
11048                if (tmp)
11049                   tmp->transfercapability = AST_TRANS_CAP_DIGITAL;
11050             } else {
11051                ast_log(LOG_WARNING, "Unknown option '%c' in '%s'\n", opt, (char *)data);
11052             }
11053          }
11054          /* Note if the call is a call waiting call */
11055          if (tmp && callwait)
11056             tmp->cdrflags |= AST_CDR_CALLWAIT;
11057          break;
11058       }
11059 next:
11060       if (backwards) {
11061          p = p->prev;
11062          if (!p)
11063             p = end;
11064       } else {
11065          p = p->next;
11066          if (!p)
11067             p = start;
11068       }
11069       /* stop when you roll to the one that we started from */
11070       if (p == exitpvt)
11071          break;
11072    }
11073    ast_mutex_unlock(lock);
11074    restart_monitor();
11075    if (callwait)
11076       *cause = AST_CAUSE_BUSY;
11077    else if (!tmp) {
11078       if (channelmatched) {
11079          if (busy)
11080             *cause = AST_CAUSE_BUSY;
11081       } else if (groupmatched) {
11082          *cause = AST_CAUSE_CONGESTION;
11083       }
11084    }
11085 
11086    return tmp;
11087 }

static int dahdi_restart ( void   )  [static]

Definition at line 14338 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, dahdi_pvt::next, NUM_DCHANS, 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().

14339 {
14340 #if defined(HAVE_PRI) || defined(HAVE_SS7)
14341    int i, j;
14342 #endif
14343    int cancel_code;
14344    struct dahdi_pvt *p;
14345 
14346    ast_mutex_lock(&restart_lock);
14347    ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
14348    dahdi_softhangup_all();
14349    ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
14350 #ifdef HAVE_OPENR2
14351    dahdi_r2_destroy_links();
14352 #endif
14353 
14354 #if defined(HAVE_PRI)
14355    for (i = 0; i < NUM_SPANS; i++) {
14356       if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
14357          cancel_code = pthread_cancel(pris[i].master);
14358          pthread_kill(pris[i].master, SIGURG);
14359          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
14360          pthread_join(pris[i].master, NULL);
14361          ast_debug(4, "Joined thread of span %d\n", i);
14362       }
14363    }
14364 #endif
14365 
14366 #if defined(HAVE_SS7)
14367    for (i = 0; i < NUM_SPANS; i++) {
14368       if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
14369          cancel_code = pthread_cancel(linksets[i].master);
14370          pthread_kill(linksets[i].master, SIGURG);
14371          ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
14372          pthread_join(linksets[i].master, NULL);
14373          ast_debug(4, "Joined thread of span %d\n", i);
14374       }
14375    }
14376 #endif
14377 
14378    ast_mutex_lock(&monlock);
14379    if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
14380       cancel_code = pthread_cancel(monitor_thread);
14381       pthread_kill(monitor_thread, SIGURG);
14382       ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
14383       pthread_join(monitor_thread, NULL);
14384       ast_debug(4, "Joined monitor thread\n");
14385    }
14386    monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
14387 
14388    ast_mutex_lock(&ss_thread_lock);
14389    while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
14390       int x = DAHDI_FLASH;
14391       ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
14392 
14393       for (p = iflist; p; p = p->next) {
14394          if (p->owner)
14395             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 */
14396          }
14397          ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
14398       }
14399 
14400    /* ensure any created channels before monitor threads were stopped are hungup */
14401    dahdi_softhangup_all();
14402    ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
14403    destroy_all_channels();
14404    ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
14405 
14406    ast_mutex_unlock(&monlock);
14407 
14408 #ifdef HAVE_PRI
14409    for (i = 0; i < NUM_SPANS; i++) {
14410       for (j = 0; j < NUM_DCHANS; j++)
14411          dahdi_close_pri_fd(&(pris[i]), j);
14412    }
14413 
14414    memset(pris, 0, sizeof(pris));
14415    for (i = 0; i < NUM_SPANS; i++) {
14416       ast_mutex_init(&pris[i].lock);
14417       pris[i].offset = -1;
14418       pris[i].master = AST_PTHREADT_NULL;
14419       for (j = 0; j < NUM_DCHANS; j++)
14420          pris[i].fds[j] = -1;
14421       }
14422    pri_set_error(dahdi_pri_error);
14423    pri_set_message(dahdi_pri_message);
14424 #endif
14425 #ifdef HAVE_SS7
14426    for (i = 0; i < NUM_SPANS; i++) {
14427       for (j = 0; j < NUM_DCHANS; j++)
14428          dahdi_close_ss7_fd(&(linksets[i]), j);
14429    }
14430 
14431    memset(linksets, 0, sizeof(linksets));
14432    for (i = 0; i < NUM_SPANS; i++) {
14433       ast_mutex_init(&linksets[i].lock);
14434       linksets[i].master = AST_PTHREADT_NULL;
14435       for (j = 0; j < NUM_DCHANS; j++)
14436          linksets[i].fds[j] = -1;
14437    }
14438    ss7_set_error(dahdi_ss7_error);
14439    ss7_set_message(dahdi_ss7_message);
14440 #endif
14441 
14442    if (setup_dahdi(2) != 0) {
14443       ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
14444       ast_mutex_unlock(&ss_thread_lock);
14445       return 1;
14446    }
14447    ast_mutex_unlock(&ss_thread_lock);
14448    ast_mutex_unlock(&restart_lock);
14449    return 0;
14450 }

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

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

14453 {
14454    switch (cmd) {
14455    case CLI_INIT:
14456       e->command = "dahdi restart";
14457       e->usage =
14458          "Usage: dahdi restart\n"
14459          "  Restarts the DAHDI channels: destroys them all and then\n"
14460          "  re-reads them from chan_dahdi.conf.\n"
14461          "  Note that this will STOP any running CALL on DAHDI channels.\n"
14462          "";
14463       return NULL;
14464    case CLI_GENERATE:
14465       return NULL;
14466    }
14467    if (a->argc != 2)
14468       return CLI_SHOWUSAGE;
14469 
14470    if (dahdi_restart() != 0)
14471       return CLI_FAILURE;
14472    return CLI_SUCCESS;
14473 }

static int dahdi_ring_phone ( struct dahdi_pvt p  )  [static]

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

05471 {
05472    int x;
05473    int res;
05474    /* Make sure our transmit state is on hook */
05475    x = 0;
05476    x = DAHDI_ONHOOK;
05477    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05478    do {
05479       x = DAHDI_RING;
05480       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
05481       if (res) {
05482          switch (errno) {
05483          case EBUSY:
05484          case EINTR:
05485             /* Wait just in case */
05486             usleep(10000);
05487             continue;
05488          case EINPROGRESS:
05489             res = 0;
05490             break;
05491          default:
05492             ast_log(LOG_WARNING, "Couldn't ring the phone: %s\n", strerror(errno));
05493             res = 0;
05494          }
05495       }
05496    } while (res);
05497    return res;
05498 }

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

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

03963 {
03964    /* Data will be our digit string */
03965    struct dahdi_pvt *p;
03966    char *digits = (char *) data;
03967 
03968    if (ast_strlen_zero(digits)) {
03969       ast_debug(1, "No digit string sent to application!\n");
03970       return -1;
03971    }
03972 
03973    p = (struct dahdi_pvt *)chan->tech_pvt;
03974 
03975    if (!p) {
03976       ast_debug(1, "Unable to find technology private\n");
03977       return -1;
03978    }
03979 
03980    ast_mutex_lock(&p->lock);
03981 
03982    if (!p->pri || !p->call) {
03983       ast_debug(1, "Unable to find pri or call on channel!\n");
03984       ast_mutex_unlock(&p->lock);
03985       return -1;
03986    }
03987 
03988    if (!pri_grab(p, p->pri)) {
03989       pri_keypad_facility(p->pri->pri, p->call, digits);
03990       pri_rel(p->pri);
03991    } else {
03992       ast_debug(1, "Unable to grab pri to send keypad facility!\n");
03993       ast_mutex_unlock(&p->lock);
03994       return -1;
03995    }
03996 
03997    ast_mutex_unlock(&p->lock);
03998 
03999    return 0;
04000 }

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

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

17381 {
17382 #define  END_SILENCE_LEN 400
17383 #define  HEADER_MS 50
17384 #define  TRAILER_MS 5
17385 #define  HEADER_LEN ((HEADER_MS + TRAILER_MS) * 8)
17386 #define  ASCII_BYTES_PER_CHAR 80
17387 
17388    unsigned char *buf,*mybuf;
17389    struct dahdi_pvt *p = c->tech_pvt;
17390    struct pollfd fds[1];
17391    int size,res,fd,len,x;
17392    int bytes=0;
17393    /* Initial carrier (imaginary) */
17394    float cr = 1.0;
17395    float ci = 0.0;
17396    float scont = 0.0;
17397    int idx;
17398 
17399    idx = dahdi_get_index(c, p, 0);
17400    if (idx < 0) {
17401       ast_log(LOG_WARNING, "Huh?  I don't exist?\n");
17402       return -1;
17403    }
17404    if (!text[0]) return(0); /* if nothing to send, dont */
17405    if ((!p->tdd) && (!p->mate)) return(0);  /* if not in TDD mode, just return */
17406    if (p->mate)
17407       buf = ast_malloc(((strlen(text) + 1) * ASCII_BYTES_PER_CHAR) + END_SILENCE_LEN + HEADER_LEN);
17408    else
17409       buf = ast_malloc(((strlen(text) + 1) * TDD_BYTES_PER_CHAR) + END_SILENCE_LEN);
17410    if (!buf)
17411       return -1;
17412    mybuf = buf;
17413    if (p->mate) {
17414       int codec = AST_LAW(p);
17415       for (x = 0; x < HEADER_MS; x++) {   /* 50 ms of Mark */
17416          PUT_CLID_MARKMS;
17417       }
17418       /* Put actual message */
17419       for (x = 0; text[x]; x++) {
17420          PUT_CLID(text[x]);
17421       }
17422       for (x = 0; x < TRAILER_MS; x++) {  /* 5 ms of Mark */
17423          PUT_CLID_MARKMS;
17424       }
17425       len = bytes;
17426       buf = mybuf;
17427    } else {
17428       len = tdd_generate(p->tdd, buf, text);
17429       if (len < 1) {
17430          ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
17431          ast_free(mybuf);
17432          return -1;
17433       }
17434    }
17435    memset(buf + len, 0x7f, END_SILENCE_LEN);
17436    len += END_SILENCE_LEN;
17437    fd = p->subs[idx].dfd;
17438    while (len) {
17439       if (ast_check_hangup(c)) {
17440          ast_free(mybuf);
17441          return -1;
17442       }
17443       size = len;
17444       if (size > READ_SIZE)
17445          size = READ_SIZE;
17446       fds[0].fd = fd;
17447       fds[0].events = POLLOUT | POLLPRI;
17448       fds[0].revents = 0;
17449       res = poll(fds, 1, -1);
17450       if (!res) {
17451          ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
17452          continue;
17453       }
17454       /* if got exception */
17455       if (fds[0].revents & POLLPRI) {
17456          ast_free(mybuf);
17457          return -1;
17458       }
17459       if (!(fds[0].revents & POLLOUT)) {
17460          ast_debug(1, "write fd not ready on channel %d\n", p->channel);
17461          continue;
17462       }
17463       res = write(fd, buf, size);
17464       if (res != size) {
17465          if (res == -1) {
17466             ast_free(mybuf);
17467             return -1;
17468          }
17469          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
17470          break;
17471       }
17472       len -= size;
17473       buf += size;
17474    }
17475    ast_free(mybuf);
17476    return(0);
17477 }

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

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

15113 {
15114    int channel;
15115    int on;
15116    struct dahdi_pvt *dahdi_chan = NULL;
15117 
15118    switch (cmd) {
15119    case CLI_INIT:
15120       e->command = "dahdi set dnd";
15121       e->usage =
15122          "Usage: dahdi set dnd <chan#> <on|off>\n"
15123          "  Sets/resets DND (Do Not Disturb) mode on a channel.\n"
15124          "  Changes take effect immediately.\n"
15125          "  <chan num> is the channel number\n"
15126          "  <on|off> Enable or disable DND mode?\n"
15127          ;
15128       return NULL;
15129    case CLI_GENERATE:
15130       return NULL;
15131    }
15132 
15133    if (a->argc != 5)
15134       return CLI_SHOWUSAGE;
15135 
15136    if ((channel = atoi(a->argv[3])) <= 0) {
15137       ast_cli(a->fd, "Expected channel number, got '%s'\n", a->argv[3]);
15138       return CLI_SHOWUSAGE;
15139    }
15140 
15141    if (ast_true(a->argv[4]))
15142       on = 1;
15143    else if (ast_false(a->argv[4]))
15144       on = 0;
15145    else {
15146       ast_cli(a->fd, "Expected 'on' or 'off', got '%s'\n", a->argv[4]);
15147       return CLI_SHOWUSAGE;
15148    }
15149 
15150    ast_mutex_lock(&iflock);
15151    for (dahdi_chan = iflist; dahdi_chan; dahdi_chan = dahdi_chan->next) {
15152       if (dahdi_chan->channel != channel)
15153          continue;
15154 
15155       /* Found the channel. Actually set it */
15156       dahdi_dnd(dahdi_chan, on);
15157       break;
15158    }
15159    ast_mutex_unlock(&iflock);
15160 
15161    if (!dahdi_chan) {
15162       ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15163       return CLI_FAILURE;
15164    }
15165 
15166    return CLI_SUCCESS;
15167 }

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

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

02864 {
02865    int x, res;
02866 
02867    x = hs;
02868    res = ioctl(fd, DAHDI_HOOK, &x);
02869 
02870    if (res < 0) {
02871       if (errno == EINPROGRESS)
02872          return 0;
02873       ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
02874       /* will expectedly fail if phone is off hook during operation, such as during a restart */
02875    }
02876 
02877    return res;
02878 }

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

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

14970 {
14971    int channel;
14972    int gain;
14973    int tx;
14974    struct dahdi_hwgain hwgain;
14975    struct dahdi_pvt *tmp = NULL;
14976 
14977    switch (cmd) {
14978    case CLI_INIT:
14979       e->command = "dahdi set hwgain";
14980       e->usage =
14981          "Usage: dahdi set hwgain <rx|tx> <chan#> <gain>\n"
14982          "  Sets the hardware gain on a a given channel, overriding the\n"
14983          "   value provided at module loadtime, whether the channel is in\n"
14984          "   use or not.  Changes take effect immediately.\n"
14985          "   <rx|tx> which direction do you want to change (relative to our module)\n"
14986          "   <chan num> is the channel number relative to the device\n"
14987          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
14988       return NULL;
14989    case CLI_GENERATE:
14990       return NULL;
14991    }
14992 
14993    if (a->argc != 6)
14994       return CLI_SHOWUSAGE;
14995 
14996    if (!strcasecmp("rx", a->argv[3]))
14997       tx = 0; /* rx */
14998    else if (!strcasecmp("tx", a->argv[3]))
14999       tx = 1; /* tx */
15000    else
15001       return CLI_SHOWUSAGE;
15002 
15003    channel = atoi(a->argv[4]);
15004    gain = atof(a->argv[5])*10.0;
15005 
15006    ast_mutex_lock(&iflock);
15007 
15008    for (tmp = iflist; tmp; tmp = tmp->next) {
15009 
15010       if (tmp->channel != channel)
15011          continue;
15012 
15013       if (tmp->subs[SUB_REAL].dfd == -1)
15014          break;
15015 
15016       hwgain.newgain = gain;
15017       hwgain.tx = tx;
15018       if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
15019          ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
15020          ast_mutex_unlock(&iflock);
15021          return CLI_FAILURE;
15022       }
15023       ast_cli(a->fd, "hardware %s gain set to %d (%.1f dB) on channel %d\n",
15024          tx ? "tx" : "rx", gain, (float)gain/10.0, channel);
15025       break;
15026    }
15027 
15028    ast_mutex_unlock(&iflock);
15029 
15030    if (tmp)
15031       return CLI_SUCCESS;
15032 
15033    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15034    return CLI_FAILURE;
15035 
15036 }

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

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

15039 {
15040    int channel;
15041    float gain;
15042    int tx;
15043    int res;
15044    ast_mutex_t *lock;
15045    struct dahdi_pvt *tmp = NULL;
15046 
15047    switch (cmd) {
15048    case CLI_INIT:
15049       e->command = "dahdi set swgain";
15050       e->usage =
15051          "Usage: dahdi set swgain <rx|tx> <chan#> <gain>\n"
15052          "  Sets the software gain on a a given channel, overriding the\n"
15053          "   value provided at module loadtime, whether the channel is in\n"
15054          "   use or not.  Changes take effect immediately.\n"
15055          "   <rx|tx> which direction do you want to change (relative to our module)\n"
15056          "   <chan num> is the channel number relative to the device\n"
15057          "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
15058       return NULL;
15059    case CLI_GENERATE:
15060       return NULL;
15061    }
15062 
15063    lock = &iflock;
15064 
15065    if (a->argc != 6)
15066       return CLI_SHOWUSAGE;
15067 
15068    if (!strcasecmp("rx", a->argv[3]))
15069       tx = 0; /* rx */
15070    else if (!strcasecmp("tx", a->argv[3]))
15071       tx = 1; /* tx */
15072    else
15073       return CLI_SHOWUSAGE;
15074 
15075    channel = atoi(a->argv[4]);
15076    gain = atof(a->argv[5]);
15077 
15078    ast_mutex_lock(lock);
15079    for (tmp = iflist; tmp; tmp = tmp->next) {
15080 
15081       if (tmp->channel != channel)
15082          continue;
15083 
15084       if (tmp->subs[SUB_REAL].dfd == -1)
15085          break;
15086 
15087       if (tx)
15088          res = set_actual_txgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15089       else
15090          res = set_actual_rxgain(tmp->subs[SUB_REAL].dfd, channel, gain, tmp->law);
15091 
15092       if (res) {
15093          ast_cli(a->fd, "Unable to set the software gain for channel %d\n", channel);
15094          ast_mutex_unlock(lock);
15095          return CLI_FAILURE;
15096       }
15097 
15098       ast_cli(a->fd, "software %s gain set to %.1f on channel %d\n",
15099          tx ? "tx" : "rx", gain, channel);
15100       break;
15101    }
15102    ast_mutex_unlock(lock);
15103 
15104    if (tmp)
15105       return CLI_SUCCESS;
15106 
15107    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
15108    return CLI_FAILURE;
15109 
15110 }

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

Definition at line 11090 of file chan_dahdi.c.

Referenced by pri_dchannel(), and ss7_start_call().

11091 {
11092    return ioctl(dfd, DAHDI_SETLAW, &law);
11093 }

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

Definition at line 2165 of file chan_dahdi.c.

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

02166 {
02167    int res;
02168    res = ioctl(dfd, DAHDI_SETLINEAR, &linear);
02169    if (res)
02170       return res;
02171    return 0;
02172 }

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 4837 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_NOTICE, LOG_WARNING, dahdi_pvt::mate, oprmode::mode, ast_channel::name, dahdi_pvt::oprmode, dahdi_pvt::oprpeer, oprmode::peer, pp, READ_SIZE, dahdi_pvt::rxgain, set_actual_rxgain(), set_actual_txgain(), SUB_REAL, dahdi_pvt::subs, dahdi_pvt::tdd, tdd_free(), tdd_new(), ast_channel::tech, ast_channel::tech_pvt, dahdi_pvt::txgain, and ast_channel_tech::type.

04838 {
04839    char *cp;
04840    signed char *scp;
04841    int x;
04842    int idx;
04843    struct dahdi_pvt *p = chan->tech_pvt, *pp;
04844    struct oprmode *oprmode;
04845 
04846 
04847    /* all supported options require data */
04848    if (!data || (datalen < 1)) {
04849       errno = EINVAL;
04850       return -1;
04851    }
04852 
04853    switch (option) {
04854    case AST_OPTION_TXGAIN:
04855       scp = (signed char *) data;
04856       idx = dahdi_get_index(chan, p, 0);
04857       if (idx < 0) {
04858          ast_log(LOG_WARNING, "No index in TXGAIN?\n");
04859          return -1;
04860       }
04861       ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
04862       return set_actual_txgain(p->subs[idx].dfd, 0, p->txgain + (float) *scp, p->law);
04863    case AST_OPTION_RXGAIN:
04864       scp = (signed char *) data;
04865       idx = dahdi_get_index(chan, p, 0);
04866       if (idx < 0) {
04867          ast_log(LOG_WARNING, "No index in RXGAIN?\n");
04868          return -1;
04869       }
04870       ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
04871       return set_actual_rxgain(p->subs[idx].dfd, 0, p->rxgain + (float) *scp, p->law);
04872    case AST_OPTION_TONE_VERIFY:
04873       if (!p->dsp)
04874          break;
04875       cp = (char *) data;
04876       switch (*cp) {
04877       case 1:
04878          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
04879          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | p->dtmfrelax);  /* set mute mode if desired */
04880          break;
04881       case 2:
04882          ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
04883          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax);  /* set mute mode if desired */
04884          break;
04885       default:
04886          ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
04887          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);  /* set mute mode if desired */
04888          break;
04889       }
04890       break;
04891    case AST_OPTION_TDD:
04892       /* turn on or off TDD */
04893       cp = (char *) data;
04894       p->mate = 0;
04895       if (!*cp) { /* turn it off */
04896          ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
04897          if (p->tdd)
04898             tdd_free(p->tdd);
04899          p->tdd = 0;
04900          break;
04901       }
04902       ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
04903          (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
04904       dahdi_disable_ec(p);
04905       /* otherwise, turn it on */
04906       if (!p->didtdd) { /* if havent done it yet */
04907          unsigned char mybuf[41000];/*! \todo XXX This is an abuse of the stack!! */
04908          unsigned char *buf;
04909          int size, res, fd, len;
04910          struct pollfd fds[1];
04911 
04912          buf = mybuf;
04913          memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
04914          ast_tdd_gen_ecdisa(buf + 16000, 16000);  /* put in tone */
04915          len = 40000;
04916          idx = dahdi_get_index(chan, p, 0);
04917          if (idx < 0) {
04918             ast_log(LOG_WARNING, "No index in TDD?\n");
04919             return -1;
04920          }
04921          fd = p->subs[idx].dfd;
04922          while (len) {
04923             if (ast_check_hangup(chan))
04924                return -1;
04925             size = len;
04926             if (size > READ_SIZE)
04927                size = READ_SIZE;
04928             fds[0].fd = fd;
04929             fds[0].events = POLLPRI | POLLOUT;
04930             fds[0].revents = 0;
04931             res = poll(fds, 1, -1);
04932             if (!res) {
04933                ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
04934                continue;
04935             }
04936             /* if got exception */
04937             if (fds[0].revents & POLLPRI)
04938                return -1;
04939             if (!(fds[0].revents & POLLOUT)) {
04940                ast_debug(1, "write fd not ready on channel %d\n", p->channel);
04941                continue;
04942             }
04943             res = write(fd, buf, size);
04944             if (res != size) {
04945                if (res == -1) return -1;
04946                ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
04947                break;
04948             }
04949             len -= size;
04950             buf += size;
04951          }
04952          p->didtdd = 1; /* set to have done it now */
04953       }
04954       if (*cp == 2) { /* Mate mode */
04955          if (p->tdd)
04956             tdd_free(p->tdd);
04957          p->tdd = 0;
04958          p->mate = 1;
04959          break;
04960       }
04961       if (!p->tdd) { /* if we dont have one yet */
04962          p->tdd = tdd_new(); /* allocate one */
04963       }
04964       break;
04965    case AST_OPTION_RELAXDTMF:  /* Relax DTMF decoding (or not) */
04966       if (!p->dsp)
04967          break;
04968       cp = (char *) data;
04969       ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
04970          *cp ? "ON" : "OFF", (int) *cp, chan->name);
04971       ast_dsp_set_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
04972       break;
04973    case AST_OPTION_AUDIO_MODE:  /* Set AUDIO mode (or not) */
04974       cp = (char *) data;
04975       if (!*cp) {
04976          ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
04977          x = 0;
04978          dahdi_disable_ec(p);
04979       } else {
04980          ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
04981          x = 1;
04982       }
04983       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &x) == -1)
04984          ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
04985       break;
04986    case AST_OPTION_OPRMODE:  /* Operator services mode */
04987       oprmode = (struct oprmode *) data;
04988       /* We don't support operator mode across technologies */
04989       if (strcasecmp(chan->tech->type, oprmode->peer->tech->type)) {
04990          ast_log(LOG_NOTICE, "Operator mode not supported on %s to %s calls.\n",
04991                chan->tech->type, oprmode->peer->tech->type);
04992          errno = EINVAL;
04993          return -1;
04994       }
04995       pp = oprmode->peer->tech_pvt;
04996       p->oprmode = pp->oprmode = 0;
04997       /* setup peers */
04998       p->oprpeer = pp;
04999       pp->oprpeer = p;
05000       /* setup modes, if any */
05001       if (oprmode->mode)
05002       {
05003          pp->oprmode = oprmode->mode;
05004          p->oprmode = -oprmode->mode;
05005       }
05006       ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
05007          oprmode->mode, chan->name,oprmode->peer->name);
05008       break;
05009    case AST_OPTION_ECHOCAN:
05010       cp = (char *) data;
05011       if (*cp) {
05012          ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
05013          dahdi_enable_ec(p);
05014       } else {
05015          ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
05016          dahdi_disable_ec(p);
05017       }
05018       break;
05019    }
05020    errno = 0;
05021 
05022    return 0;
05023 }

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

Definition at line 14609 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_channel::name, ast_variable::name, dahdi_pvt::next, ast_variable::next, NUM_SPANS, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::params, dahdi_pvt::pri, dahdi_pri::pri, pris, dahdi_pvt::propconfno, dahdi_pvt::pulsedial, dahdi_pvt::radio, dahdi_pvt::resetting, S_OR, dahdi_pvt::sig, sig2str, dahdi_pvt::slaves, dahdi_pvt::span, dahdi_pvt::ss7, SUB_CALLWAIT, SUB_REAL, SUB_THREEWAY, dahdi_pvt::subs, dahdi_pvt::tdd, ast_cli_entry::usage, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

14610 {
14611    int channel;
14612    struct dahdi_pvt *tmp = NULL;
14613    struct dahdi_confinfo ci;
14614    struct dahdi_params ps;
14615    int x;
14616    ast_mutex_t *lock;
14617    struct dahdi_pvt *start;
14618 #ifdef HAVE_PRI
14619    char *c;
14620    int trunkgroup;
14621    struct dahdi_pri *pri=NULL;
14622 #endif
14623    switch (cmd) {
14624    case CLI_INIT:
14625       e->command = "dahdi show channel";
14626       e->usage =
14627          "Usage: dahdi show channel <chan num>\n"
14628          "  Detailed information about a given channel\n";
14629       return NULL;
14630    case CLI_GENERATE:
14631       return NULL;
14632    }
14633 
14634    lock = &iflock;
14635    start = iflist;
14636 
14637    if (a->argc != 4)
14638       return CLI_SHOWUSAGE;
14639 #ifdef HAVE_PRI
14640    if ((c = strchr(a->argv[3], ':'))) {
14641       if (sscanf(a->argv[3], "%30d:%30d", &trunkgroup, &channel) != 2)
14642          return CLI_SHOWUSAGE;
14643       if ((trunkgroup < 1) || (channel < 1))
14644          return CLI_SHOWUSAGE;
14645       for (x = 0; x < NUM_SPANS; x++) {
14646          if (pris[x].trunkgroup == trunkgroup) {
14647             pri = pris + x;
14648             break;
14649          }
14650       }
14651       if (pri) {
14652          start = pri->crvs;
14653          lock = &pri->lock;
14654       } else {
14655          ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14656          return CLI_FAILURE;
14657       }
14658    } else
14659 #endif
14660       channel = atoi(a->argv[3]);
14661 
14662    ast_mutex_lock(lock);
14663    tmp = start;
14664    while (tmp) {
14665       if (tmp->channel == channel) {
14666 #ifdef HAVE_PRI
14667          if (pri)
14668             ast_cli(a->fd, "Trunk/CRV: %d/%d\n", trunkgroup, tmp->channel);
14669          else
14670 #endif
14671          ast_cli(a->fd, "Channel: %d\n", tmp->channel);
14672          ast_cli(a->fd, "File Descriptor: %d\n", tmp->subs[SUB_REAL].dfd);
14673          ast_cli(a->fd, "Span: %d\n", tmp->span);
14674          ast_cli(a->fd, "Extension: %s\n", tmp->exten);
14675          ast_cli(a->fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
14676          ast_cli(a->fd, "Context: %s\n", tmp->context);
14677          ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
14678          ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
14679          ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
14680          ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
14681          if (tmp->vars) {
14682             struct ast_variable *v;
14683             ast_cli(a->fd, "Variables:\n");
14684             for (v = tmp->vars ; v ; v = v->next)
14685                ast_cli(a->fd, "       %s = %s\n", v->name, v->value);
14686          }
14687          ast_cli(a->fd, "Destroy: %d\n", tmp->destroy);
14688          ast_cli(a->fd, "InAlarm: %d\n", tmp->inalarm);
14689          ast_cli(a->fd, "Signalling Type: %s\n", sig2str(tmp->sig));
14690          ast_cli(a->fd, "Radio: %d\n", tmp->radio);
14691          ast_cli(a->fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
14692          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)" : "");
14693          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)" : "");
14694          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)" : "");
14695          ast_cli(a->fd, "Confno: %d\n", tmp->confno);
14696          ast_cli(a->fd, "Propagated Conference: %d\n", tmp->propconfno);
14697          ast_cli(a->fd, "Real in conference: %d\n", tmp->inconference);
14698          ast_cli(a->fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
14699          ast_cli(a->fd, "Busy Detection: %s\n", tmp->busydetect ? "yes" : "no");
14700          if (tmp->busydetect) {
14701 #if defined(BUSYDETECT_TONEONLY)
14702             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_TONEONLY\n");
14703 #elif defined(BUSYDETECT_COMPARE_TONE_AND_SILENCE)
14704             ast_cli(a->fd, "    Busy Detector Helper: BUSYDETECT_COMPARE_TONE_AND_SILENCE\n");
14705 #endif
14706 #ifdef BUSYDETECT_DEBUG
14707             ast_cli(a->fd, "    Busy Detector Debug: Enabled\n");
14708 #endif
14709             ast_cli(a->fd, "    Busy Count: %d\n", tmp->busycount);
14710             ast_cli(a->fd, "    Busy Pattern: %d,%d\n", tmp->busy_tonelength, tmp->busy_quietlength);
14711          }
14712          ast_cli(a->fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
14713          ast_cli(a->fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
14714          ast_cli(a->fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
14715          ast_cli(a->fd, "Default law: %s\n", tmp->law == DAHDI_LAW_MULAW ? "ulaw" : tmp->law == DAHDI_LAW_ALAW ? "alaw" : "unknown");
14716          ast_cli(a->fd, "Fax Handled: %s\n", tmp->faxhandled ? "yes" : "no");
14717          ast_cli(a->fd, "Pulse phone: %s\n", tmp->pulsedial ? "yes" : "no");
14718          ast_cli(a->fd, "DND: %s\n", tmp->dnd ? "yes" : "no");
14719          ast_cli(a->fd, "Echo Cancellation:\n");
14720 
14721          if (tmp->echocancel.head.tap_length) {
14722             ast_cli(a->fd, "\t%d taps\n", tmp->echocancel.head.tap_length);
14723             for (x = 0; x < tmp->echocancel.head.param_count; x++) {
14724                ast_cli(a->fd, "\t\t%s: %ud\n", tmp->echocancel.params[x].name, tmp->echocancel.params[x].value);
14725             }
14726             ast_cli(a->fd, "\t%scurrently %s\n", tmp->echocanbridged ? "" : "(unless TDM bridged) ", tmp->echocanon ? "ON" : "OFF");
14727          } else {
14728             ast_cli(a->fd, "\tnone\n");
14729          }
14730          ast_cli(a->fd, "Wait for dialtone: %dms\n", tmp->waitfordialtone);
14731          if (tmp->master)
14732             ast_cli(a->fd, "Master Channel: %d\n", tmp->master->channel);
14733          for (x = 0; x < MAX_SLAVES; x++) {
14734             if (tmp->slaves[x])
14735                ast_cli(a->fd, "Slave Channel: %d\n", tmp->slaves[x]->channel);
14736          }
14737 #ifdef HAVE_OPENR2
14738          if (tmp->mfcr2) {
14739             char calldir[OR2_MAX_PATH];
14740             openr2_context_t *r2context = openr2_chan_get_context(tmp->r2chan);
14741             openr2_variant_t r2variant = openr2_context_get_variant(r2context);
14742             ast_cli(a->fd, "MFC/R2 MF State: %s\n", openr2_chan_get_mf_state_string(tmp->r2chan));
14743             ast_cli(a->fd, "MFC/R2 MF Group: %s\n", openr2_chan_get_mf_group_string(tmp->r2chan));
14744             ast_cli(a->fd, "MFC/R2 State: %s\n", openr2_chan_get_r2_state_string(tmp->r2chan));
14745             ast_cli(a->fd, "MFC/R2 Call State: %s\n", openr2_chan_get_call_state_string(tmp->r2chan));
14746             ast_cli(a->fd, "MFC/R2 Call Files Enabled: %s\n", openr2_chan_get_call_files_enabled(tmp->r2chan) ? "Yes" : "No");
14747             ast_cli(a->fd, "MFC/R2 Variant: %s\n", openr2_proto_get_variant_string(r2variant));
14748             ast_cli(a->fd, "MFC/R2 Max ANI: %d\n", openr2_context_get_max_ani(r2context));
14749             ast_cli(a->fd, "MFC/R2 Max DNIS: %d\n", openr2_context_get_max_dnis(r2context));
14750             ast_cli(a->fd, "MFC/R2 Get ANI First: %s\n", openr2_context_get_ani_first(r2context) ? "Yes" : "No");
14751 #if defined(OR2_LIB_INTERFACE) && OR2_LIB_INTERFACE > 1
14752             ast_cli(a->fd, "MFC/R2 Skip Category Request: %s\n", openr2_context_get_skip_category_request(r2context) ? "Yes" : "No");
14753 #endif
14754             ast_cli(a->fd, "MFC/R2 Immediate Accept: %s\n", openr2_context_get_immediate_accept(r2context) ? "Yes" : "No");
14755             ast_cli(a->fd, "MFC/R2 Accept on Offer: %s\n", tmp->mfcr2_accept_on_offer ? "Yes" : "No");
14756             ast_cli(a->fd, "MFC/R2 Charge Calls: %s\n", tmp->mfcr2_charge_calls ? "Yes" : "No");
14757             ast_cli(a->fd, "MFC/R2 Allow Collect Calls: %s\n", tmp->mfcr2_allow_collect_calls ? "Yes" : "No");
14758             ast_cli(a->fd, "MFC/R2 Forced Release: %s\n", tmp->mfcr2_forced_release ? "Yes" : "No");
14759             ast_cli(a->fd, "MFC/R2 MF Back Timeout: %dms\n", openr2_context_get_mf_back_timeout(r2context));
14760             ast_cli(a->fd, "MFC/R2 R2 Metering Pulse Timeout: %dms\n", openr2_context_get_metering_pulse_timeout(r2context));
14761             ast_cli(a->fd, "MFC/R2 Rx CAS: %s\n", openr2_chan_get_rx_cas_string(tmp->r2chan));
14762             ast_cli(a->fd, "MFC/R2 Tx CAS: %s\n", openr2_chan_get_tx_cas_string(tmp->r2chan));
14763             ast_cli(a->fd, "MFC/R2 MF Tx Signal: %d\n", openr2_chan_get_tx_mf_signal(tmp->r2chan));
14764             ast_cli(a->fd, "MFC/R2 MF Rx Signal: %d\n", openr2_chan_get_rx_mf_signal(tmp->r2chan));
14765             ast_cli(a->fd, "MFC/R2 Call Files Directory: %s\n", openr2_context_get_log_directory(r2context, calldir, sizeof(calldir)));
14766          }
14767 #endif
14768 #ifdef HAVE_SS7
14769          if (tmp->ss7) {
14770             ast_cli(a->fd, "CIC: %d\n", tmp->cic);
14771          }
14772 #endif
14773 #ifdef HAVE_PRI
14774          if (tmp->pri) {
14775             ast_cli(a->fd, "PRI Flags: ");
14776             if (tmp->resetting)
14777                ast_cli(a->fd, "Resetting ");
14778             if (tmp->call)
14779                ast_cli(a->fd, "Call ");
14780             if (tmp->bearer)
14781                ast_cli(a->fd, "Bearer ");
14782             ast_cli(a->fd, "\n");
14783             if (tmp->logicalspan)
14784                ast_cli(a->fd, "PRI Logical Span: %d\n", tmp->logicalspan);
14785             else
14786                ast_cli(a->fd, "PRI Logical Span: Implicit\n");
14787          }
14788 #endif
14789          memset(&ci, 0, sizeof(ci));
14790          ps.channo = tmp->channel;
14791          if (tmp->subs[SUB_REAL].dfd > -1) {
14792             memset(&ci, 0, sizeof(ci));
14793             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONF, &ci)) {
14794                ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
14795             }
14796             if (!ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GETCONFMUTE, &x)) {
14797                ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
14798             }
14799             memset(&ps, 0, sizeof(ps));
14800             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps) < 0) {
14801                ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
14802             } else {
14803                ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
14804             }
14805          }
14806          ast_mutex_unlock(lock);
14807          return CLI_SUCCESS;
14808       }
14809       tmp = tmp->next;
14810    }
14811 
14812    ast_cli(a->fd, "Unable to find given channel %d\n", channel);
14813    ast_mutex_unlock(lock);
14814    return CLI_FAILURE;
14815 }

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

Definition at line 14485 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, dahdi_pri::pri, pris, dahdi_pvt::remotelyblocked, and ast_cli_entry::usage.

14486 {
14487 #define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14488 #define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
14489    unsigned int targetnum = 0;
14490    int filtertype = 0;
14491    struct dahdi_pvt *tmp = NULL;
14492    char tmps[20] = "";
14493    char statestr[20] = "";
14494    char blockstr[20] = "";
14495    ast_mutex_t *lock;
14496    struct dahdi_pvt *start;
14497 #ifdef HAVE_PRI
14498    int trunkgroup;
14499    struct dahdi_pri *pri = NULL;
14500    int x;
14501 #endif
14502    switch (cmd) {
14503    case CLI_INIT:
14504       e->command = "dahdi show channels [trunkgroup|group|context]";
14505       e->usage =
14506          "Usage: dahdi show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
14507          "  Shows a list of available channels with optional filtering\n"
14508          "  <group> must be a number between 0 and 63\n";
14509       return NULL;
14510    case CLI_GENERATE:
14511       return NULL;
14512    }
14513 
14514    lock = &iflock;
14515    start = iflist;
14516 
14517    /* syntax: dahdi show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
14518 
14519    if (!((a->argc == 3) || (a->argc == 5)))
14520       return CLI_SHOWUSAGE;
14521 
14522    if (a->argc == 5) {
14523 #ifdef HAVE_PRI
14524       if (!strcasecmp(a->argv[3], "trunkgroup")) {
14525          /* this option requires no special handling, so leave filtertype to zero */
14526          if ((trunkgroup = atoi(a->argv[4])) < 1)
14527             return CLI_SHOWUSAGE;
14528          for (x = 0; x < NUM_SPANS; x++) {
14529             if (pris[x].trunkgroup == trunkgroup) {
14530                pri = pris + x;
14531                break;
14532             }
14533          }
14534          if (pri) {
14535             start = pri->crvs;
14536             lock = &pri->lock;
14537          } else {
14538             ast_cli(a->fd, "No such trunk group %d\n", trunkgroup);
14539             return CLI_FAILURE;
14540          }
14541       } else
14542 #endif
14543       if (!strcasecmp(a->argv[3], "group")) {
14544          targetnum = atoi(a->argv[4]);
14545          if ((targetnum < 0) || (targetnum > 63))
14546             return CLI_SHOWUSAGE;
14547          targetnum = 1 << targetnum;
14548          filtertype = 1;
14549       } else if (!strcasecmp(a->argv[3], "context")) {
14550          filtertype = 2;
14551       }
14552    }
14553 
14554    ast_mutex_lock(lock);
14555 #ifdef HAVE_PRI
14556    ast_cli(a->fd, FORMAT2, pri ? "CRV" : "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14557 #else
14558    ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State");
14559 #endif
14560 
14561    tmp = start;
14562    while (tmp) {
14563       if (filtertype) {
14564          switch(filtertype) {
14565          case 1: /* dahdi show channels group <group> */
14566             if (!(tmp->group & targetnum)) {
14567                tmp = tmp->next;
14568                continue;
14569             }
14570             break;
14571          case 2: /* dahdi show channels context <context> */
14572             if (strcasecmp(tmp->context, a->argv[4])) {
14573                tmp = tmp->next;
14574                continue;
14575             }
14576             break;
14577          default:
14578             ;
14579          }
14580       }
14581       if (tmp->channel > 0) {
14582          snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
14583       } else
14584          ast_copy_string(tmps, "pseudo", sizeof(tmps));
14585 
14586       if (tmp->locallyblocked)
14587          blockstr[0] = 'L';
14588       else
14589          blockstr[0] = ' ';
14590 
14591       if (tmp->remotelyblocked)
14592          blockstr[1] = 'R';
14593       else
14594          blockstr[1] = ' ';
14595 
14596       blockstr[2] = '\0';
14597 
14598       snprintf(statestr, sizeof(statestr), "%s", "In Service");
14599 
14600       ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr);
14601       tmp = tmp->next;
14602    }
14603    ast_mutex_unlock(lock);
14604    return CLI_SUCCESS;
14605 #undef FORMAT
14606 #undef FORMAT2
14607 }

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

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

14855 {
14856    #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
14857    #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
14858    int span;
14859    int res;
14860    char alarmstr[50];
14861 
14862    int ctl;
14863    struct dahdi_spaninfo s;
14864 
14865    switch (cmd) {
14866    case CLI_INIT:
14867       e->command = "dahdi show status";
14868       e->usage =
14869          "Usage: dahdi show status\n"
14870          "       Shows a list of DAHDI cards with status\n";
14871       return NULL;
14872    case CLI_GENERATE:
14873       return NULL;
14874    }
14875    ctl = open("/dev/dahdi/ctl", O_RDWR);
14876    if (ctl < 0) {
14877       ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
14878       return CLI_FAILURE;
14879    }
14880    ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
14881 
14882    for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
14883       s.spanno = span;
14884       res = ioctl(ctl, DAHDI_SPANSTAT, &s);
14885       if (res) {
14886          continue;
14887       }
14888       alarmstr[0] = '\0';
14889       if (s.alarms > 0) {
14890          if (s.alarms & DAHDI_ALARM_BLUE)
14891             strcat(alarmstr, "BLU/");
14892          if (s.alarms & DAHDI_ALARM_YELLOW)
14893             strcat(alarmstr, "YEL/");
14894          if (s.alarms & DAHDI_ALARM_RED)
14895             strcat(alarmstr, "RED/");
14896          if (s.alarms & DAHDI_ALARM_LOOPBACK)
14897             strcat(alarmstr, "LB/");
14898          if (s.alarms & DAHDI_ALARM_RECOVER)
14899             strcat(alarmstr, "REC/");
14900          if (s.alarms & DAHDI_ALARM_NOTOPEN)
14901             strcat(alarmstr, "NOP/");
14902          if (!strlen(alarmstr))
14903             strcat(alarmstr, "UUU/");
14904          if (strlen(alarmstr)) {
14905             /* Strip trailing / */
14906             alarmstr[strlen(alarmstr) - 1] = '\0';
14907          }
14908       } else {
14909          if (s.numchans)
14910             strcpy(alarmstr, "OK");
14911          else
14912             strcpy(alarmstr, "UNCONFIGURED");
14913       }
14914 
14915       ast_cli(a->fd, FORMAT, s.desc, alarmstr, s.irqmisses, s.bpvcount, s.crc4count,
14916          s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
14917          s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
14918          s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
14919          "CAS",
14920          s.lineconfig & DAHDI_CONFIG_B8ZS ? "B8ZS" :
14921          s.lineconfig & DAHDI_CONFIG_HDB3 ? "HDB3" :
14922          s.lineconfig & DAHDI_CONFIG_AMI ? "AMI" :
14923          "Unk",
14924          s.lineconfig & DAHDI_CONFIG_CRC4 ?
14925          s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL",
14926          lbostr[s.lbo]
14927          );
14928    }
14929    close(ctl);
14930 
14931    return CLI_SUCCESS;
14932 #undef FORMAT
14933 #undef FORMAT2
14934 }

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

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

14937 {
14938    int pseudo_fd = -1;
14939    struct dahdi_versioninfo vi;
14940 
14941    switch (cmd) {
14942    case CLI_INIT:
14943       e->command = "dahdi show version";
14944       e->usage =
14945          "Usage: dahdi show version\n"
14946          "       Shows the DAHDI version in use\n";
14947       return NULL;
14948    case CLI_GENERATE:
14949       return NULL;
14950    }
14951    if ((pseudo_fd = open("/dev/dahdi/ctl", O_RDONLY)) < 0) {
14952       ast_cli(a->fd, "Failed to open control file to get version.\n");
14953       return CLI_SUCCESS;
14954    }
14955 
14956    strcpy(vi.version, "Unknown");
14957    strcpy(vi.echo_canceller, "Unknown");
14958 
14959    if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
14960       ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
14961    else
14962       ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
14963 
14964    close(pseudo_fd);
14965 
14966    return CLI_SUCCESS;
14967 }

static char* dahdi_sig2str ( int  sig  )  [static]

Definition at line 2408 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_MFCR2, SIG_PRI, SIG_SF, SIG_SF_FEATB, SIG_SF_FEATD, SIG_SF_FEATDMF, SIG_SFWINK, and SIG_SS7.

02409 {
02410    static char buf[256];
02411    switch (sig) {
02412    case SIG_EM:
02413       return "E & M Immediate";
02414    case SIG_EMWINK:
02415       return "E & M Wink";
02416    case SIG_EM_E1:
02417       return "E & M E1";
02418    case SIG_FEATD:
02419       return "Feature Group D (DTMF)";
02420    case SIG_FEATDMF:
02421       return "Feature Group D (MF)";
02422    case SIG_FEATDMF_TA:
02423       return "Feature Groud D (MF) Tandem Access";
02424    case SIG_FEATB:
02425       return "Feature Group B (MF)";
02426    case SIG_E911:
02427       return "E911 (MF)";
02428    case SIG_FGC_CAMA:
02429       return "FGC/CAMA (Dialpulse)";
02430    case SIG_FGC_CAMAMF:
02431       return "FGC/CAMA (MF)";
02432    case SIG_FXSLS:
02433       return "FXS Loopstart";
02434    case SIG_FXSGS:
02435       return "FXS Groundstart";
02436    case SIG_FXSKS:
02437       return "FXS Kewlstart";
02438    case SIG_FXOLS:
02439       return "FXO Loopstart";
02440    case SIG_FXOGS:
02441       return "FXO Groundstart";
02442    case SIG_FXOKS:
02443       return "FXO Kewlstart";
02444    case SIG_PRI:
02445       return "ISDN PRI";
02446    case SIG_BRI:
02447       return "ISDN BRI Point to Point";
02448    case SIG_BRI_PTMP:
02449       return "ISDN BRI Point to MultiPoint";
02450    case SIG_SS7:
02451       return "SS7";
02452    case SIG_MFCR2:
02453       return "MFC/R2";
02454    case SIG_SF:
02455       return "SF (Tone) Immediate";
02456    case SIG_SFWINK:
02457       return "SF (Tone) Wink";
02458    case SIG_SF_FEATD:
02459       return "SF (Tone) with Feature Group D (DTMF)";
02460    case SIG_SF_FEATDMF:
02461       return "SF (Tone) with Feature Group D (MF)";
02462    case SIG_SF_FEATB:
02463       return "SF (Tone) with Feature Group B (MF)";
02464    case SIG_GR303FXOKS:
02465       return "GR-303 with FXOKS";
02466    case SIG_GR303FXSKS:
02467       return "GR-303 with FXSKS";
02468    case 0:
02469       return "Pseudo";
02470    default:
02471       snprintf(buf, sizeof(buf), "Unknown signalling %d", sig);
02472       return buf;
02473    }
02474 }

static void dahdi_softhangup_all ( void   )  [static]

Definition at line 14309 of file chan_dahdi.c.

References ast_channel_trylock, ast_channel_unlock, ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_verbose, iflist, iflock, dahdi_pvt::lock, ast_channel::name, dahdi_pvt::next, option_debug, dahdi_pvt::owner, and dahdi_pvt::restartpending.

Referenced by dahdi_restart().

14310 {
14311    struct dahdi_pvt *p;
14312 retry:
14313    ast_mutex_lock(&iflock);
14314    for (p = iflist; p; p = p->next) {
14315       ast_mutex_lock(&p->lock);
14316       if (p->owner && !p->restartpending) {
14317          if (ast_channel_trylock(p->owner)) {
14318             if (option_debug > 2)
14319                ast_verbose("Avoiding deadlock\n");
14320             /* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
14321             ast_mutex_unlock(&p->lock);
14322             ast_mutex_unlock(&iflock);
14323             goto retry;
14324          }
14325          if (option_debug > 2)
14326             ast_verbose("Softhanging up on %s\n", p->owner->name);
14327          ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
14328          p->restartpending = 1;
14329          num_restart_pending++;
14330          ast_channel_unlock(p->owner);
14331       }
14332       ast_mutex_unlock(&p->lock);
14333    }
14334    ast_mutex_unlock(&iflock);
14335 }

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

Definition at line 11939 of file chan_dahdi.c.

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

Referenced by dahdi_restart(), and load_module().

11940 {
11941 #if 0
11942    int i;
11943 
11944    for (i = 0; i < NUM_SPANS; i++)
11945       if (linksets[i].ss7 == ss7)
11946          break;
11947 
11948 #else
11949    ast_log(LOG_ERROR, "%s", s);
11950 #endif
11951 }

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

Definition at line 11922 of file chan_dahdi.c.

References ast_verbose, linksets, and NUM_SPANS.

Referenced by dahdi_restart(), and load_module().

11923 {
11924 #if 0
11925    int i;
11926 
11927    for (i = 0; i < NUM_SPANS; i++)
11928       if (linksets[i].ss7 == ss7)
11929          break;
11930 
11931    ast_verbose("[%d] %s", i+1, s);
11932 #else
11933    ast_verbose("%s", s);
11934 #endif
11935 }

static void dahdi_train_ec ( struct dahdi_pvt p  )  [static]

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

02693 {
02694    int x;
02695    int res;
02696 
02697    if (p && p->echocanon && p->echotraining) {
02698       x = p->echotraining;
02699       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_ECHOTRAIN, &x);
02700       if (res)
02701          ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
02702       else
02703          ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
02704    } else {
02705       ast_debug(1, "No echo training requested\n");
02706    }
02707 }

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

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

05045 {
05046    /* Unlink a specific slave or all slaves/masters from a given master */
05047    int x;
05048    int hasslaves;
05049    if (!master)
05050       return;
05051    if (needlock) {
05052       ast_mutex_lock(&master->lock);
05053       if (slave) {
05054          while (ast_mutex_trylock(&slave->lock)) {
05055             DEADLOCK_AVOIDANCE(&master->lock);
05056          }
05057       }
05058    }
05059    hasslaves = 0;
05060    for (x = 0; x < MAX_SLAVES; x++) {
05061       if (master->slaves[x]) {
05062          if (!slave || (master->slaves[x] == slave)) {
05063             /* Take slave out of the conference */
05064             ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
05065             conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
05066             conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
05067             master->slaves[x]->master = NULL;
05068             master->slaves[x] = NULL;
05069          } else
05070             hasslaves = 1;
05071       }
05072       if (!hasslaves)
05073          master->inconference = 0;
05074    }
05075    if (!slave) {
05076       if (master->master) {
05077          /* Take master out of the conference */
05078          conf_del(master->master, &master->subs[SUB_REAL], SUB_REAL);
05079          conf_del(master, &master->master->subs[SUB_REAL], SUB_REAL);
05080          hasslaves = 0;
05081          for (x = 0; x < MAX_SLAVES; x++) {
05082             if (master->master->slaves[x] == master)
05083                master->master->slaves[x] = NULL;
05084             else if (master->master->slaves[x])
05085                hasslaves = 1;
05086          }
05087          if (!hasslaves)
05088             master->master->inconference = 0;
05089       }
05090       master->master = NULL;
05091    }
05092    update_conf(master);
05093    if (needlock) {
05094       if (slave)
05095          ast_mutex_unlock(&slave->lock);
05096       ast_mutex_unlock(&master->lock);
05097    }
05098 }

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

Avoid the silly dahdi_waitevent which ignores a bunch of events.

Definition at line 385 of file chan_dahdi.c.

Referenced by ss_thread().

00386 {
00387    int i, j = 0;
00388    i = DAHDI_IOMUX_SIGEVENT;
00389    if (ioctl(fd, DAHDI_IOMUX, &i) == -1)
00390       return -1;
00391    if (ioctl(fd, DAHDI_GETEVENT, &j) == -1)
00392       return -1;
00393    return j;
00394 }

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

Definition at line 7635 of file chan_dahdi.c.

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

Referenced by ss_thread().

07636 {
07637    int j;
07638    dahdi_set_hook(p->subs[idx].dfd, DAHDI_WINK);
07639    for (;;)
07640    {
07641       /* set bits of interest */
07642       j = DAHDI_IOMUX_SIGEVENT;
07643       /* wait for some happening */
07644       if (ioctl(p->subs[idx].dfd,DAHDI_IOMUX,&j) == -1) return(-1);
07645       /* exit loop if we have it */
07646       if (j & DAHDI_IOMUX_SIGEVENT) break;
07647    }
07648    /* get the event info */
07649    if (ioctl(p->subs[idx].dfd,DAHDI_GETEVENT,&j) == -1) return(-1);
07650    return 0;
07651 }

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

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

07091 {
07092    struct dahdi_pvt *p = ast->tech_pvt;
07093    int res;
07094    int idx;
07095    idx = dahdi_get_index(ast, p, 0);
07096    if (idx < 0) {
07097       ast_log(LOG_WARNING, "%s doesn't really exist?\n", ast->name);
07098       return -1;
07099    }
07100 
07101 #if 0
07102 #ifdef HAVE_PRI
07103    ast_mutex_lock(&p->lock);
07104    if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
07105       if (p->pri->pri) {
07106          if (!pri_grab(p, p->pri)) {
07107                pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
07108                pri_rel(p->pri);
07109          } else
07110                ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07111       }
07112       p->proceeding=1;
07113    }
07114    ast_mutex_unlock(&p->lock);
07115 #endif
07116 #endif
07117    /* Write a frame of (presumably voice) data */
07118    if (frame->frametype != AST_FRAME_VOICE) {
07119       if (frame->frametype != AST_FRAME_IMAGE)
07120          ast_log(LOG_WARNING, "Don't know what to do with frame type '%d'\n", frame->frametype);
07121       return 0;
07122    }
07123    if ((frame->subclass != AST_FORMAT_SLINEAR) &&
07124       (frame->subclass != AST_FORMAT_ULAW) &&
07125       (frame->subclass != AST_FORMAT_ALAW)) {
07126       ast_log(LOG_WARNING, "Cannot handle frames in %d format\n", frame->subclass);
07127       return -1;
07128    }
07129    if (p->dialing) {
07130       ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
07131       return 0;
07132    }
07133    if (!p->owner) {
07134       ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
07135       return 0;
07136    }
07137    if (p->cidspill) {
07138       ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
07139       return 0;
07140    }
07141    /* Return if it's not valid data */
07142    if (!frame->data.ptr || !frame->datalen)
07143       return 0;
07144 
07145    if (frame->subclass == AST_FORMAT_SLINEAR) {
07146       if (!p->subs[idx].linear) {
07147          p->subs[idx].linear = 1;
07148          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07149          if (res)
07150             ast_log(LOG_WARNING, "Unable to set linear mode on channel %d\n", p->channel);
07151       }
07152       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 1);
07153    } else {
07154       /* x-law already */
07155       if (p->subs[idx].linear) {
07156          p->subs[idx].linear = 0;
07157          res = dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
07158          if (res)
07159             ast_log(LOG_WARNING, "Unable to set companded mode on channel %d\n", p->channel);
07160       }
07161       res = my_dahdi_write(p, (unsigned char *)frame->data.ptr, frame->datalen, idx, 0);
07162    }
07163    if (res < 0) {
07164       ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
07165       return -1;
07166    }
07167    return 0;
07168 }

static void destroy_all_channels ( void   )  [static]

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

03930 {
03931    int x;
03932    struct dahdi_pvt *p, *pl;
03933 
03934    while (num_restart_pending) {
03935       usleep(1);
03936    }
03937 
03938    ast_mutex_lock(&iflock);
03939    /* Destroy all the interfaces and free their memory */
03940    p = iflist;
03941    while (p) {
03942       /* Free any callerid */
03943       if (p->cidspill)
03944          ast_free(p->cidspill);
03945       pl = p;
03946       p = p->next;
03947       x = pl->channel;
03948       /* Free associated memory */
03949       if (pl)
03950          destroy_dahdi_pvt(&pl);
03951       if (option_verbose > 2)
03952          ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
03953    }
03954    iflist = NULL;
03955    ifcount = 0;
03956    ast_mutex_unlock(&iflock);
03957 }

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

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

03880 {
03881    int owned = 0;
03882    int i = 0;
03883 
03884    if (!now) {
03885       if (cur->owner) {
03886          owned = 1;
03887       }
03888 
03889       for (i = 0; i < 3; i++) {
03890          if (cur->subs[i].owner) {
03891             owned = 1;
03892          }
03893       }
03894       if (!owned) {
03895          if (prev) {
03896             prev->next = cur->next;
03897             if (prev->next)
03898                prev->next->prev = prev;
03899             else
03900                ifend = prev;
03901          } else {
03902             iflist = cur->next;
03903             if (iflist)
03904                iflist->prev = NULL;
03905             else
03906                ifend = NULL;
03907          }
03908          destroy_dahdi_pvt(&cur);
03909       }
03910    } else {
03911       if (prev) {
03912          prev->next = cur->next;
03913          if (prev->next)
03914             prev->next->prev = prev;
03915          else
03916             ifend = prev;
03917       } else {
03918          iflist = cur->next;
03919          if (iflist)
03920             iflist->prev = NULL;
03921          else
03922             ifend = NULL;
03923       }
03924       destroy_dahdi_pvt(&cur);
03925    }
03926    return 0;
03927 }

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

Definition at line 3856 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 destroy_all_channels(), destroy_channel(), duplicate_pseudo(), and mkintf().

03857 {
03858    struct dahdi_pvt *p = *pvt;
03859    /* Remove channel from the list */
03860    if (p->prev)
03861       p->prev->next = p->next;
03862    if (p->next)
03863       p->next->prev = p->prev;
03864    if (p->use_smdi)
03865       ast_smdi_interface_unref(p->smdi_iface);
03866    if (p->mwi_event_sub)
03867       ast_event_unsubscribe(p->mwi_event_sub);
03868    if (p->vars) {
03869       ast_variables_destroy(p->vars);
03870    }
03871    ast_mutex_destroy(&p->lock);
03872    dahdi_close_sub(p, SUB_REAL);
03873    if (p->owner)
03874       p->owner->tech_pvt = NULL;
03875    free(p);
03876    *pvt = NULL;
03877 }

static char* dialplan2str ( int  dialplan  )  [static]

Definition at line 2399 of file chan_dahdi.c.

Referenced by dahdi_call(), and mkintf().

02400 {
02401    if (dialplan == -1 || dialplan == -2) {
02402       return("Dynamically set dialplan in ISDN");
02403    }
02404    return (pri_plan2str(dialplan));
02405 }

static int digit_to_dtmfindex ( char  digit  )  [static]

Definition at line 2229 of file chan_dahdi.c.

Referenced by dahdi_digit_begin().

02230 {
02231    if (isdigit(digit))
02232       return DAHDI_TONE_DTMF_BASE + (digit - '0');
02233    else if (digit >= 'A' && digit <= 'D')
02234       return DAHDI_TONE_DTMF_A + (digit - 'A');
02235    else if (digit >= 'a' && digit <= 'd')
02236       return DAHDI_TONE_DTMF_A + (digit - 'a');
02237    else if (digit == '*')
02238       return DAHDI_TONE_DTMF_s;
02239    else if (digit == '#')
02240       return DAHDI_TONE_DTMF_p;
02241    else
02242       return -1;
02243 }

static void disable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

05124 {
05125    int val;
05126 
05127    p->ignoredtmf = 1;
05128 
05129    val = 0;
05130    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05131 
05132    if (!p->hardwaredtmf && p->dsp) {
05133       p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
05134       ast_dsp_set_features(p->dsp, p->dsp_features);
05135    }
05136 }

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

Definition at line 12162 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(), dahdi_pvt::channel, ast_channel::context, ast_channel::exten, ast_frame::frametype, dahdi_pri::idlecontext, dahdi_pri::idledial, dahdi_pri::idleext, LOG_WARNING, ast_channel::name, dahdi_pvt::pri, ast_channel::priority, ast_frame::subclass, and ast_channel::tech_pvt.

Referenced by pri_dchannel().

12163 {
12164    struct ast_channel *chan = vchan;
12165    struct dahdi_pvt *pvt = chan->tech_pvt;
12166    struct ast_frame *f;
12167    char ex[80];
12168    /* Wait up to 30 seconds for an answer */
12169    int newms, ms = 30000;
12170    ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
12171    snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
12172    if (ast_call(chan, ex, 0)) {
12173       ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
12174       ast_hangup(chan);
12175       return NULL;
12176    }
12177    while ((newms = ast_waitfor(chan, ms)) > 0) {
12178       f = ast_read(chan);
12179       if (!f) {
12180          /* Got hangup */
12181          break;
12182       }
12183       if (f->frametype == AST_FRAME_CONTROL) {
12184          switch (f->subclass) {
12185          case AST_CONTROL_ANSWER:
12186             /* Launch the PBX */
12187             ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
12188             ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
12189             chan->priority = 1;
12190             ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
12191             ast_pbx_run(chan);
12192             /* It's already hungup, return immediately */
12193             return NULL;
12194          case AST_CONTROL_BUSY:
12195             ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
12196             break;
12197          case AST_CONTROL_CONGESTION:
12198             ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
12199             break;
12200          };
12201       }
12202       ast_frfree(f);
12203       ms = newms;
12204    }
12205    /* Hangup the channel since nothing happend */
12206    ast_hangup(chan);
12207    return NULL;
12208 }

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

Definition at line 9496 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, ast_strlen_zero(), 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(), dahdi_pvt::fxsoffhookstate, handle_init_event(), has_voicemail(), iflist, iflock, last, mwi_thread_data::len, LOG_DEBUG, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::msgstate, mwi_send_init(), mwi_send_process_buffer(), mwi_send_process_event(), mwi_thread(), dahdi_pvt::mwimonitor_fsk, dahdi_pvt::mwimonitoractive, dahdi_pvt::mwisendactive, dahdi_pvt::next, dahdi_pvt::onhooktime, dahdi_subchannel::owner, dahdi_pvt::owner, dahdi_pvt::pri, mwi_thread_data::pvt, dahdi_pvt::radio, dahdi_pvt::sig, SIG_MFCR2, SUB_REAL, and dahdi_pvt::subs.

Referenced by restart_monitor().

09497 {
09498    int count, res, res2, spoint, pollres=0;
09499    struct dahdi_pvt *i;
09500    struct dahdi_pvt *last = NULL;
09501    struct dahdi_pvt *doomed;
09502    time_t thispass = 0, lastpass = 0;
09503    int found;
09504    char buf[1024];
09505    struct pollfd *pfds=NULL;
09506    int lastalloc = -1;
09507    /* This thread monitors all the frame relay interfaces which are not yet in use
09508       (and thus do not have a separate thread) indefinitely */
09509    /* From here on out, we die whenever asked */
09510 #if 0
09511    if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
09512       ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
09513       return NULL;
09514    }
09515    ast_debug(1, "Monitor starting...\n");
09516 #endif
09517    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09518 
09519    for (;;) {
09520       /* Lock the interface list */
09521       ast_mutex_lock(&iflock);
09522       if (!pfds || (lastalloc != ifcount)) {
09523          if (pfds) {
09524             ast_free(pfds);
09525             pfds = NULL;
09526          }
09527          if (ifcount) {
09528             if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
09529                ast_mutex_unlock(&iflock);
09530                return NULL;
09531             }
09532          }
09533          lastalloc = ifcount;
09534       }
09535       /* Build the stuff we're going to poll on, that is the socket of every
09536          dahdi_pvt that does not have an associated owner channel */
09537       count = 0;
09538       i = iflist;
09539       while (i) {
09540          if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio) && !(i->sig & SIG_MFCR2)) {
09541             if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
09542                /* This needs to be watched, as it lacks an owner */
09543                pfds[count].fd = i->subs[SUB_REAL].dfd;
09544                pfds[count].events = POLLPRI;
09545                pfds[count].revents = 0;
09546                /* If we are monitoring for VMWI or sending CID, we need to
09547                   read from the channel as well */
09548                if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
09549                   pfds[count].events |= POLLIN;
09550                count++;
09551             }
09552          }
09553          i = i->next;
09554       }
09555       /* Okay, now that we know what to do, release the interface lock */
09556       ast_mutex_unlock(&iflock);
09557 
09558       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
09559       pthread_testcancel();
09560       /* Wait at least a second for something to happen */
09561       res = poll(pfds, count, 1000);
09562       pthread_testcancel();
09563       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
09564 
09565       /* Okay, poll has finished.  Let's see what happened.  */
09566       if (res < 0) {
09567          if ((errno != EAGAIN) && (errno != EINTR))
09568             ast_log(LOG_WARNING, "poll return %d: %s\n", res, strerror(errno));
09569          continue;
09570       }
09571       /* Alright, lock the interface list again, and let's look and see what has
09572          happened */
09573       ast_mutex_lock(&iflock);
09574       found = 0;
09575       spoint = 0;
09576       lastpass = thispass;
09577       thispass = time(NULL);
09578       i = iflist;
09579       doomed = NULL;
09580       for (i = iflist;; i = i->next) {
09581          if (doomed) {
09582             int res;
09583             res = dahdi_destroy_channel_bynum(doomed->channel);
09584             if (!res) {
09585                ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
09586             }
09587             doomed = NULL;
09588          }
09589          if (!i) {
09590             break;
09591          }
09592 
09593          if (thispass != lastpass) {
09594             if (!found && ((i == last) || ((i == iflist) && !last))) {
09595                last = i;
09596                if (last) {
09597                   /* Only allow MWI to be initiated on a quiescent fxs port */
09598                   if (!last->mwisendactive &&   last->sig & __DAHDI_SIG_FXO &&
09599                         !last->fxsoffhookstate && !last->owner &&
09600                         !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3)) {
09601                      res = has_voicemail(last);
09602                      if (last->msgstate != res) {
09603                         /* Set driver resources for signalling VMWI */
09604                         res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, &res);
09605                         if (res2) {
09606                            /* TODO: This message will ALWAYS be generated on some cards; any way to restrict it to those cards where it is interesting? */
09607                            ast_debug(3, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
09608                         }
09609                         /* If enabled for FSK spill then initiate it */
09610                         if (mwi_send_init(last)) {
09611                            ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
09612                         }
09613                         last->msgstate = res;
09614                         found ++;
09615                      }
09616                   }
09617                   last = last->next;
09618                }
09619             }
09620          }
09621          if ((i->subs[SUB_REAL].dfd > -1) && i->sig) {
09622             if (i->radio && !i->owner)
09623             {
09624                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09625                if (res)
09626                {
09627                   ast_debug(1, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
09628                   /* Don't hold iflock while handling init events */
09629                   ast_mutex_unlock(&iflock);
09630                   doomed = handle_init_event(i, res);
09631                   ast_mutex_lock(&iflock);
09632                }
09633                continue;
09634             }
09635             pollres = ast_fdisset(pfds, i->subs[SUB_REAL].dfd, count, &spoint);
09636             if (pollres & POLLIN) {
09637                if (i->owner || i->subs[SUB_REAL].owner) {
09638 #ifdef HAVE_PRI
09639                   if (!i->pri)
09640 #endif
09641                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d) in read...\n", i->subs[SUB_REAL].dfd);
09642                   continue;
09643                }
09644                if (!i->mwimonitor_fsk && !i->mwisendactive) {
09645                   ast_log(LOG_WARNING, "Whoa....  I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
09646                   continue;
09647                }
09648                res = read(i->subs[SUB_REAL].dfd, buf, sizeof(buf));
09649                if (res > 0) {
09650                   if (i->mwimonitor_fsk) {
09651                      if (calc_energy((unsigned char *) buf, res, AST_LAW(i)) > mwilevel) {
09652                         pthread_attr_t attr;
09653                         pthread_t threadid;
09654                         struct mwi_thread_data *mtd;
09655 
09656                         pthread_attr_init(&attr);
09657                         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
09658 
09659                         ast_log(LOG_DEBUG, "Maybe some MWI on port %d!\n", i->channel);
09660                         if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
09661                            mtd->pvt = i;
09662                            memcpy(mtd->buf, buf, res);
09663                            mtd->len = res;
09664                            if (ast_pthread_create_background(&threadid, &attr, mwi_thread, mtd)) {
09665                               ast_log(LOG_WARNING, "Unable to start mwi thread on channel %d\n", i->channel);
09666                               ast_free(mtd);
09667                            }
09668                            i->mwimonitoractive = 1;
09669                         }
09670                      }
09671                   }
09672                   if (i->mwisendactive) {
09673                      mwi_send_process_buffer(i, res);
09674                   }
09675                } else {
09676                   ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
09677                }
09678             }
09679             if (pollres & POLLPRI) {
09680                if (i->owner || i->subs[SUB_REAL].owner) {
09681 #ifdef HAVE_PRI
09682                   if (!i->pri)
09683 #endif
09684                      ast_log(LOG_WARNING, "Whoa....  I'm owned but found (%d)...\n", i->subs[SUB_REAL].dfd);
09685                   continue;
09686                }
09687                res = dahdi_get_event(i->subs[SUB_REAL].dfd);
09688                ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
09689                /* Don't hold iflock while handling init events */
09690                ast_mutex_unlock(&iflock);
09691                if (0 == i->mwisendactive || 0 == mwi_send_process_event(i, res)) {
09692                   doomed = handle_init_event(i, res);
09693                }
09694                ast_mutex_lock(&iflock);
09695             }
09696          }
09697       }
09698       ast_mutex_unlock(&iflock);
09699    }
09700    /* Never reached */
09701    return NULL;
09702 
09703 }

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

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

10772 {
10773    struct dahdi_pvt *p;
10774    struct dahdi_bufferinfo bi;
10775    int res;
10776 
10777    if ((p = ast_malloc(sizeof(*p)))) {
10778       memcpy(p, src, sizeof(struct dahdi_pvt));
10779       ast_mutex_init(&p->lock);
10780       p->subs[SUB_REAL].dfd = dahdi_open("/dev/dahdi/pseudo");
10781       if (p->subs[SUB_REAL].dfd < 0) {
10782          ast_log(LOG_ERROR, "Unable to dup channel: %s\n", strerror(errno));
10783          destroy_dahdi_pvt(&p);
10784          return NULL;
10785       }
10786       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10787       if (!res) {
10788          bi.txbufpolicy = src->buf_policy;
10789          bi.rxbufpolicy = src->buf_policy;
10790          bi.numbufs = src->buf_no;
10791          res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10792          if (res < 0) {
10793             ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
10794          }
10795       } else
10796          ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
10797    }
10798    p->destroy = 1;
10799    p->next = iflist;
10800    p->prev = NULL;
10801    iflist = p;
10802    if (iflist->next)
10803       iflist->next->prev = p;
10804    return p;
10805 }

static void enable_dtmf_detect ( struct dahdi_pvt p  )  [static]

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

05139 {
05140    int val;
05141 
05142    if (p->channel == CHAN_PSEUDO)
05143       return;
05144 
05145    p->ignoredtmf = 0;
05146 
05147    val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
05148    ioctl(p->subs[SUB_REAL].dfd, DAHDI_TONEDETECT, &val);
05149 
05150    if (!p->hardwaredtmf && p->dsp) {
05151       p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
05152       ast_dsp_set_features(p->dsp, p->dsp_features);
05153    }
05154 }

static char* event2str ( int  event  )  [static]

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

02390 {
02391    static char buf[256];
02392    if ((event < (ARRAY_LEN(events))) && (event > -1))
02393       return events[event];
02394    sprintf(buf, "Event %d", event); /* safe */
02395    return buf;
02396 }

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

Definition at line 2761 of file chan_dahdi.c.

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

Referenced by set_actual_rxgain().

02762 {
02763    int j;
02764    int k;
02765    float linear_gain = pow(10.0, gain / 20.0);
02766 
02767    switch (law) {
02768    case DAHDI_LAW_ALAW:
02769       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02770          if (gain) {
02771             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02772             if (k > 32767) k = 32767;
02773             if (k < -32767) k = -32767;
02774             g->rxgain[j] = AST_LIN2A(k);
02775          } else {
02776             g->rxgain[j] = j;
02777          }
02778       }
02779       break;
02780    case DAHDI_LAW_MULAW:
02781       for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
02782          if (gain) {
02783             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02784             if (k > 32767) k = 32767;
02785             if (k < -32767) k = -32767;
02786             g->rxgain[j] = AST_LIN2MU(k);
02787          } else {
02788             g->rxgain[j] = j;
02789          }
02790       }
02791       break;
02792    }
02793 }

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

Definition at line 2727 of file chan_dahdi.c.

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

Referenced by set_actual_txgain().

02728 {
02729    int j;
02730    int k;
02731    float linear_gain = pow(10.0, gain / 20.0);
02732 
02733    switch (law) {
02734    case DAHDI_LAW_ALAW:
02735       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02736          if (gain) {
02737             k = (int) (((float) AST_ALAW(j)) * linear_gain);
02738             if (k > 32767) k = 32767;
02739             if (k < -32767) k = -32767;
02740             g->txgain[j] = AST_LIN2A(k);
02741          } else {
02742             g->txgain[j] = j;
02743          }
02744       }
02745       break;
02746    case DAHDI_LAW_MULAW:
02747       for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
02748          if (gain) {
02749             k = (int) (((float) AST_MULAW(j)) * linear_gain);
02750             if (k > 32767) k = 32767;
02751             if (k < -32767) k = -32767;
02752             g->txgain[j] = AST_LIN2MU(k);
02753          } else {
02754             g->txgain[j] = j;
02755          }
02756       }
02757       break;
02758    }
02759 }

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

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

15202 {
15203    struct dahdi_pvt *p = iflist;
15204    while (p) {
15205       if (p->channel == channel) {
15206          break;
15207       }
15208       p = p->next;
15209    }
15210    return p;
15211 }

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

05581 {
05582    int res;
05583    struct dahdi_spaninfo zi;
05584    struct dahdi_params params;
05585 
05586    memset(&zi, 0, sizeof(zi));
05587    zi.spanno = p->span;
05588 
05589    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SPANSTAT, &zi)) >= 0) {
05590       if (zi.alarms != DAHDI_ALARM_NONE)
05591          return zi.alarms;
05592    } else {
05593       ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
05594       return 0;
05595    }
05596 
05597    /* No alarms on the span. Check for channel alarms. */
05598    memset(&params, 0, sizeof(params));
05599    if ((res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &params)) >= 0)
05600       return params.chan_alarms;
05601 
05602    ast_log(LOG_WARNING, "Unable to determine alarm on channel %d\n", p->channel);
05603 
05604    return DAHDI_ALARM_NONE;
05605 }

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

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

05689 {
05690    const char *alarm_str = alarm2str(alms);
05691 
05692    ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
05693    manager_event(EVENT_FLAG_SYSTEM, "Alarm",
05694       "Alarm: %s\r\n"
05695       "Channel: %d\r\n",
05696       alarm_str, p->channel);
05697 }

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

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

14818 {
14819    int i, j;
14820    switch (cmd) {
14821    case CLI_INIT:
14822       e->command = "dahdi show cadences";
14823       e->usage =
14824          "Usage: dahdi show cadences\n"
14825          "       Shows all cadences currently defined\n";
14826       return NULL;
14827    case CLI_GENERATE:
14828       return NULL;
14829    }
14830    for (i = 0; i < num_cadence; i++) {
14831       char output[1024];
14832       char tmp[16], tmp2[64];
14833       snprintf(tmp, sizeof(tmp), "r%d: ", i + 1);
14834       term_color(output, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(output));
14835 
14836       for (j = 0; j < 16; j++) {
14837          if (cadences[i].ringcadence[j] == 0)
14838             break;
14839          snprintf(tmp, sizeof(tmp), "%d", cadences[i].ringcadence[j]);
14840          if (cidrings[i] * 2 - 1 == j)
14841             term_color(tmp2, tmp, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp2) - 1);
14842          else
14843             term_color(tmp2, tmp, COLOR_GREEN, COLOR_BLACK, sizeof(tmp2) - 1);
14844          if (j != 0)
14845             strncat(output, ",", sizeof(output) - strlen(output) - 1);
14846          strncat(output, tmp2, sizeof(output) - strlen(output) - 1);
14847       }
14848       ast_cli(a->fd,"%s\n",output);
14849    }
14850    return CLI_SUCCESS;
14851 }

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

Definition at line 9269 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, 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, dahdi_pvt::fxsoffhookstate, 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().

09270 {
09271    int res;
09272    pthread_t threadid;
09273    struct ast_channel *chan;
09274 
09275    /* Handle an event on a given channel for the monitor thread. */
09276 
09277    switch (event) {
09278    case DAHDI_EVENT_NONE:
09279    case DAHDI_EVENT_BITSCHANGED:
09280       break;
09281    case DAHDI_EVENT_WINKFLASH:
09282    case DAHDI_EVENT_RINGOFFHOOK:
09283       if (i->inalarm) break;
09284       if (i->radio) break;
09285       /* Got a ring/answer.  What kind of channel are we? */
09286       switch (i->sig) {
09287       case SIG_FXOLS:
09288       case SIG_FXOGS:
09289       case SIG_FXOKS:
09290          res = dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09291          i->fxsoffhookstate = 1;
09292          if (res && (errno == EBUSY))
09293             break;
09294          if (i->cidspill) {
09295             /* Cancel VMWI spill */
09296             ast_free(i->cidspill);
09297             i->cidspill = NULL;
09298          }
09299          if (i->immediate) {
09300             dahdi_enable_ec(i);
09301             /* The channel is immediately up.  Start right away */
09302             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_RINGTONE);
09303             chan = dahdi_new(i, AST_STATE_RING, 1, SUB_REAL, 0, 0);
09304             if (!chan) {
09305                ast_log(LOG_WARNING, "Unable to start PBX on channel %d\n", i->channel);
09306                res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09307                if (res < 0)
09308                   ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09309             }
09310          } else {
09311             /* Check for callerid, digits, etc */
09312             chan = dahdi_new(i, AST_STATE_RESERVED, 0, SUB_REAL, 0, 0);
09313             if (chan) {
09314                if (has_voicemail(i))
09315                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_STUTTER);
09316                else
09317                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_DIALTONE);
09318                if (res < 0)
09319                   ast_log(LOG_WARNING, "Unable to play dialtone on channel %d, do you have defaultzone and loadzone defined?\n", i->channel);
09320                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09321                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09322                   res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09323                   if (res < 0)
09324                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09325                   ast_hangup(chan);
09326                }
09327             } else
09328                ast_log(LOG_WARNING, "Unable to create channel\n");
09329          }
09330          break;
09331       case SIG_FXSLS:
09332       case SIG_FXSGS:
09333       case SIG_FXSKS:
09334             i->ringt = i->ringt_base;
09335             /* Fall through */
09336       case SIG_EMWINK:
09337       case SIG_FEATD:
09338       case SIG_FEATDMF:
09339       case SIG_FEATDMF_TA:
09340       case SIG_E911:
09341       case SIG_FGC_CAMA:
09342       case SIG_FGC_CAMAMF:
09343       case SIG_FEATB:
09344       case SIG_EM:
09345       case SIG_EM_E1:
09346       case SIG_SFWINK:
09347       case SIG_SF_FEATD:
09348       case SIG_SF_FEATDMF:
09349       case SIG_SF_FEATB:
09350       case SIG_SF:
09351          /* Check for callerid, digits, etc */
09352          if (i->cid_start == CID_START_POLARITY_IN) {
09353             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09354          } else {
09355             chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
09356          }
09357 
09358          if (!chan) {
09359             ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09360          } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09361             ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09362             res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09363             if (res < 0) {
09364                ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09365             }
09366             ast_hangup(chan);
09367          }
09368          break;
09369       default:
09370          ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09371          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
09372          if (res < 0)
09373             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
09374          return NULL;
09375       }
09376       break;
09377    case DAHDI_EVENT_NOALARM:
09378       i->inalarm = 0;
09379       ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", i->channel);
09380       manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
09381          "Channel: %d\r\n", i->channel);
09382       break;
09383    case DAHDI_EVENT_ALARM:
09384       i->inalarm = 1;
09385       res = get_alarms(i);
09386       handle_alarms(i, res);
09387       /* fall thru intentionally */
09388    case DAHDI_EVENT_ONHOOK:
09389       if (i->radio)
09390          break;
09391       /* Back on hook.  Hang up. */
09392       switch (i->sig) {
09393       case SIG_FXOLS:
09394       case SIG_FXOGS:
09395       case SIG_FEATD:
09396       case SIG_FEATDMF:
09397       case SIG_FEATDMF_TA:
09398       case SIG_E911:
09399       case SIG_FGC_CAMA:
09400       case SIG_FGC_CAMAMF:
09401       case SIG_FEATB:
09402       case SIG_EM:
09403       case SIG_EM_E1:
09404       case SIG_EMWINK:
09405       case SIG_SF_FEATD:
09406       case SIG_SF_FEATDMF:
09407       case SIG_SF_FEATB:
09408       case SIG_SF:
09409       case SIG_SFWINK:
09410       case SIG_FXSLS:
09411       case SIG_FXSGS:
09412       case SIG_FXSKS:
09413       case SIG_GR303FXSKS:
09414          dahdi_disable_ec(i);
09415          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09416          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09417          break;
09418       case SIG_GR303FXOKS:
09419       case SIG_FXOKS:
09420          dahdi_disable_ec(i);
09421          /* Diddle the battery for the zhone */
09422 #ifdef ZHONE_HACK
09423          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
09424          usleep(1);
09425 #endif
09426          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09427          dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
09428          break;
09429       case SIG_PRI:
09430       case SIG_SS7:
09431       case SIG_BRI:
09432       case SIG_BRI_PTMP:
09433          dahdi_disable_ec(i);
09434          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09435          break;
09436       default:
09437          ast_log(LOG_WARNING, "Don't know how to handle on hook with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
09438          res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
09439          return NULL;
09440       }
09441       if (i->sig & __DAHDI_SIG_FXO) {
09442          i->fxsoffhookstate = 0;
09443       }
09444       break;
09445    case DAHDI_EVENT_POLARITY:
09446       switch (i->sig) {
09447       case SIG_FXSLS:
09448       case SIG_FXSKS:
09449       case SIG_FXSGS:
09450          /* We have already got a PR before the channel was
09451             created, but it wasn't handled. We need polarity
09452             to be REV for remote hangup detection to work.
09453             At least in Spain */
09454          if (i->hanguponpolarityswitch)
09455             i->polarity = POLARITY_REV;
09456          if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
09457             i->polarity = POLARITY_REV;
09458             ast_verb(2, "Starting post polarity "
09459                "CID detection on channel %d\n",
09460                i->channel);
09461             chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
09462             if (!chan) {
09463                ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
09464             } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
09465                ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
09466             }
09467          }
09468          break;
09469       default:
09470          ast_log(LOG_WARNING, "handle_init_event detected "
09471             "polarity reversal on non-FXO (SIG_FXS) "
09472             "interface %d\n", i->channel);
09473       }
09474       break;
09475    case DAHDI_EVENT_REMOVED: /* destroy channel, will actually do so in do_monitor */
09476       ast_log(LOG_NOTICE,
09477             "Got DAHDI_EVENT_REMOVED. Destroying channel %d\n",
09478             i->channel);
09479       return i;
09480    case DAHDI_EVENT_NEONMWI_ACTIVE:
09481       if (i->mwimonitor_neon) {
09482          notify_message(i->mailbox, 1);
09483          ast_log(LOG_NOTICE, "NEON MWI set for channel %d, mailbox %s \n", i->channel, i->mailbox);
09484       }
09485       break;
09486    case DAHDI_EVENT_NEONMWI_INACTIVE:
09487       if (i->mwimonitor_neon) {
09488          notify_message(i->mailbox, 0);
09489          ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
09490       }
09491       break;
09492    }
09493    return NULL;
09494 }

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

Definition at line 13707 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, complete_span_4(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NUM_DCHANS, NUM_SPANS, ast_cli_args::pos, pridebugfdlock, pris, ast_cli_entry::usage, and ast_cli_args::word.

13708 {
13709    int span;
13710    int x;
13711    int level = 0;
13712    switch (cmd) {
13713    case CLI_INIT:
13714       e->command = "pri set debug {on|off|0|1|2} span";
13715       e->usage =
13716          "Usage: pri set debug {<level>|on|off} span <span>\n"
13717          "       Enables debugging on a given PRI span\n";
13718       return NULL;
13719    case CLI_GENERATE:
13720       return complete_span_4(a->line, a->word, a->pos, a->n);
13721    }
13722    if (a->argc < 6) {
13723       return CLI_SHOWUSAGE;
13724    }
13725 
13726    if (!strcasecmp(a->argv[3], "on")) {
13727       level = 1;
13728    } else if (!strcasecmp(a->argv[3], "off")) {
13729       level = 0;
13730    } else {
13731       level = atoi(a->argv[3]);
13732    }
13733    span = atoi(a->argv[5]);
13734    if ((span < 1) || (span > NUM_SPANS)) {
13735       ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
13736       return CLI_SUCCESS;
13737    }
13738    if (!pris[span-1].pri) {
13739       ast_cli(a->fd, "No PRI running on span %d\n", span);
13740       return CLI_SUCCESS;
13741    }
13742    for (x = 0; x < NUM_DCHANS; x++) {
13743       if (pris[span-1].dchans[x]) {
13744          if (level == 1) {
13745             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13746                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13747                PRI_DEBUG_Q921_STATE);
13748             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13749          } else if (level == 0) {
13750             pri_set_debug(pris[span-1].dchans[x], 0);
13751             //close the file if it's set
13752             ast_mutex_lock(&pridebugfdlock);
13753             close(pridebugfd);
13754             pridebugfd = -1;
13755             ast_cli(a->fd, "PRI debug output to file disabled\n");
13756             ast_mutex_unlock(&pridebugfdlock);
13757          } else {
13758             pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
13759                PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
13760                PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
13761             ast_cli(a->fd, "Enabled debugging on span %d\n", span);
13762          }
13763       }
13764    }
13765    return CLI_SUCCESS;
13766 }

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

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

13670 {
13671    int myfd;
13672    switch (cmd) {
13673    case CLI_INIT:
13674       e->command = "pri set debug file";
13675       e->usage = "Usage: pri set debug file [output-file]\n"
13676          "       Sends PRI debug output to the specified output file\n";
13677       return NULL;
13678    case CLI_GENERATE:
13679       return NULL;
13680    }
13681    if (a->argc < 5)
13682       return CLI_SHOWUSAGE;
13683 
13684    if (ast_strlen_zero(a->argv[4]))
13685       return CLI_SHOWUSAGE;
13686 
13687    myfd = open(a->argv[4], O_CREAT|O_WRONLY, AST_FILE_MODE);
13688    if (myfd < 0) {
13689       ast_cli(a->fd, "Unable to open '%s' for writing\n", a->argv[4]);
13690       return CLI_SUCCESS;
13691    }
13692 
13693    ast_mutex_lock(&pridebugfdlock);
13694 
13695    if (pridebugfd >= 0)
13696       close(pridebugfd);
13697 
13698    pridebugfd = myfd;
13699    ast_copy_string(pridebugfilename,a->argv[4],sizeof(pridebugfilename));
13700    ast_mutex_unlock(&pridebugfdlock);
13701    ast_cli(a->fd, "PRI debug output will be sent to '%s'\n", a->argv[4]);
13702    return CLI_SUCCESS;
13703 }

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

Definition at line 13880 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_DCHANS, NUM_SPANS, pridebugfdlock, pris, and ast_cli_entry::usage.

13881 {
13882    int x;
13883    int span;
13884    int count=0;
13885    int debug=0;
13886 
13887    switch (cmd) {
13888    case CLI_INIT:
13889       e->command = "pri show debug";
13890       e->usage =
13891          "Usage: pri show debug\n"
13892          "  Show the debug state of pri spans\n";
13893       return NULL;
13894    case CLI_GENERATE:
13895       return NULL;
13896    }
13897 
13898    for (span = 0; span < NUM_SPANS; span++) {
13899       if (pris[span].pri) {
13900          for (x = 0; x < NUM_DCHANS; x++) {
13901             debug = 0;
13902             if (pris[span].dchans[x]) {
13903                debug = pri_get_debug(pris[span].dchans[x]);
13904                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" );
13905                count++;
13906             }
13907          }
13908       }
13909 
13910    }
13911    ast_mutex_lock(&pridebugfdlock);
13912    if (pridebugfd >= 0)
13913       ast_cli(a->fd, "Logging PRI debug to file %s\n", pridebugfilename);
13914    ast_mutex_unlock(&pridebugfdlock);
13915 
13916    if (!count)
13917       ast_cli(a->fd, "No debug set or no PRI running\n");
13918    return CLI_SUCCESS;
13919 }

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

Definition at line 13828 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_DCHANS, NUM_SPANS, dahdi_pri::overlapdial, ast_cli_args::pos, pri_order(), pris, status, ast_cli_entry::usage, and ast_cli_args::word.

13829 {
13830    int span;
13831    int x;
13832    char status[256];
13833    switch (cmd) {
13834    case CLI_INIT:
13835       e->command = "pri show span";
13836       e->usage =
13837          "Usage: pri show span <span>\n"
13838          "       Displays PRI Information on a given PRI span\n";
13839       return NULL;
13840    case CLI_GENERATE:
13841       return complete_span_4(a->line, a->word, a->pos, a->n);
13842    }
13843 
13844    if (a->argc < 4)
13845       return CLI_SHOWUSAGE;
13846    span = atoi(a->argv[3]);
13847    if ((span < 1) || (span > NUM_SPANS)) {
13848       ast_cli(a->fd, "Invalid span '%s'.  Should be a number from %d to %d\n", a->argv[3], 1, NUM_SPANS);
13849       return CLI_SUCCESS;
13850    }
13851    if (!pris[span-1].pri) {
13852       ast_cli(a->fd, "No PRI running on span %d\n", span);
13853       return CLI_SUCCESS;
13854    }
13855    for (x = 0; x < NUM_DCHANS; x++) {
13856       if (pris[span-1].dchannels[x]) {
13857 #ifdef PRI_DUMP_INFO_STR
13858          char *info_str = NULL;
13859 #endif
13860          ast_cli(a->fd, "%s D-channel: %d\n", pri_order(x), pris[span-1].dchannels[x]);
13861          build_status(status, sizeof(status), pris[span-1].dchanavail[x], pris[span-1].dchans[x] == pris[span-1].pri);
13862          ast_cli(a->fd, "Status: %s\n", status);
13863 #ifdef PRI_DUMP_INFO_STR
13864          info_str = pri_dump_info_str(pris[span-1].pri);
13865          if (info_str) {
13866             ast_cli(a->fd, "%s", info_str);
13867             ast_free(info_str);
13868          }
13869 #else
13870          pri_dump_info(pris[span-1].pri);
13871 #endif
13872          ast_cli(a->fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & DAHDI_OVERLAPDIAL_INCOMING)?"Yes":"No");
13873       }
13874    }
13875    return CLI_SUCCESS;
13876 }

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

Definition at line 13793 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_DCHANS, NUM_SPANS, pris, status, and ast_cli_entry::usage.

13794 {
13795    int span;
13796    int x;
13797    char status[256];
13798 
13799    switch (cmd) {
13800    case CLI_INIT:
13801       e->command = "pri show spans";
13802       e->usage =
13803          "Usage: pri show spans\n"
13804          "       Displays PRI Information\n";
13805       return NULL;
13806    case CLI_GENERATE:
13807       return NULL;
13808    }
13809 
13810    if (a->argc != 3)
13811       return CLI_SHOWUSAGE;
13812 
13813    for (span = 0; span < NUM_SPANS; span++) {
13814       if (pris[span].pri) {
13815          for (x = 0; x < NUM_DCHANS; x++) {
13816             if (pris[span].dchannels[x]) {
13817                build_status(status, sizeof(status), pris[span].dchanavail[x], pris[span].dchans[x] == pris[span].pri);
13818                ast_cli(a->fd, "PRI span %d/%d: %s\n", span + 1, x, status);
13819             }
13820          }
13821       }
13822    }
13823    return CLI_SUCCESS;
13824 }

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

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

13924 {
13925    switch (cmd) {
13926    case CLI_INIT:
13927       e->command = "pri show version";
13928       e->usage =
13929          "Usage: pri show version\n"
13930          "Show libpri version information\n";
13931       return NULL;
13932    case CLI_GENERATE:
13933       return NULL;
13934    }
13935 
13936    ast_cli(a->fd, "libpri version: %s\n", pri_get_version());
13937 
13938    return CLI_SUCCESS;
13939 }

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

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

15570 {
15571    int linkset, cic;
15572    int blocked = -1, i;
15573    switch (cmd) {
15574    case CLI_INIT:
15575       e->command = "ss7 block cic";
15576       e->usage =
15577          "Usage: ss7 block cic <linkset> <CIC>\n"
15578          "       Sends a remote blocking request for the given CIC on the specified linkset\n";
15579       return NULL;
15580    case CLI_GENERATE:
15581       return NULL;
15582    }
15583    if (a->argc == 5)
15584       linkset = atoi(a->argv[3]);
15585    else
15586       return CLI_SHOWUSAGE;
15587 
15588    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15589       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15590       return CLI_SUCCESS;
15591    }
15592 
15593    if (!linksets[linkset-1].ss7) {
15594       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15595       return CLI_SUCCESS;
15596    }
15597 
15598    cic = atoi(a->argv[4]);
15599 
15600    if (cic < 1) {
15601       ast_cli(a->fd, "Invalid CIC specified!\n");
15602       return CLI_SUCCESS;
15603    }
15604 
15605    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15606       if (linksets[linkset-1].pvts[i]->cic == cic) {
15607          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15608          if (!blocked) {
15609             ast_mutex_lock(&linksets[linkset-1].lock);
15610             isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15611             ast_mutex_unlock(&linksets[linkset-1].lock);
15612          }
15613       }
15614    }
15615 
15616    if (blocked < 0) {
15617       ast_cli(a->fd, "Invalid CIC specified!\n");
15618       return CLI_SUCCESS;
15619    }
15620 
15621    if (!blocked)
15622       ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
15623    else
15624       ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
15625 
15626    /* Break poll on the linkset so it sends our messages */
15627    pthread_kill(linksets[linkset-1].master, SIGURG);
15628 
15629    return CLI_SUCCESS;
15630 }

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

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

15635 {
15636    int linkset;
15637    int i;
15638    switch (cmd) {
15639    case CLI_INIT:
15640       e->command = "ss7 block linkset";
15641       e->usage =
15642          "Usage: ss7 block linkset <linkset number>\n"
15643          "       Sends a remote blocking request for all CICs on the given linkset\n";
15644       return NULL;
15645    case CLI_GENERATE:
15646       return NULL;
15647    }
15648    if (a->argc == 4)
15649       linkset = atoi(a->argv[3]);
15650    else
15651       return CLI_SHOWUSAGE;
15652 
15653    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15654       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15655       return CLI_SUCCESS;
15656    }
15657 
15658    if (!linksets[linkset-1].ss7) {
15659       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15660       return CLI_SUCCESS;
15661    }
15662 
15663    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15664       ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15665       ast_mutex_lock(&linksets[linkset-1].lock);
15666       isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15667       ast_mutex_unlock(&linksets[linkset-1].lock);
15668    }
15669 
15670    /* Break poll on the linkset so it sends our messages */
15671    pthread_kill(linksets[linkset-1].master, SIGURG);
15672 
15673    return CLI_SUCCESS;
15674 }

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

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

15531 {
15532    int span;
15533    switch (cmd) {
15534    case CLI_INIT:
15535       e->command = "ss7 set debug {on|off} linkset";
15536       e->usage =
15537          "Usage: ss7 set debug {on|off} linkset <linkset>\n"
15538          "       Enables debugging on a given SS7 linkset\n";
15539       return NULL;
15540    case CLI_GENERATE:
15541       return NULL;
15542    }
15543    if (a->argc < 6)
15544       return CLI_SHOWUSAGE;
15545    span = atoi(a->argv[5]);
15546    if ((span < 1) || (span > NUM_SPANS)) {
15547       ast_cli(a->fd, "Invalid linkset %s.  Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
15548       return CLI_SUCCESS;
15549    }
15550    if (!linksets[span-1].ss7) {
15551       ast_cli(a->fd, "No SS7 running on linkset %d\n", span);
15552       return CLI_SUCCESS;
15553    }
15554    if (linksets[span-1].ss7) {
15555       if (strcasecmp(a->argv[3], "on")) {
15556          ss7_set_debug(linksets[span-1].ss7, SS7_DEBUG_MTP2 | SS7_DEBUG_MTP3 | SS7_DEBUG_ISUP);
15557          ast_cli(a->fd, "Enabled debugging on linkset %d\n", span);
15558       } else {
15559          ss7_set_debug(linksets[span-1].ss7, 0);
15560          ast_cli(a->fd, "Disabled debugging on linkset %d\n", span);
15561       }
15562    }
15563 
15564    return CLI_SUCCESS;
15565 }

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

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

15783 {
15784    int linkset;
15785    struct dahdi_ss7 *ss7;
15786    switch (cmd) {
15787    case CLI_INIT:
15788       e->command = "ss7 show linkset";
15789       e->usage =
15790          "Usage: ss7 show linkset <span>\n"
15791          "       Shows the status of an SS7 linkset.\n";
15792       return NULL;
15793    case CLI_GENERATE:
15794       return NULL;
15795    }
15796 
15797    if (a->argc < 4)
15798       return CLI_SHOWUSAGE;
15799    linkset = atoi(a->argv[3]);
15800    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15801       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15802       return CLI_SUCCESS;
15803    }
15804    if (!linksets[linkset-1].ss7) {
15805       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15806       return CLI_SUCCESS;
15807    }
15808    if (linksets[linkset-1].ss7)
15809       ss7 = &linksets[linkset-1];
15810 
15811    ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
15812 
15813    return CLI_SUCCESS;
15814 }

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

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

15679 {
15680    int linkset, cic;
15681    int i, blocked = -1;
15682    switch (cmd) {
15683    case CLI_INIT:
15684       e->command = "ss7 unblock cic";
15685       e->usage =
15686          "Usage: ss7 unblock cic <linkset> <CIC>\n"
15687          "       Sends a remote unblocking request for the given CIC on the specified linkset\n";
15688       return NULL;
15689    case CLI_GENERATE:
15690       return NULL;
15691    }
15692 
15693    if (a->argc == 5)
15694       linkset = atoi(a->argv[3]);
15695    else
15696       return CLI_SHOWUSAGE;
15697 
15698    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15699       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15700       return CLI_SUCCESS;
15701    }
15702 
15703    if (!linksets[linkset-1].ss7) {
15704       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15705       return CLI_SUCCESS;
15706    }
15707 
15708    cic = atoi(a->argv[4]);
15709 
15710    if (cic < 1) {
15711       ast_cli(a->fd, "Invalid CIC specified!\n");
15712       return CLI_SUCCESS;
15713    }
15714 
15715    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15716       if (linksets[linkset-1].pvts[i]->cic == cic) {
15717          blocked = linksets[linkset-1].pvts[i]->locallyblocked;
15718          if (blocked) {
15719             ast_mutex_lock(&linksets[linkset-1].lock);
15720             isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
15721             ast_mutex_unlock(&linksets[linkset-1].lock);
15722          }
15723       }
15724    }
15725 
15726    if (blocked > 0)
15727       ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
15728 
15729    /* Break poll on the linkset so it sends our messages */
15730    pthread_kill(linksets[linkset-1].master, SIGURG);
15731 
15732    return CLI_SUCCESS;
15733 }

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

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

15738 {
15739    int linkset;
15740    int i;
15741    switch (cmd) {
15742    case CLI_INIT:
15743       e->command = "ss7 unblock linkset";
15744       e->usage =
15745          "Usage: ss7 unblock linkset <linkset number>\n"
15746          "       Sends a remote unblocking request for all CICs on the specified linkset\n";
15747       return NULL;
15748    case CLI_GENERATE:
15749       return NULL;
15750    }
15751 
15752    if (a->argc == 4)
15753       linkset = atoi(a->argv[3]);
15754    else
15755       return CLI_SHOWUSAGE;
15756 
15757    if ((linkset < 1) || (linkset > NUM_SPANS)) {
15758       ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
15759       return CLI_SUCCESS;
15760    }
15761 
15762    if (!linksets[linkset-1].ss7) {
15763       ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
15764       return CLI_SUCCESS;
15765    }
15766 
15767    for (i = 0; i < linksets[linkset-1].numchans; i++) {
15768       ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
15769       ast_mutex_lock(&linksets[linkset-1].lock);
15770       isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
15771       ast_mutex_unlock(&linksets[linkset-1].lock);
15772    }
15773 
15774    /* Break poll on the linkset so it sends our messages */
15775    pthread_kill(linksets[linkset-1].master, SIGURG);
15776 
15777    return CLI_SUCCESS;
15778 }

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

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

15819 {
15820    switch (cmd) {
15821    case CLI_INIT:
15822       e->command = "ss7 show version";
15823       e->usage =
15824          "Usage: ss7 show version\n"
15825          "  Show the libss7 version\n";
15826       return NULL;
15827    case CLI_GENERATE:
15828       return NULL;
15829    }
15830 
15831    ast_cli(a->fd, "libss7 version: %s\n", ss7_get_version());
15832 
15833    return CLI_SUCCESS;
15834 }

static int has_voicemail ( struct dahdi_pvt p  )  [static]

Definition at line 3001 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_strlen_zero(), context, dahdi_pvt::mailbox, and mailbox.

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

03002 {
03003    int new_msgs;
03004    struct ast_event *event;
03005    char *mailbox, *context;
03006 
03007    mailbox = context = ast_strdupa(p->mailbox);
03008    strsep(&context, "@");
03009    if (ast_strlen_zero(context))
03010       context = "default";
03011 
03012    event = ast_event_get_cached(AST_EVENT_MWI,
03013       AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
03014       AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
03015       AST_EVENT_IE_END);
03016 
03017    if (event) {
03018       new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
03019       ast_event_destroy(event);
03020    } else
03021       new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
03022 
03023    return new_msgs;
03024 }

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

Definition at line 2516 of file chan_dahdi.c.

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

Referenced by conf_del().

02517 {
02518    /* If they're listening to our channel, they're ours */
02519    if ((p->channel == c->curconf.confno) && (c->curconf.confmode == DAHDI_CONF_DIGITALMON))
02520       return 1;
02521    /* If they're a talker on our (allocated) conference, they're ours */
02522    if ((p->confno > 0) && (p->confno == c->curconf.confno) && (c->curconf.confmode & DAHDI_CONF_TALKER))
02523       return 1;
02524    return 0;
02525 }

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

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

02547 {
02548    int x;
02549    int useslavenative;
02550    struct dahdi_pvt *slave = NULL;
02551    /* Start out optimistic */
02552    useslavenative = 1;
02553    /* Update conference state in a stateless fashion */
02554    for (x = 0; x < 3; x++) {
02555       /* Any three-way calling makes slave native mode *definitely* out
02556          of the question */
02557       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway)
02558          useslavenative = 0;
02559    }
02560    /* If we don't have any 3-way calls, check to see if we have
02561       precisely one slave */
02562    if (useslavenative) {
02563       for (x = 0; x < MAX_SLAVES; x++) {
02564          if (p->slaves[x]) {
02565             if (slave) {
02566                /* Whoops already have a slave!  No
02567                   slave native and stop right away */
02568                slave = NULL;
02569                useslavenative = 0;
02570                break;
02571             } else {
02572                /* We have one slave so far */
02573                slave = p->slaves[x];
02574             }
02575          }
02576       }
02577    }
02578    /* If no slave, slave native definitely out */
02579    if (!slave)
02580       useslavenative = 0;
02581    else if (slave->law != p->law) {
02582       useslavenative = 0;
02583       slave = NULL;
02584    }
02585    if (out)
02586       *out = slave;
02587    return useslavenative;
02588 }

static int linkset_addsigchan ( int  sigchan  )  [static]

Definition at line 15407 of file chan_dahdi.c.

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

Referenced by process_dahdi().

15408 {
15409    struct dahdi_ss7 *link;
15410    int res;
15411    int curfd;
15412    struct dahdi_params p;
15413    struct dahdi_bufferinfo bi;
15414    struct dahdi_spaninfo si;
15415 
15416 
15417    link = ss7_resolve_linkset(cur_linkset);
15418    if (!link) {
15419       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
15420       return -1;
15421    }
15422 
15423    if (cur_ss7type < 0) {
15424       ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
15425       return -1;
15426    }
15427 
15428    if (!link->ss7)
15429       link->ss7 = ss7_new(cur_ss7type);
15430 
15431    if (!link->ss7) {
15432       ast_log(LOG_ERROR, "Can't create new SS7!\n");
15433       return -1;
15434    }
15435 
15436    link->type = cur_ss7type;
15437 
15438    if (cur_pointcode < 0) {
15439       ast_log(LOG_ERROR, "Unspecified pointcode!\n");
15440       return -1;
15441    } else
15442       ss7_set_pc(link->ss7, cur_pointcode);
15443 
15444    if (sigchan < 0) {
15445       ast_log(LOG_ERROR, "Invalid sigchan!\n");
15446       return -1;
15447    } else {
15448       if (link->numsigchans >= NUM_DCHANS) {
15449          ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
15450          return -1;
15451       }
15452       curfd = link->numsigchans;
15453 
15454       link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
15455       if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
15456          ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
15457          return -1;
15458       }
15459       memset(&p, 0, sizeof(p));
15460       res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
15461       if (res) {
15462          dahdi_close_ss7_fd(link, curfd);
15463          ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
15464          return -1;
15465       }
15466       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
15467          dahdi_close_ss7_fd(link, curfd);
15468          ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
15469          return -1;
15470       }
15471 
15472       memset(&bi, 0, sizeof(bi));
15473       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
15474       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
15475       bi.numbufs = 32;
15476       bi.bufsize = 512;
15477 
15478       if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
15479          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
15480          dahdi_close_ss7_fd(link, curfd);
15481          return -1;
15482       }
15483 
15484       if (p.sigtype == DAHDI_SIG_MTP2)
15485          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
15486       else
15487          ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
15488 
15489       link->numsigchans++;
15490 
15491       memset(&si, 0, sizeof(si));
15492       res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
15493       if (res) {
15494          dahdi_close_ss7_fd(link, curfd);
15495          ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
15496       }
15497 
15498       if (!si.alarms) {
15499          link->linkstate[curfd] = LINKSTATE_DOWN;
15500          ss7_link_noalarm(link->ss7, link->fds[curfd]);
15501       } else {
15502          link->linkstate[curfd] = LINKSTATE_DOWN | LINKSTATE_INALARM;
15503          ss7_link_alarm(link->ss7, link->fds[curfd]);
15504       }
15505    }
15506 
15507    if (cur_adjpointcode < 0) {
15508       ast_log(LOG_ERROR, "Unspecified adjpointcode!\n");
15509       return -1;
15510    } else {
15511       ss7_set_adjpc(link->ss7, link->fds[curfd], cur_adjpointcode);
15512    }
15513 
15514    if (cur_defaultdpc < 0) {
15515       ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
15516       return -1;
15517    }
15518 
15519    if (cur_networkindicator < 0) {
15520       ast_log(LOG_ERROR, "Invalid networkindicator!\n");
15521       return -1;
15522    } else
15523       ss7_set_network_ind(link->ss7, cur_networkindicator);
15524 
15525    return 0;
15526 }

static int load_module ( void   )  [static]

Definition at line 17308 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_xml, 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_DCHANS, NUM_SPANS, dahdi_pri::offset, pris, and setup_dahdi().

17309 {
17310    int res;
17311 #if defined(HAVE_PRI) || defined(HAVE_SS7)
17312    int y, i;
17313 #endif
17314 
17315 #ifdef HAVE_PRI
17316    memset(pris, 0, sizeof(pris));
17317    for (y = 0; y < NUM_SPANS; y++) {
17318       ast_mutex_init(&pris[y].lock);
17319       pris[y].offset = -1;
17320       pris[y].master = AST_PTHREADT_NULL;
17321       for (i = 0; i < NUM_DCHANS; i++)
17322          pris[y].fds[i] = -1;
17323    }
17324    pri_set_error(dahdi_pri_error);
17325    pri_set_message(dahdi_pri_message);
17326    ast_register_application_xml(dahdi_send_keypad_facility_app, dahdi_send_keypad_facility_exec);
17327 #ifdef HAVE_PRI_PROG_W_CAUSE
17328    ast_register_application_xml(dahdi_send_callrerouting_facility_app, dahdi_send_callrerouting_facility_exec);
17329 #endif
17330 #endif
17331 #ifdef HAVE_SS7
17332    memset(linksets, 0, sizeof(linksets));
17333    for (y = 0; y < NUM_SPANS; y++) {
17334       ast_mutex_init(&linksets[y].lock);
17335       linksets[y].master = AST_PTHREADT_NULL;
17336       for (i = 0; i < NUM_DCHANS; i++)
17337          linksets[y].fds[i] = -1;
17338    }
17339    ss7_set_error(dahdi_ss7_error);
17340    ss7_set_message(dahdi_ss7_message);
17341 #endif /* HAVE_SS7 */
17342    res = setup_dahdi(0);
17343    /* Make sure we can register our DAHDI channel type */
17344    if (res)
17345       return AST_MODULE_LOAD_DECLINE;
17346    if (ast_channel_register(&dahdi_tech)) {
17347       ast_log(LOG_ERROR, "Unable to register channel class 'DAHDI'\n");
17348       __unload_module();
17349       return AST_MODULE_LOAD_FAILURE;
17350    }
17351 #ifdef HAVE_PRI
17352    ast_string_field_init(&inuse, 16);
17353    ast_string_field_set(&inuse, name, "GR-303InUse");
17354    ast_cli_register_multiple(dahdi_pri_cli, ARRAY_LEN(dahdi_pri_cli));
17355 #endif
17356 #ifdef HAVE_SS7
17357    ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
17358 #endif
17359 #ifdef HAVE_OPENR2
17360    ast_cli_register_multiple(dahdi_mfcr2_cli, sizeof(dahdi_mfcr2_cli)/sizeof(dahdi_mfcr2_cli[0]));
17361    ast_register_application_xml(dahdi_accept_r2_call_app, dahdi_accept_r2_call_exec);
17362 #endif
17363 
17364    ast_cli_register_multiple(dahdi_cli, ARRAY_LEN(dahdi_cli));
17365 
17366    memset(round_robin, 0, sizeof(round_robin));
17367    ast_manager_register( "DAHDITransfer", 0, action_transfer, "Transfer DAHDI Channel" );
17368    ast_manager_register( "DAHDIHangup", 0, action_transferhangup, "Hangup DAHDI Channel" );
17369    ast_manager_register( "DAHDIDialOffhook", 0, action_dahdidialoffhook, "Dial over DAHDI channel while offhook" );
17370    ast_manager_register( "DAHDIDNDon", 0, action_dahdidndon, "Toggle DAHDI channel Do Not Disturb status ON" );
17371    ast_manager_register( "DAHDIDNDoff", 0, action_dahdidndoff, "Toggle DAHDI channel Do Not Disturb status OFF" );
17372    ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
17373    ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
17374 
17375    ast_cond_init(&ss_thread_complete, NULL);
17376 
17377    return res;
17378 }

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

Definition at line 9990 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_strlen_zero(), ast_variable_new(), dahdi_pvt::buf_no, dahdi_pvt::buf_policy, dahdi_pvt::bufsize, 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_pri::discardremoteholdretrieval, dahdi_pvt::dpc, dahdi_pvt::drings, dahdi_pvt::dsp, DSP_DIGITMODE_DTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echocancel, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, ast_variable::file, dahdi_pvt::firstradio, free, dahdi_pvt::fxsoffhookstate, 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_pri::qsigchannelmapping, 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_MFCR2, 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, 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, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by build_channels(), and process_dahdi().

09991 {
09992    /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
09993    struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
09994    char fn[80];
09995    struct dahdi_bufferinfo bi;
09996 
09997    int res;
09998    int span = 0;
09999    int here = 0;
10000    int x;
10001    struct dahdi_pvt **wlist;
10002    struct dahdi_pvt **wend;
10003    struct dahdi_params p;
10004 
10005    wlist = &iflist;
10006    wend = &ifend;
10007 
10008 #ifdef HAVE_PRI
10009    if (pri) {
10010       wlist = &pri->crvs;
10011       wend = &pri->crvend;
10012    }
10013 #endif
10014 
10015    tmp2 = *wlist;
10016    prev = NULL;
10017 
10018    while (tmp2) {
10019       if (!tmp2->destroy) {
10020          if (tmp2->channel == channel) {
10021             tmp = tmp2;
10022             here = 1;
10023             break;
10024          }
10025          if (tmp2->channel > channel) {
10026             break;
10027          }
10028       }
10029       prev = tmp2;
10030       tmp2 = tmp2->next;
10031    }
10032 
10033    if (!here && reloading != 1) {
10034       if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
10035          if (tmp)
10036             free(tmp);
10037          return NULL;
10038       }
10039       ast_mutex_init(&tmp->lock);
10040       ifcount++;
10041       for (x = 0; x < 3; x++)
10042          tmp->subs[x].dfd = -1;
10043       tmp->channel = channel;
10044       tmp->priindication_oob = conf->chan.priindication_oob;
10045    }
10046 
10047    if (tmp) {
10048       int chan_sig = conf->chan.sig;
10049       if (!here) {
10050          if ((channel != CHAN_PSEUDO) && !pri) {
10051             int count = 0;
10052             snprintf(fn, sizeof(fn), "%d", channel);
10053             /* Open non-blocking */
10054             tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10055             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 */
10056                usleep(1);
10057                tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
10058                count++;
10059             }
10060             /* Allocate a DAHDI structure */
10061             if (tmp->subs[SUB_REAL].dfd < 0) {
10062                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);
10063                destroy_dahdi_pvt(&tmp);
10064                return NULL;
10065             }
10066             memset(&p, 0, sizeof(p));
10067             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10068             if (res < 0) {
10069                ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
10070                destroy_dahdi_pvt(&tmp);
10071                return NULL;
10072             }
10073             if (conf->is_sig_auto)
10074                chan_sig = sigtype_to_signalling(p.sigtype);
10075             if (p.sigtype != (chan_sig & 0x3ffff)) {
10076                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));
10077                destroy_dahdi_pvt(&tmp);
10078                return NULL;
10079             }
10080             tmp->law = p.curlaw;
10081             tmp->span = p.spanno;
10082             span = p.spanno - 1;
10083          } else {
10084             if (channel == CHAN_PSEUDO)
10085                chan_sig = 0;
10086             else if ((chan_sig != SIG_FXOKS) && (chan_sig != SIG_FXSKS)) {
10087                ast_log(LOG_ERROR, "CRV's must use FXO/FXS Kewl Start (fxo_ks/fxs_ks) signalling only.\n");
10088                return NULL;
10089             }
10090          }
10091 #ifdef HAVE_SS7
10092          if (chan_sig == SIG_SS7) {
10093             struct dahdi_ss7 *ss7;
10094             int clear = 0;
10095             if (ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &clear)) {
10096                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10097                destroy_dahdi_pvt(&tmp);
10098                return NULL;
10099             }
10100 
10101             ss7 = ss7_resolve_linkset(cur_linkset);
10102             if (!ss7) {
10103                ast_log(LOG_ERROR, "Unable to find linkset %d\n", cur_linkset);
10104                destroy_dahdi_pvt(&tmp);
10105                return NULL;
10106             }
10107             if (cur_cicbeginswith < 0) {
10108                ast_log(LOG_ERROR, "Need to set cicbeginswith for the channels!\n");
10109                destroy_dahdi_pvt(&tmp);
10110                return NULL;
10111             }
10112 
10113             tmp->cic = cur_cicbeginswith++;
10114 
10115             /* DB: Add CIC's DPC information */
10116             tmp->dpc = cur_defaultdpc;
10117 
10118             tmp->ss7 = ss7;
10119             tmp->ss7call = NULL;
10120             ss7->pvts[ss7->numchans++] = tmp;
10121 
10122             ast_copy_string(ss7->internationalprefix, conf->ss7.internationalprefix, sizeof(ss7->internationalprefix));
10123             ast_copy_string(ss7->nationalprefix, conf->ss7.nationalprefix, sizeof(ss7->nationalprefix));
10124             ast_copy_string(ss7->subscriberprefix, conf->ss7.subscriberprefix, sizeof(ss7->subscriberprefix));
10125             ast_copy_string(ss7->unknownprefix, conf->ss7.unknownprefix, sizeof(ss7->unknownprefix));
10126 
10127             ss7->called_nai = conf->ss7.called_nai;
10128             ss7->calling_nai = conf->ss7.calling_nai;
10129          }
10130 #endif
10131 #ifdef HAVE_OPENR2
10132          if (chan_sig == SIG_MFCR2 && reloading != 1) {
10133             struct dahdi_mfcr2 *r2_link;
10134             r2_link = dahdi_r2_get_link();
10135             if (!r2_link) {
10136                ast_log(LOG_WARNING, "Cannot get another R2 DAHDI context!\n");
10137                destroy_dahdi_pvt(&tmp);
10138                return NULL;
10139             }
10140             if (!r2_link->protocol_context && dahdi_r2_set_context(r2_link, conf)) {
10141                ast_log(LOG_ERROR, "Cannot create OpenR2 protocol context.\n");
10142                destroy_dahdi_pvt(&tmp);
10143                return NULL;
10144             }
10145             if (r2_link->numchans == (sizeof(r2_link->pvts)/sizeof(r2_link->pvts[0]))) {
10146                ast_log(LOG_ERROR, "Cannot add more channels to this link!\n");
10147                destroy_dahdi_pvt(&tmp);
10148                return NULL;
10149             }
10150             r2_link->pvts[r2_link->numchans++] = tmp;
10151             tmp->r2chan = openr2_chan_new_from_fd(r2_link->protocol_context,
10152                                         tmp->subs[SUB_REAL].dfd,
10153                                         NULL, NULL);
10154             if (!tmp->r2chan) {
10155                openr2_liberr_t err = openr2_context_get_last_error(r2_link->protocol_context);
10156                ast_log(LOG_ERROR, "Cannot create OpenR2 channel: %s\n", openr2_context_error_string(err));
10157                destroy_dahdi_pvt(&tmp);
10158                return NULL;
10159             }
10160             tmp->mfcr2 = r2_link;
10161             if (conf->mfcr2.call_files) {
10162                openr2_chan_enable_call_files(tmp->r2chan);
10163             }
10164             openr2_chan_set_client_data(tmp->r2chan, tmp);
10165             /* cast seems to be needed to get rid of the annoying warning regarding format attribute  */
10166             openr2_chan_set_logging_func(tmp->r2chan, (openr2_logging_func_t)dahdi_r2_on_chan_log);
10167             openr2_chan_set_log_level(tmp->r2chan, conf->mfcr2.loglevel);
10168             tmp->mfcr2_category = conf->mfcr2.category;
10169             tmp->mfcr2_charge_calls = conf->mfcr2.charge_calls;
10170             tmp->mfcr2_allow_collect_calls = conf->mfcr2.allow_collect_calls;
10171             tmp->mfcr2_forced_release = conf->mfcr2.forced_release;
10172             tmp->mfcr2_accept_on_offer = conf->mfcr2.accept_on_offer;
10173             tmp->mfcr2call = 0;
10174             tmp->mfcr2_dnis_index = 0;
10175             tmp->mfcr2_ani_index = 0;
10176             r2_link->monitored_count++;
10177          }
10178 #endif
10179 #ifdef HAVE_PRI
10180          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
10181             int offset;
10182             int myswitchtype;
10183             int matchesdchan;
10184             int x,y;
10185             offset = 0;
10186             if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
10187                   && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
10188                ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
10189                destroy_dahdi_pvt(&tmp);
10190                return NULL;
10191             }
10192             if (span >= NUM_SPANS) {
10193                ast_log(LOG_ERROR, "Channel %d does not lie on a span I know of (%d)\n", channel, span);
10194                destroy_dahdi_pvt(&tmp);
10195                return NULL;
10196             } else {
10197                struct dahdi_spaninfo si;
10198                si.spanno = 0;
10199                if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
10200                   ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
10201                   destroy_dahdi_pvt(&tmp);
10202                   return NULL;
10203                }
10204                /* Store the logical span first based upon the real span */
10205                tmp->logicalspan = pris[span].prilogicalspan;
10206                pri_resolve_span(&span, channel, (channel - p.chanpos), &si);
10207                if (span < 0) {
10208                   ast_log(LOG_WARNING, "Channel %d: Unable to find locate channel/trunk group!\n", channel);
10209                   destroy_dahdi_pvt(&tmp);
10210                   return NULL;
10211                }
10212                if ((chan_sig == SIG_PRI) ||
10213                      (chan_sig == SIG_BRI) ||
10214                      (chan_sig == SIG_BRI_PTMP))
10215                   myswitchtype = conf->pri.switchtype;
10216                else
10217                   myswitchtype = PRI_SWITCH_GR303_TMC;
10218                /* Make sure this isn't a d-channel */
10219                matchesdchan=0;
10220                for (x = 0; x < NUM_SPANS; x++) {
10221                   for (y = 0; y < NUM_DCHANS; y++) {
10222                      if (pris[x].dchannels[y] == tmp->channel) {
10223                         matchesdchan = 1;
10224                         break;
10225                      }
10226                   }
10227                }
10228                offset = p.chanpos;
10229                if (!matchesdchan) {
10230                   if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
10231                      ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
10232                      destroy_dahdi_pvt(&tmp);
10233                      return NULL;
10234                   }
10235                   if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
10236                      ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
10237                      destroy_dahdi_pvt(&tmp);
10238                      return NULL;
10239                   }
10240                   if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
10241                      ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
10242                      destroy_dahdi_pvt(&tmp);
10243                      return NULL;
10244                   }
10245                   if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
10246                      ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
10247                      destroy_dahdi_pvt(&tmp);
10248                      return NULL;
10249                   }
10250                   if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
10251                      ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
10252                      destroy_dahdi_pvt(&tmp);
10253                      return NULL;
10254                   }
10255                   if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
10256                      ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
10257                      destroy_dahdi_pvt(&tmp);
10258                      return NULL;
10259                   }
10260                   if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
10261                      ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
10262                      destroy_dahdi_pvt(&tmp);
10263                      return NULL;
10264                   }
10265                   if (pris[span].numchans >= MAX_CHANNELS) {
10266                      ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
10267                         pris[span].trunkgroup);
10268                      destroy_dahdi_pvt(&tmp);
10269                      return NULL;
10270                   }
10271 
10272                   pris[span].sig = chan_sig;
10273                   pris[span].nodetype = conf->pri.nodetype;
10274                   pris[span].switchtype = myswitchtype;
10275                   pris[span].nsf = conf->pri.nsf;
10276                   pris[span].dialplan = conf->pri.dialplan;
10277                   pris[span].localdialplan = conf->pri.localdialplan;
10278                   pris[span].pvts[pris[span].numchans++] = tmp;
10279                   pris[span].minunused = conf->pri.minunused;
10280                   pris[span].minidle = conf->pri.minidle;
10281                   pris[span].overlapdial = conf->pri.overlapdial;
10282                   pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
10283                   pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
10284 #ifdef HAVE_PRI_INBANDDISCONNECT
10285                   pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
10286 #endif
10287                   pris[span].facilityenable = conf->pri.facilityenable;
10288                   ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
10289                   ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
10290                   ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
10291                   ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
10292                   ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
10293                   ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
10294                   ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
10295                   pris[span].resetinterval = conf->pri.resetinterval;
10296 
10297                   tmp->pri = &pris[span];
10298                   tmp->prioffset = offset;
10299                   tmp->call = NULL;
10300                } else {
10301                   ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
10302                   destroy_dahdi_pvt(&tmp);
10303                   return NULL;
10304                }
10305             }
10306          } else {
10307             tmp->prioffset = 0;
10308          }
10309 #endif
10310       } else {
10311          chan_sig = tmp->sig;
10312          if (tmp->subs[SUB_REAL].dfd > -1) {
10313             memset(&p, 0, sizeof(p));
10314             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10315          }
10316       }
10317       /* Adjust starttime on loopstart and kewlstart trunks to reasonable values */
10318       switch (chan_sig) {
10319       case SIG_FXSKS:
10320       case SIG_FXSLS:
10321       case SIG_EM:
10322       case SIG_EM_E1:
10323       case SIG_EMWINK:
10324       case SIG_FEATD:
10325       case SIG_FEATDMF:
10326       case SIG_FEATDMF_TA:
10327       case SIG_FEATB:
10328       case SIG_E911:
10329       case SIG_SF:
10330       case SIG_SFWINK:
10331       case SIG_FGC_CAMA:
10332       case SIG_FGC_CAMAMF:
10333       case SIG_SF_FEATD:
10334       case SIG_SF_FEATDMF:
10335       case SIG_SF_FEATB:
10336          p.starttime = 250;
10337          break;
10338       }
10339 
10340       if (tmp->radio) {
10341          /* XXX Waiting to hear back from Jim if these should be adjustable XXX */
10342          p.channo = channel;
10343          p.rxwinktime = 1;
10344          p.rxflashtime = 1;
10345          p.starttime = 1;
10346          p.debouncetime = 5;
10347       }
10348       if (!tmp->radio) {
10349          p.channo = channel;
10350          /* Override timing settings based on config file */
10351          if (conf->timing.prewinktime >= 0)
10352             p.prewinktime = conf->timing.prewinktime;
10353          if (conf->timing.preflashtime >= 0)
10354             p.preflashtime = conf->timing.preflashtime;
10355          if (conf->timing.winktime >= 0)
10356             p.winktime = conf->timing.winktime;
10357          if (conf->timing.flashtime >= 0)
10358             p.flashtime = conf->timing.flashtime;
10359          if (conf->timing.starttime >= 0)
10360             p.starttime = conf->timing.starttime;
10361          if (conf->timing.rxwinktime >= 0)
10362             p.rxwinktime = conf->timing.rxwinktime;
10363          if (conf->timing.rxflashtime >= 0)
10364             p.rxflashtime = conf->timing.rxflashtime;
10365          if (conf->timing.debouncetime >= 0)
10366             p.debouncetime = conf->timing.debouncetime;
10367       }
10368 
10369       /* dont set parms on a pseudo-channel (or CRV) */
10370       if (tmp->subs[SUB_REAL].dfd >= 0)
10371       {
10372          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_PARAMS, &p);
10373          if (res < 0) {
10374             ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
10375             destroy_dahdi_pvt(&tmp);
10376             return NULL;
10377          }
10378       }
10379 #if 1
10380       if (!here && (tmp->subs[SUB_REAL].dfd > -1)) {
10381          memset(&bi, 0, sizeof(bi));
10382          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_BUFINFO, &bi);
10383          if (!res) {
10384             bi.txbufpolicy = conf->chan.buf_policy;
10385             bi.rxbufpolicy = conf->chan.buf_policy;
10386             bi.numbufs = conf->chan.buf_no;
10387             res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_SET_BUFINFO, &bi);
10388             if (res < 0) {
10389                ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
10390             }
10391          } else {
10392             ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
10393          }
10394          tmp->buf_policy = conf->chan.buf_policy;
10395          tmp->buf_no = conf->chan.buf_no;
10396          tmp->usefaxbuffers = conf->chan.usefaxbuffers;
10397          tmp->faxbuf_policy = conf->chan.faxbuf_policy;
10398          tmp->faxbuf_no = conf->chan.faxbuf_no;
10399          /* This is not as gnarly as it may first appear.  If the ioctl above failed, we'd be setting
10400           * tmp->bufsize to zero which would cause subsequent faxbuffer-related ioctl calls to fail.
10401           * The reason the ioctl call above failed should to be determined before worrying about the
10402           * faxbuffer-related ioctl calls */
10403          tmp->bufsize = bi.bufsize;
10404       }
10405 #endif
10406       tmp->immediate = conf->chan.immediate;
10407       tmp->transfertobusy = conf->chan.transfertobusy;
10408       if (chan_sig & __DAHDI_SIG_FXS) {
10409          tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
10410          tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
10411          tmp->mwimonitor_rpas = conf->chan.mwimonitor_rpas;
10412       }
10413       tmp->sig = chan_sig;
10414       tmp->outsigmod = conf->chan.outsigmod;
10415       tmp->ringt_base = ringt_base;
10416       tmp->firstradio = 0;
10417       if ((chan_sig == SIG_FXOKS) || (chan_sig == SIG_FXOLS) || (chan_sig == SIG_FXOGS))
10418          tmp->permcallwaiting = conf->chan.callwaiting;
10419       else
10420          tmp->permcallwaiting = 0;
10421       /* Flag to destroy the channel must be cleared on new mkif.  Part of changes for reload to work */
10422       tmp->destroy = 0;
10423       tmp->drings = conf->chan.drings;
10424 
10425       /* 10 is a nice default. */
10426       if (tmp->drings.ringnum[0].range == 0)
10427          tmp->drings.ringnum[0].range = 10;
10428       if (tmp->drings.ringnum[1].range == 0)
10429          tmp->drings.ringnum[1].range = 10;
10430       if (tmp->drings.ringnum[2].range == 0)
10431          tmp->drings.ringnum[2].range = 10;
10432 
10433       tmp->usedistinctiveringdetection = usedistinctiveringdetection;
10434       tmp->callwaitingcallerid = conf->chan.callwaitingcallerid;
10435       tmp->threewaycalling = conf->chan.threewaycalling;
10436       tmp->adsi = conf->chan.adsi;
10437       tmp->use_smdi = conf->chan.use_smdi;
10438       tmp->permhidecallerid = conf->chan.hidecallerid;
10439       tmp->callreturn = conf->chan.callreturn;
10440       tmp->echocancel = conf->chan.echocancel;
10441       tmp->echotraining = conf->chan.echotraining;
10442       tmp->pulse = conf->chan.pulse;
10443       if (tmp->echocancel.head.tap_length) {
10444          tmp->echocanbridged = conf->chan.echocanbridged;
10445       } else {
10446          if (conf->chan.echocanbridged)
10447             ast_log(LOG_NOTICE, "echocancelwhenbridged requires echocancel to be enabled; ignoring\n");
10448          tmp->echocanbridged = 0;
10449       }
10450       tmp->busydetect = conf->chan.busydetect;
10451       tmp->busycount = conf->chan.busycount;
10452       tmp->busy_tonelength = conf->chan.busy_tonelength;
10453       tmp->busy_quietlength = conf->chan.busy_quietlength;
10454       tmp->callprogress = conf->chan.callprogress;
10455       tmp->waitfordialtone = conf->chan.waitfordialtone;
10456       tmp->cancallforward = conf->chan.cancallforward;
10457       tmp->dtmfrelax = conf->chan.dtmfrelax;
10458       tmp->callwaiting = tmp->permcallwaiting;
10459       tmp->hidecallerid = tmp->permhidecallerid;
10460       tmp->channel = channel;
10461       tmp->stripmsd = conf->chan.stripmsd;
10462       tmp->use_callerid = conf->chan.use_callerid;
10463       tmp->cid_signalling = conf->chan.cid_signalling;
10464       tmp->cid_start = conf->chan.cid_start;
10465       tmp->dahditrcallerid = conf->chan.dahditrcallerid;
10466       tmp->restrictcid = conf->chan.restrictcid;
10467       tmp->use_callingpres = conf->chan.use_callingpres;
10468       tmp->priexclusive = conf->chan.priexclusive;
10469       if (tmp->usedistinctiveringdetection) {
10470          if (!tmp->use_callerid) {
10471             ast_log(LOG_NOTICE, "Distinctive Ring detect requires 'usecallerid' be on\n");
10472             tmp->use_callerid = 1;
10473          }
10474       }
10475 
10476       if (tmp->cid_signalling == CID_SIG_SMDI) {
10477          if (!tmp->use_smdi) {
10478             ast_log(LOG_WARNING, "SMDI callerid requires SMDI to be enabled, enabling...\n");
10479             tmp->use_smdi = 1;
10480          }
10481       }
10482       if (tmp->use_smdi) {
10483          tmp->smdi_iface = ast_smdi_interface_find(conf->smdi_port);
10484          if (!(tmp->smdi_iface)) {
10485             ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n");
10486             tmp->use_smdi = 0;
10487          }
10488       }
10489 
10490       ast_copy_string(tmp->accountcode, conf->chan.accountcode, sizeof(tmp->accountcode));
10491       tmp->amaflags = conf->chan.amaflags;
10492       if (!here) {
10493          tmp->confno = -1;
10494          tmp->propconfno = -1;
10495       }
10496       tmp->canpark = conf->chan.canpark;
10497       tmp->transfer = conf->chan.transfer;
10498       ast_copy_string(tmp->defcontext,conf->chan.context,sizeof(tmp->defcontext));
10499       ast_copy_string(tmp->language, conf->chan.language, sizeof(tmp->language));
10500       ast_copy_string(tmp->mohinterpret, conf->chan.mohinterpret, sizeof(tmp->mohinterpret));
10501       ast_copy_string(tmp->mohsuggest, conf->chan.mohsuggest, sizeof(tmp->mohsuggest));
10502       ast_copy_string(tmp->context, conf->chan.context, sizeof(tmp->context));
10503       ast_copy_string(tmp->parkinglot, conf->chan.parkinglot, sizeof(tmp->parkinglot));
10504       tmp->cid_ton = 0;
10505       if ((tmp->sig != SIG_PRI) || (tmp->sig != SIG_SS7) || (tmp->sig != SIG_BRI) || (tmp->sig != SIG_BRI_PTMP) || (tmp->sig != SIG_MFCR2)) {
10506          ast_copy_string(tmp->cid_num, conf->chan.cid_num, sizeof(tmp->cid_num));
10507          ast_copy_string(tmp->cid_name, conf->chan.cid_name, sizeof(tmp->cid_name));
10508       } else {
10509          tmp->cid_num[0] = '\0';
10510          tmp->cid_name[0] = '\0';
10511       }
10512       ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
10513       if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
10514          char *mailbox, *context;
10515          mailbox = context = ast_strdupa(tmp->mailbox);
10516          strsep(&context, "@");
10517          if (ast_strlen_zero(context))
10518             context = "default";
10519          tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
10520             AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
10521             AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
10522             AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
10523             AST_EVENT_IE_END);
10524       }
10525       tmp->msgstate = -1;
10526 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10527       tmp->mwisend_setting = conf->chan.mwisend_setting;
10528       tmp->mwisend_fsk  = conf->chan.mwisend_fsk;
10529       tmp->mwisend_rpas = conf->chan.mwisend_rpas;
10530 #endif
10531       if (chan_sig & __DAHDI_SIG_FXO) {
10532          memset(&p, 0, sizeof(p));
10533          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &p);
10534          if (!res) {
10535             tmp->fxsoffhookstate = p.rxisoffhook;
10536          }
10537 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
10538          res = ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_VMWI_CONFIG, &tmp->mwisend_setting);
10539 #endif
10540       }
10541       tmp->onhooktime = time(NULL);
10542       tmp->group = conf->chan.group;
10543       tmp->callgroup = conf->chan.callgroup;
10544       tmp->pickupgroup= conf->chan.pickupgroup;
10545       if (conf->chan.vars) {
10546          struct ast_variable *v, *tmpvar;
10547                    for (v = conf->chan.vars ; v ; v = v->next) {
10548                          if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
10549                                   tmpvar->next = tmp->vars;
10550                                    tmp->vars = tmpvar;
10551                            }
10552                   }
10553       }
10554       tmp->cid_rxgain = conf->chan.cid_rxgain;
10555       tmp->rxgain = conf->chan.rxgain;
10556       tmp->txgain = conf->chan.txgain;
10557       tmp->tonezone = conf->chan.tonezone;
10558       if (tmp->subs[SUB_REAL].dfd > -1) {
10559          set_actual_gain(tmp->subs[SUB_REAL].dfd, 0, tmp->rxgain, tmp->txgain, tmp->law);
10560          if (tmp->dsp)
10561             ast_dsp_set_digitmode(tmp->dsp, DSP_DIGITMODE_DTMF | tmp->dtmfrelax);
10562          update_conf(tmp);
10563          if (!here) {
10564             if ((chan_sig != SIG_BRI) && (chan_sig != SIG_BRI_PTMP) && (chan_sig != SIG_PRI)
10565                 && (chan_sig != SIG_SS7) && (chan_sig != SIG_MFCR2))
10566                /* Hang it up to be sure it's good */
10567                dahdi_set_hook(tmp->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
10568          }
10569          ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
10570 #ifdef HAVE_PRI
10571          /* the dchannel is down so put the channel in alarm */
10572          if (tmp->pri && !pri_is_up(tmp->pri))
10573             tmp->inalarm = 1;
10574 #endif
10575          if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
10576             tmp->inalarm = 1;
10577             handle_alarms(tmp, res);
10578          }
10579       }
10580 
10581       tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
10582       tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
10583       tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
10584       tmp->sendcalleridafter = conf->chan.sendcalleridafter;
10585       if (!here) {
10586          tmp->locallyblocked = tmp->remotelyblocked = 0;
10587          if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
10588             tmp->inservice = 0;
10589          else /* We default to in service on protocols that don't have a reset */
10590             tmp->inservice = 1;
10591       }
10592    }
10593    if (tmp && !here) {
10594       /* nothing on the iflist */
10595       if (!*wlist) {
10596          *wlist = tmp;
10597          tmp->prev = NULL;
10598          tmp->next = NULL;
10599          *wend = tmp;
10600       } else {
10601          /* at least one member on the iflist */
10602          struct dahdi_pvt *working = *wlist;
10603 
10604          /* check if we maybe have to put it on the begining */
10605          if (working->channel > tmp->channel) {
10606             tmp->next = *wlist;
10607             tmp->prev = NULL;
10608             (*wlist)->prev = tmp;
10609             *wlist = tmp;
10610          } else {
10611          /* go through all the members and put the member in the right place */
10612             while (working) {
10613                /* in the middle */
10614                if (working->next) {
10615                   if (working->channel < tmp->channel && working->next->channel > tmp->channel) {
10616                      tmp->next = working->next;
10617                      tmp->prev = working;
10618                      working->next->prev = tmp;
10619                      working->next = tmp;
10620                      break;
10621                   }
10622                } else {
10623                /* the last */
10624                   if (working->channel < tmp->channel) {
10625                      working->next = tmp;
10626                      tmp->next = NULL;
10627                      tmp->prev = working;
10628                      *wend = tmp;
10629                      break;
10630                   }
10631                }
10632                working = working->next;
10633             }
10634          }
10635       }
10636    }
10637    return tmp;
10638 }

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

Definition at line 367 of file chan_dahdi.c.

Referenced by mkintf().

00368 {
00369    /* This module does not handle MWI in an event-based manner.  However, it
00370     * subscribes to MWI for each mailbox that is configured so that the core
00371     * knows that we care about it.  Then, chan_dahdi will get the MWI from the
00372     * event cache instead of checking the mailbox directly. */
00373 }

static int mwi_send_init ( struct dahdi_pvt pvt  )  [static]

Definition at line 9063 of file chan_dahdi.c.

References ast_calloc, ast_free, AST_LAW, ast_log(), CID_MWI_TYPE_MDMF_FULL, dahdi_pvt::cid_name, dahdi_pvt::cid_num, dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_subchannel::dfd, has_voicemail(), LOG_WARNING, MAX_CALLERID_SIZE, MWI_SEND_SA, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, SUB_REAL, dahdi_pvt::subs, and vmwi_generate().

Referenced by do_monitor().

09064 {
09065    int x, res;
09066 
09067 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09068    /* Determine how this spill is to be sent */
09069    if (pvt->mwisend_rpas) {
09070       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09071       pvt->mwisendactive = 1;
09072    } else if (pvt->mwisend_fsk) {
09073       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09074       pvt->mwisendactive = 1;
09075    } else {
09076       pvt->mwisendactive = 0;
09077       return 0;
09078    }
09079 #else
09080    if (mwisend_rpas) {
09081       pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
09082    } else {
09083       pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09084    }
09085    pvt->mwisendactive = 1;
09086 #endif
09087 
09088    if (pvt->cidspill) {
09089       ast_log(LOG_WARNING, "cidspill already exists when trying to send FSK MWI\n");
09090       ast_free(pvt->cidspill);
09091       pvt->cidspill = NULL;
09092       pvt->cidpos = 0;
09093       pvt->cidlen = 0;
09094    }
09095    pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
09096    if (!pvt->cidspill) {
09097       pvt->mwisendactive = 0;
09098       return -1;
09099    }
09100    x = DAHDI_FLUSH_BOTH;
09101    res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
09102    x = 3000;
09103    ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
09104 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09105    if (pvt->mwisend_fsk) {
09106 #endif
09107       pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
09108                         AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
09109       pvt->cidpos = 0;
09110 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09111    }
09112 #endif
09113    return 0;
09114 }

static int mwi_send_process_buffer ( struct dahdi_pvt pvt,
int  num_read 
) [static]

Definition at line 9116 of file chan_dahdi.c.

References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_CLEANUP, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA, MWI_SEND_SA_WAIT, MWI_SEND_SPILL, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, quit, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

09117 {
09118    struct timeval    now;
09119    int         res;
09120 
09121    /* sanity check to catch if this had been interrupted previously
09122    *  i.e. state says there is more to do but there is no spill allocated
09123    */
09124    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
09125       pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09126    } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09127       /* Normal processing -- Perform mwi send action */
09128       switch ( pvt->mwisend_data.mwisend_current) {
09129       case MWI_SEND_SA:
09130          /* Send the Ring Pulse Signal Alert */
09131          res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
09132          if (res) {
09133             ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
09134             goto quit;
09135          }
09136          res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
09137          pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
09138          break;
09139       case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
09140          break;
09141       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
09142 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09143          if (pvt->mwisend_fsk) {
09144 #endif
09145             gettimeofday(&now, NULL);
09146             if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
09147                pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
09148             }
09149 #ifdef HAVE_DAHDI_LINEREVERSE_VMWI
09150          } else { /* support for mwisendtype=nofsk */
09151             pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09152          }
09153 #endif
09154          break;
09155       case MWI_SEND_SPILL:
09156          /* We read some number of bytes.  Write an equal amount of data */
09157          if(0 < num_read) {
09158             if (num_read > pvt->cidlen - pvt->cidpos)
09159                num_read = pvt->cidlen - pvt->cidpos;
09160             res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
09161             if (res > 0) {
09162                pvt->cidpos += res;
09163                if (pvt->cidpos >= pvt->cidlen) {
09164                   pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
09165                }
09166             } else {
09167                ast_log(LOG_WARNING, "MWI FSK Send Write failed: %s\n", strerror(errno));
09168                goto quit;
09169             }
09170          }
09171          break;
09172       case MWI_SEND_CLEANUP:
09173          /* For now, do nothing */
09174          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09175          break;
09176       default:
09177          /* Should not get here, punt*/
09178          goto quit;
09179       }
09180    }
09181 
09182    if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
09183       if (pvt->cidspill) {
09184          ast_free(pvt->cidspill);
09185          pvt->cidspill = NULL;
09186          pvt->cidpos = 0;
09187          pvt->cidlen = 0;
09188       }
09189       pvt->mwisendactive = 0;
09190    }
09191    return 0;
09192 quit:
09193    if (pvt->cidspill) {
09194       ast_free(pvt->cidspill);
09195       pvt->cidspill = NULL;
09196       pvt->cidpos = 0;
09197       pvt->cidlen = 0;
09198    }
09199    pvt->mwisendactive = 0;
09200    return -1;
09201 }

static int mwi_send_process_event ( struct dahdi_pvt pvt,
int  event 
) [static]

Definition at line 9203 of file chan_dahdi.c.

References ast_free, ast_log(), dahdi_pvt::cidlen, dahdi_pvt::cidpos, dahdi_pvt::cidspill, dahdi_set_hook(), dahdi_subchannel::dfd, errno, LOG_WARNING, MWI_SEND_DONE, MWI_SEND_PAUSE, MWI_SEND_SA_WAIT, mwisend_info::mwisend_current, dahdi_pvt::mwisend_data, dahdi_pvt::mwisendactive, mwisend_info::pause, SUB_REAL, and dahdi_pvt::subs.

Referenced by do_monitor().

09204 {
09205    int handled = 0;
09206 
09207    if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
09208       switch (event) {
09209       case DAHDI_EVENT_RINGEROFF:
09210          if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
09211             handled = 1;
09212 
09213             if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
09214                ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
09215                if(pvt->cidspill) {
09216                   ast_free(pvt->cidspill);
09217                   pvt->cidspill = NULL;
09218                }
09219                pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09220                pvt->mwisendactive = 0;
09221             } else {
09222                pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
09223                gettimeofday(&pvt->mwisend_data.pause, NULL);
09224             }
09225          }
09226          break;
09227       /* Going off hook, I need to punt this spill */
09228       case DAHDI_EVENT_RINGOFFHOOK:
09229          if (pvt->cidspill) {
09230             ast_free(pvt->cidspill);
09231             pvt->cidspill = NULL;
09232             pvt->cidpos = 0;
09233             pvt->cidlen = 0;
09234          }
09235          pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
09236          pvt->mwisendactive = 0;
09237          break;
09238       case DAHDI_EVENT_RINGERON:
09239       case DAHDI_EVENT_HOOKCOMPLETE:
09240          break;
09241       default:
09242          break;
09243       }
09244    }
09245    return handled;
09246 }

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

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

08926 {
08927    struct mwi_thread_data *mtd = data;
08928    struct callerid_state *cs;
08929    pthread_t threadid;
08930    int samples = 0;
08931    char *name, *number;
08932    int flags;
08933    int i, res;
08934    unsigned int spill_done = 0;
08935    int spill_result = -1;
08936 
08937    if (!(cs = callerid_new(mtd->pvt->cid_signalling))) {
08938       mtd->pvt->mwimonitoractive = 0;
08939 
08940       return NULL;
08941    }
08942 
08943    callerid_feed(cs, mtd->buf, mtd->len, AST_LAW(mtd->pvt));
08944 
08945    bump_gains(mtd->pvt);
08946 
08947    for (;;) {
08948       i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08949       if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
08950          ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08951          goto quit;
08952       }
08953 
08954       if (i & DAHDI_IOMUX_SIGEVENT) {
08955          struct ast_channel *chan;
08956 
08957          /* If we get an event, screen out events that we do not act on.
08958           * Otherwise, cancel and go to the simple switch to let it deal with it.
08959           */
08960          res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
08961 
08962          switch (res) {
08963          case DAHDI_EVENT_NEONMWI_ACTIVE:
08964          case DAHDI_EVENT_NEONMWI_INACTIVE:
08965          case DAHDI_EVENT_NONE:
08966          case DAHDI_EVENT_BITSCHANGED:
08967             break;
08968          case DAHDI_EVENT_NOALARM:
08969             mtd->pvt->inalarm = 0;
08970             ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", mtd->pvt->channel);
08971             manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
08972                "Channel: %d\r\n", mtd->pvt->channel);
08973             break;
08974          case DAHDI_EVENT_ALARM:
08975             mtd->pvt->inalarm = 1;
08976             res = get_alarms(mtd->pvt);
08977             handle_alarms(mtd->pvt, res);
08978             break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
08979          default:
08980             ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
08981             callerid_free(cs);
08982 
08983             restore_gains(mtd->pvt);
08984             mtd->pvt->ringt = mtd->pvt->ringt_base;
08985 
08986             if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
08987                if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
08988                   ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
08989                   res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
08990                   if (res < 0)
08991                      ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", mtd->pvt->channel);
08992                   ast_hangup(chan);
08993                   goto quit;
08994                }
08995                goto quit_no_clean;
08996 
08997             } else {
08998                ast_log(LOG_WARNING, "Could not create channel to handle call\n");
08999             }
09000          }
09001       } else if (i & DAHDI_IOMUX_READ) {
09002          if ((res = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
09003             if (errno != ELAST) {
09004                ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
09005                goto quit;
09006             }
09007             break;
09008          }
09009          samples += res;
09010          if (!spill_done) {
09011             if ((spill_result = callerid_feed(cs, mtd->buf, res, AST_LAW(mtd->pvt))) < 0) {
09012                ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
09013                break;
09014             } else if (spill_result) {
09015                spill_done = 1;
09016             }
09017          } else {
09018             /* keep reading data until the energy level drops below the threshold
09019                so we don't get another 'trigger' on the remaining carrier signal
09020             */
09021             if (calc_energy(mtd->buf, res, AST_LAW(mtd->pvt)) <= mwilevel)
09022                break;
09023          }
09024          if (samples > (8000 * 4)) /*Termination case - time to give up*/
09025             break;
09026       }
09027    }
09028 
09029    if (spill_result == 1) {
09030       callerid_get(cs, &name, &number, &flags);
09031       if (flags & CID_MSGWAITING) {
09032          ast_log(LOG_NOTICE, "mwi: Have Messages on channel %d\n", mtd->pvt->channel);
09033          notify_message(mtd->pvt->mailbox, 1);
09034       } else if (flags & CID_NOMSGWAITING) {
09035          ast_log(LOG_NOTICE, "mwi: No Messages on channel %d\n", mtd->pvt->channel);
09036          notify_message(mtd->pvt->mailbox, 0);
09037       } else {
09038          ast_log(LOG_NOTICE, "mwi: Status unknown on channel %d\n", mtd->pvt->channel);
09039       }
09040    }
09041 
09042 
09043 quit:
09044    callerid_free(cs);
09045 
09046    restore_gains(mtd->pvt);
09047 
09048 quit_no_clean:
09049    mtd->pvt->mwimonitoractive = 0;
09050 
09051    ast_free(mtd);
09052 
09053    return NULL;
09054 }

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

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

07069 {
07070    int sent=0;
07071    int size;
07072    int res;
07073    int fd;
07074    fd = p->subs[idx].dfd;
07075    while (len) {
07076       size = len;
07077       if (size > (linear ? READ_SIZE * 2 : READ_SIZE))
07078          size = (linear ? READ_SIZE * 2 : READ_SIZE);
07079       res = write(fd, buf, size);
07080       if (res != size) {
07081          ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
07082          return sent;
07083       }
07084       len -= size;
07085       buf += size;
07086    }
07087    return sent;
07088 }

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

Definition at line 7616 of file chan_dahdi.c.

References ast_waitfordigit().

Referenced by ss_thread().

07617 {
07618    char c;
07619 
07620    *str = 0; /* start with empty output buffer */
07621    for (;;)
07622    {
07623       /* Wait for the first digit (up to specified ms). */
07624       c = ast_waitfordigit(chan, ms);
07625       /* if timeout, hangup or error, return as such */
07626       if (c < 1)
07627          return c;
07628       *str++ = c;
07629       *str = 0;
07630       if (strchr(term, c))
07631          return 1;
07632    }
07633 }

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 2940 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_strlen_zero(), context, mailbox, and s.

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

02941 {
02942    char s[sizeof(mwimonitornotify) + 80];
02943    struct ast_event *event;
02944    char *mailbox, *context;
02945 
02946    /* Strip off @default */
02947    context = mailbox = ast_strdupa(mailbox_full);
02948    strsep(&context, "@");
02949    if (ast_strlen_zero(context))
02950       context = "default";
02951 
02952    if (!(event = ast_event_new(AST_EVENT_MWI,
02953          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
02954          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
02955          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02956          AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, thereornot,
02957          AST_EVENT_IE_END))) {
02958       return;
02959    }
02960 
02961    ast_event_queue_and_cache(event);
02962 
02963    if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
02964       snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
02965       ast_safe_system(s);
02966    }
02967 }

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

Definition at line 9858 of file chan_dahdi.c.

Referenced by process_dahdi().

09859 {
09860    unsigned int code1, code2, code3;
09861    int numvals;
09862 
09863    numvals = sscanf(pcstring, "%30d-%30d-%30d", &code1, &code2, &code3);
09864    if (numvals == 1)
09865       return code1;
09866    if (numvals == 3)
09867       return (code1 << 16) | (code2 << 8) | code3;
09868 
09869    return 0;
09870 }

static int pri_active_dchan_fd ( struct dahdi_pri pri  )  [static]

Definition at line 4126 of file chan_dahdi.c.

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

Referenced by pri_find_principle().

04127 {
04128    int x = -1;
04129 
04130    for (x = 0; x < NUM_DCHANS; x++) {
04131       if ((pri->dchans[x] == pri->pri))
04132          break;
04133    }
04134 
04135    return pri->fds[x];
04136 }

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

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

04093 {
04094    bearer->owner = &inuse;
04095    bearer->realcall = crv;
04096    crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
04097    if (crv->subs[SUB_REAL].owner)
04098       ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
04099    crv->bearer = bearer;
04100    crv->call = bearer->call;
04101    crv->pri = pri;
04102    return 0;
04103 }

static int pri_check_restart ( struct dahdi_pri pri  )  [static]

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

12298 {
12299    do {
12300       pri->resetpos++;
12301    } while ((pri->resetpos < pri->numchans) &&
12302       (!pri->pvts[pri->resetpos] ||
12303       pri->pvts[pri->resetpos]->call ||
12304       pri->pvts[pri->resetpos]->resetting));
12305    if (pri->resetpos < pri->numchans) {
12306       /* Mark the channel as resetting and restart it */
12307       pri->pvts[pri->resetpos]->resetting = 1;
12308       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
12309    } else {
12310       pri->resetting = 0;
12311       time(&pri->lastreset);
12312    }
12313    return 0;
12314 }

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

Definition at line 9845 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

09846 {
09847    if (pris[span].mastertrunkgroup) {
09848       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);
09849       return -1;
09850    }
09851    pris[span].mastertrunkgroup = trunkgroup;
09852    pris[span].prilogicalspan = logicalspan;
09853    return 0;
09854 }

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

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

09781 {
09782    struct dahdi_spaninfo si;
09783    struct dahdi_params p;
09784    int fd;
09785    int span;
09786    int ospan=0;
09787    int x,y;
09788    for (x = 0; x < NUM_SPANS; x++) {
09789       if (pris[x].trunkgroup == trunkgroup) {
09790          ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
09791          return -1;
09792       }
09793    }
09794    for (y = 0; y < NUM_DCHANS; y++) {
09795       if (!channels[y])
09796          break;
09797       memset(&si, 0, sizeof(si));
09798       memset(&p, 0, sizeof(p));
09799       fd = open("/dev/dahdi/channel", O_RDWR);
09800       if (fd < 0) {
09801          ast_log(LOG_WARNING, "Failed to open channel: %s\n", strerror(errno));
09802          return -1;
09803       }
09804       x = channels[y];
09805       if (ioctl(fd, DAHDI_SPECIFY, &x)) {
09806          ast_log(LOG_WARNING, "Failed to specify channel %d: %s\n", channels[y], strerror(errno));
09807          close(fd);
09808          return -1;
09809       }
09810       if (ioctl(fd, DAHDI_GET_PARAMS, &p)) {
09811          ast_log(LOG_WARNING, "Failed to get channel parameters for channel %d: %s\n", channels[y], strerror(errno));
09812          return -1;
09813       }
09814       if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
09815          ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
09816          close(fd);
09817          return -1;
09818       }
09819       span = p.spanno - 1;
09820       if (pris[span].trunkgroup) {
09821          ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
09822          close(fd);
09823          return -1;
09824       }
09825       if (pris[span].pvts[0]) {
09826          ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
09827          close(fd);
09828          return -1;
09829       }
09830       if (!y) {
09831          pris[span].trunkgroup = trunkgroup;
09832          pris[span].offset = channels[y] - p.chanpos;
09833          ospan = span;
09834       }
09835       pris[ospan].dchannels[y] = channels[y];
09836       pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
09837       pris[span].span = span + 1;
09838       close(fd);
09839    }
09840    return 0;
09841 }

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

Definition at line 12398 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_pri::discardremoteholdretrieval, 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, ast_channel::name, 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().

12399 {
12400    struct dahdi_pri *pri = vpri;
12401    pri_event *e;
12402    struct pollfd fds[NUM_DCHANS];
12403    int res;
12404    int chanpos = 0;
12405    int x;
12406    int haveidles;
12407    int activeidles;
12408    int nextidle = -1;
12409    struct ast_channel *c;
12410    struct timeval tv, lowest, *next;
12411    struct timeval lastidle = ast_tvnow();
12412    int doidling=0;
12413    char *cc;
12414    char idlen[80];
12415    struct ast_channel *idle;
12416    pthread_t p;
12417    time_t t;
12418    int i, which=-1;
12419    int numdchans;
12420    int cause=0;
12421    struct dahdi_pvt *crv;
12422    pthread_t threadid;
12423    char ani2str[6];
12424    char plancallingnum[256];
12425    char plancallingani[256];
12426    char calledtonstr[10];
12427 
12428    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12429 
12430    gettimeofday(&lastidle, NULL);
12431    if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
12432       /* Need to do idle dialing, check to be sure though */
12433       cc = strchr(pri->idleext, '@');
12434       if (cc) {
12435          *cc = '\0';
12436          cc++;
12437          ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
12438 #if 0
12439          /* Extensions may not be loaded yet */
12440          if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
12441             ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
12442          else
12443 #endif
12444             doidling = 1;
12445       } else
12446          ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
12447    }
12448    for (;;) {
12449       for (i = 0; i < NUM_DCHANS; i++) {
12450          if (!pri->dchannels[i])
12451             break;
12452          fds[i].fd = pri->fds[i];
12453          fds[i].events = POLLIN | POLLPRI;
12454          fds[i].revents = 0;
12455       }
12456       numdchans = i;
12457       time(&t);
12458       ast_mutex_lock(&pri->lock);
12459       if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
12460          if (pri->resetting && pri_is_up(pri)) {
12461             if (pri->resetpos < 0)
12462                pri_check_restart(pri);
12463          } else {
12464             if (!pri->resetting  && (t - pri->lastreset) >= pri->resetinterval) {
12465                pri->resetting = 1;
12466                pri->resetpos = -1;
12467             }
12468          }
12469       }
12470       /* Look for any idle channels if appropriate */
12471       if (doidling && pri_is_up(pri)) {
12472          nextidle = -1;
12473          haveidles = 0;
12474          activeidles = 0;
12475          for (x = pri->numchans; x >= 0; x--) {
12476             if (pri->pvts[x] && !pri->pvts[x]->owner &&
12477                !pri->pvts[x]->call) {
12478                if (haveidles < pri->minunused) {
12479                   haveidles++;
12480                } else if (!pri->pvts[x]->resetting) {
12481                   nextidle = x;
12482                   break;
12483                }
12484             } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
12485                activeidles++;
12486          }
12487          if (nextidle > -1) {
12488             if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
12489                /* Don't create a new idle call more than once per second */
12490                snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
12491                idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
12492                if (idle) {
12493                   pri->pvts[nextidle]->isidlecall = 1;
12494                   if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
12495                      ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
12496                      dahdi_hangup(idle);
12497                   }
12498                } else
12499                   ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
12500                lastidle = ast_tvnow();
12501             }
12502          } else if ((haveidles < pri->minunused) &&
12503             (activeidles > pri->minidle)) {
12504             /* Mark something for hangup if there is something
12505                that can be hungup */
12506             for (x = pri->numchans; x >= 0; x--) {
12507                /* find a candidate channel */
12508                if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
12509                   pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12510                   haveidles++;
12511                   /* Stop if we have enough idle channels or
12512                     can't spare any more active idle ones */
12513                   if ((haveidles >= pri->minunused) ||
12514                      (activeidles <= pri->minidle))
12515                      break;
12516                }
12517             }
12518          }
12519       }
12520       /* Start with reasonable max */
12521       lowest = ast_tv(60, 0);
12522       for (i = 0; i < NUM_DCHANS; i++) {
12523          /* Find lowest available d-channel */
12524          if (!pri->dchannels[i])
12525             break;
12526          if ((next = pri_schedule_next(pri->dchans[i]))) {
12527             /* We need relative time here */
12528             tv = ast_tvsub(*next, ast_tvnow());
12529             if (tv.tv_sec < 0) {
12530                tv = ast_tv(0,0);
12531             }
12532             if (doidling || pri->resetting) {
12533                if (tv.tv_sec > 1) {
12534                   tv = ast_tv(1, 0);
12535                }
12536             } else {
12537                if (tv.tv_sec > 60) {
12538                   tv = ast_tv(60, 0);
12539                }
12540             }
12541          } else if (doidling || pri->resetting) {
12542             /* Make sure we stop at least once per second if we're
12543                monitoring idle channels */
12544             tv = ast_tv(1,0);
12545          } else {
12546             /* Don't poll for more than 60 seconds */
12547             tv = ast_tv(60, 0);
12548          }
12549          if (!i || ast_tvcmp(tv, lowest) < 0) {
12550             lowest = tv;
12551          }
12552       }
12553       ast_mutex_unlock(&pri->lock);
12554 
12555       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
12556       pthread_testcancel();
12557       e = NULL;
12558       res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
12559       pthread_testcancel();
12560       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
12561 
12562       ast_mutex_lock(&pri->lock);
12563       if (!res) {
12564          for (which = 0; which < NUM_DCHANS; which++) {
12565             if (!pri->dchans[which])
12566                break;
12567             /* Just a timeout, run the scheduler */
12568             e = pri_schedule_run(pri->dchans[which]);
12569             if (e)
12570                break;
12571          }
12572       } else if (res > -1) {
12573          for (which = 0; which < NUM_DCHANS; which++) {
12574             if (!pri->dchans[which])
12575                break;
12576             if (fds[which].revents & POLLPRI) {
12577                /* Check for an event */
12578                x = 0;
12579                res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
12580                if (x) {
12581                   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);
12582                   manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
12583                      "PRIEvent: %s\r\n"
12584                      "PRIEventCode: %d\r\n"
12585                      "D-channel: %s\r\n"
12586                      "Span: %d\r\n",
12587                      event2str(x),
12588                      x,
12589                      pri_order(which),
12590                      pri->span
12591                      );
12592                }
12593                /* Keep track of alarm state */
12594                if (x == DAHDI_EVENT_ALARM) {
12595                   pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
12596                   pri_find_dchan(pri);
12597                } else if (x == DAHDI_EVENT_NOALARM) {
12598                   pri->dchanavail[which] |= DCHAN_NOTINALARM;
12599                   pri_restart(pri->dchans[which]);
12600                }
12601 
12602                ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
12603             } else if (fds[which].revents & POLLIN) {
12604                e = pri_check_event(pri->dchans[which]);
12605             }
12606             if (e)
12607                break;
12608          }
12609       } else if (errno != EINTR)
12610          ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
12611 
12612       if (e) {
12613          if (pri->debug)
12614             pri_dump_event(pri->dchans[which], e);
12615 
12616          if (e->e != PRI_EVENT_DCHAN_DOWN) {
12617             if (!(pri->dchanavail[which] & DCHAN_UP)) {
12618                ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
12619             }
12620             pri->dchanavail[which] |= DCHAN_UP;
12621          } else if (pri->sig != SIG_BRI_PTMP) {
12622             if (pri->dchanavail[which] & DCHAN_UP) {
12623                ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
12624             }
12625             pri->dchanavail[which] &= ~DCHAN_UP;
12626          }
12627 
12628          if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
12629             /* Must be an NFAS group that has the secondary dchan active */
12630             pri->pri = pri->dchans[which];
12631 
12632          switch (e->e) {
12633          case PRI_EVENT_DCHAN_UP:
12634             if (!pri->pri) pri_find_dchan(pri);
12635 
12636             /* Note presense of D-channel */
12637             time(&pri->lastreset);
12638 
12639             /* Restart in 5 seconds */
12640             if (pri->resetinterval > -1) {
12641                pri->lastreset -= pri->resetinterval;
12642                pri->lastreset += 5;
12643             }
12644             pri->resetting = 0;
12645             /* Take the channels from inalarm condition */
12646             for (i = 0; i < pri->numchans; i++)
12647                if (pri->pvts[i]) {
12648                   pri->pvts[i]->inalarm = 0;
12649                }
12650             break;
12651          case PRI_EVENT_DCHAN_DOWN:
12652             pri_find_dchan(pri);
12653             if (!pri_is_up(pri)) {
12654                pri->resetting = 0;
12655                /* Hangup active channels and put them in alarm mode */
12656                for (i = 0; i < pri->numchans; i++) {
12657                   struct dahdi_pvt *p = pri->pvts[i];
12658                   if (p) {
12659                      if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
12660                         /* T309 is not enabled : hangup calls when alarm occurs */
12661                         if (p->call) {
12662                            if (p->pri && p->pri->pri) {
12663                               pri_hangup(p->pri->pri, p->call, -1);
12664                               pri_destroycall(p->pri->pri, p->call);
12665                               p->call = NULL;
12666                            } else
12667                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
12668                         }
12669                         if (p->realcall) {
12670                            pri_hangup_all(p->realcall, pri);
12671                         } else if (p->owner)
12672                            p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12673                      }
12674                      /* For PTMP connections with non persistent layer 2 we want
12675                       * to *not* declare inalarm unless there actually is an alarm */
12676                      if (p->sig != SIG_BRI_PTMP) {
12677                         p->inalarm = 1;
12678                      }
12679                   }
12680                }
12681             }
12682             break;
12683          case PRI_EVENT_RESTART:
12684             if (e->restart.channel > -1) {
12685                chanpos = pri_find_principle(pri, e->restart.channel);
12686                if (chanpos < 0)
12687                   ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
12688                      PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12689                else {
12690                   ast_verb(3, "B-channel %d/%d restarted on span %d\n",
12691                         PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
12692                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12693                   if (pri->pvts[chanpos]->call) {
12694                      pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
12695                      pri->pvts[chanpos]->call = NULL;
12696                   }
12697                   /* Force soft hangup if appropriate */
12698                   if (pri->pvts[chanpos]->realcall)
12699                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
12700                   else if (pri->pvts[chanpos]->owner)
12701                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12702                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12703                }
12704             } else {
12705                ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
12706                for (x = 0; x < pri->numchans; x++)
12707                   if (pri->pvts[x]) {
12708                      ast_mutex_lock(&pri->pvts[x]->lock);
12709                      if (pri->pvts[x]->call) {
12710                         pri_destroycall(pri->pri, pri->pvts[x]->call);
12711                         pri->pvts[x]->call = NULL;
12712                      }
12713                      if (pri->pvts[x]->realcall)
12714                         pri_hangup_all(pri->pvts[x]->realcall, pri);
12715                      else if (pri->pvts[x]->owner)
12716                         pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12717                      ast_mutex_unlock(&pri->pvts[x]->lock);
12718                   }
12719             }
12720             break;
12721          case PRI_EVENT_KEYPAD_DIGIT:
12722             chanpos = pri_find_principle(pri, e->digit.channel);
12723             if (chanpos < 0) {
12724                ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
12725                   PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
12726             } else {
12727                chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
12728                if (chanpos > -1) {
12729                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12730                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
12731                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
12732                      /* how to do that */
12733                      int digitlen = strlen(e->digit.digits);
12734                      char digit;
12735                      int i;
12736                      for (i = 0; i < digitlen; i++) {
12737                         digit = e->digit.digits[i];
12738                         {
12739                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
12740                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12741                         }
12742                      }
12743                   }
12744                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12745                }
12746             }
12747             break;
12748 
12749          case PRI_EVENT_INFO_RECEIVED:
12750             chanpos = pri_find_principle(pri, e->ring.channel);
12751             if (chanpos < 0) {
12752                ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
12753                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12754             } else {
12755                chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
12756                if (chanpos > -1) {
12757                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
12758                   /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
12759                   if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
12760                      /* how to do that */
12761                      int digitlen = strlen(e->ring.callednum);
12762                      char digit;
12763                      int i;
12764                      for (i = 0; i < digitlen; i++) {
12765                         digit = e->ring.callednum[i];
12766                         {
12767                            struct ast_frame f = { AST_FRAME_DTMF, digit, };
12768                            dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
12769                         }
12770                      }
12771                   }
12772                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12773                }
12774             }
12775             break;
12776          case PRI_EVENT_RING:
12777             crv = NULL;
12778             if (e->ring.channel == -1)
12779                chanpos = pri_find_empty_chan(pri, 1);
12780             else
12781                chanpos = pri_find_principle(pri, e->ring.channel);
12782             /* if no channel specified find one empty */
12783             if (chanpos < 0) {
12784                ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
12785                   PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12786             } else {
12787                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12788                if (pri->pvts[chanpos]->owner) {
12789                   if (pri->pvts[chanpos]->call == e->ring.call) {
12790                      ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
12791                         PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12792                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12793                      break;
12794                   } else {
12795                      /* This is where we handle initial glare */
12796                      ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n",
12797                      PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
12798                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12799                      chanpos = -1;
12800                   }
12801                }
12802                if (chanpos > -1)
12803                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12804             }
12805             if ((chanpos < 0) && (e->ring.flexible))
12806                chanpos = pri_find_empty_chan(pri, 1);
12807             if (chanpos > -1) {
12808                ast_mutex_lock(&pri->pvts[chanpos]->lock);
12809                if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
12810                   /* Should be safe to lock CRV AFAIK while bearer is still locked */
12811                   crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
12812                   if (crv)
12813                      ast_mutex_lock(&crv->lock);
12814                   if (!crv || crv->owner) {
12815                      pri->pvts[chanpos]->call = NULL;
12816                      if (crv) {
12817                         if (crv->owner)
12818                            crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
12819                         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);
12820                      } else
12821                         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);
12822                      pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
12823                      if (crv)
12824                         ast_mutex_unlock(&crv->lock);
12825                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
12826                      break;
12827                   }
12828                }
12829                pri->pvts[chanpos]->call = e->ring.call;
12830                apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
12831                if (pri->pvts[chanpos]->use_callerid) {
12832                   ast_shrink_phone_number(plancallingnum);
12833                   ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
12834 #ifdef PRI_ANI
12835                   if (!ast_strlen_zero(e->ring.callingani)) {
12836                      apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
12837                      ast_shrink_phone_number(plancallingani);
12838                      ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
12839                   } else {
12840                      pri->pvts[chanpos]->cid_ani[0] = '\0';
12841                   }
12842 #endif
12843                   ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
12844                   pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
12845                } else {
12846                   pri->pvts[chanpos]->cid_num[0] = '\0';
12847                   pri->pvts[chanpos]->cid_ani[0] = '\0';
12848                   pri->pvts[chanpos]->cid_name[0] = '\0';
12849                   pri->pvts[chanpos]->cid_ton = 0;
12850                }
12851                apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
12852                   e->ring.redirectingnum, e->ring.callingplanrdnis);
12853                /* If immediate=yes go to s|1 */
12854                if (pri->pvts[chanpos]->immediate) {
12855                   ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
12856                   pri->pvts[chanpos]->exten[0] = 's';
12857                   pri->pvts[chanpos]->exten[1] = '\0';
12858                }
12859                /* Get called number */
12860                else if (!ast_strlen_zero(e->ring.callednum)) {
12861                   ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
12862                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12863                } else if (pri->overlapdial)
12864                   pri->pvts[chanpos]->exten[0] = '\0';
12865                else {
12866                   /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
12867                   pri->pvts[chanpos]->exten[0] = 's';
12868                   pri->pvts[chanpos]->exten[1] = '\0';
12869                }
12870                /* Set DNID on all incoming calls -- even immediate */
12871                if (!ast_strlen_zero(e->ring.callednum))
12872                   ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
12873                /* No number yet, but received "sending complete"? */
12874                if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
12875                   ast_verb(3, "Going to extension s|1 because of Complete received\n");
12876                   pri->pvts[chanpos]->exten[0] = 's';
12877                   pri->pvts[chanpos]->exten[1] = '\0';
12878                }
12879 
12880                /* Make sure extension exists (or in overlap dial mode, can exist) */
12881                if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
12882                   ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12883                   /* Setup law */
12884                   int law;
12885                   if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
12886                      /* Set to audio mode at this point */
12887                      law = 1;
12888                      if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
12889                         ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
12890                   }
12891                   if (e->ring.layer1 == PRI_LAYER_1_ALAW)
12892                      law = DAHDI_LAW_ALAW;
12893                   else
12894                      law = DAHDI_LAW_MULAW;
12895                   res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
12896                   if (res < 0)
12897                      ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
12898                   res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
12899                   if (res < 0)
12900                      ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
12901                   if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
12902                      /* Just announce proceeding */
12903                      pri->pvts[chanpos]->proceeding = 1;
12904                      pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
12905                   } else {
12906                      if (pri->switchtype != PRI_SWITCH_GR303_TMC)
12907                         pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12908                      else
12909                         pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
12910                   }
12911                   /* Get the use_callingpres state */
12912                   pri->pvts[chanpos]->callingpres = e->ring.callingpres;
12913 
12914                   /* Start PBX */
12915                   if (!e->ring.complete
12916                      && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
12917                      && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
12918                      /*
12919                       * Release the PRI lock while we create the channel
12920                       * so other threads can send D channel messages.
12921                       */
12922                      ast_mutex_unlock(&pri->lock);
12923                      if (crv) {
12924                         /* Set bearer and such */
12925                         pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
12926                         c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12927                         pri->pvts[chanpos]->owner = &inuse;
12928                         ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
12929                      } else {
12930                         c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
12931                      }
12932                      ast_mutex_lock(&pri->lock);
12933                      if (c) {
12934                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12935                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12936                         }
12937                         if (e->ring.ani2 >= 0) {
12938                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12939                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12940                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12941                         }
12942 
12943 #ifdef SUPPORT_USERUSER
12944                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
12945                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
12946                         }
12947 #endif
12948 
12949                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
12950                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
12951                         if (e->ring.redirectingreason >= 0)
12952                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
12953                      }
12954                      if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
12955                         ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
12956                            plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
12957                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
12958                      } else {
12959                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
12960                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
12961                         if (c)
12962                            ast_hangup(c);
12963                         else {
12964                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
12965                            pri->pvts[chanpos]->call = NULL;
12966                         }
12967                      }
12968                   } else {
12969                      /*
12970                       * Release the PRI lock while we create the channel
12971                       * so other threads can send D channel messages.
12972                       */
12973                      ast_mutex_unlock(&pri->lock);
12974                      c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
12975                      ast_mutex_lock(&pri->lock);
12976                      if (c) {
12977                         /*
12978                          * It is reasonably safe to set the following
12979                          * channel variables while the PRI and DAHDI private
12980                          * structures are locked.  The PBX has not been
12981                          * started yet and it is unlikely that any other task
12982                          * will do anything with the channel we have just
12983                          * created.
12984                          */
12985                         if (!ast_strlen_zero(e->ring.callingsubaddr)) {
12986                            pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
12987                         }
12988                         if (e->ring.ani2 >= 0) {
12989                            snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
12990                            pbx_builtin_setvar_helper(c, "ANI2", ani2str);
12991                            pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
12992                         }
12993 
12994 #ifdef SUPPORT_USERUSER
12995                         if (!ast_strlen_zero(e->ring.useruserinfo)) {
12996                            pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
12997                         }
12998 #endif
12999 
13000                         if (e->ring.redirectingreason >= 0)
13001                            pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
13002 
13003                         snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
13004                         pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
13005                      }
13006                      if (c && !ast_pbx_start(c)) {
13007                         ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
13008                            plancallingnum, pri->pvts[chanpos]->exten,
13009                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13010 
13011                         dahdi_enable_ec(pri->pvts[chanpos]);
13012                      } else {
13013                         ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
13014                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
13015                         if (c) {
13016                            ast_hangup(c);
13017                         } else {
13018                            pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
13019                            pri->pvts[chanpos]->call = NULL;
13020                         }
13021                      }
13022                   }
13023                } else {
13024                   ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
13025                      pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
13026                      pri->pvts[chanpos]->prioffset, pri->span);
13027                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
13028                   pri->pvts[chanpos]->call = NULL;
13029                   pri->pvts[chanpos]->exten[0] = '\0';
13030                }
13031                if (crv)
13032                   ast_mutex_unlock(&crv->lock);
13033                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13034             } else {
13035                if (e->ring.flexible)
13036                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
13037                else
13038                   pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
13039             }
13040             break;
13041          case PRI_EVENT_RINGING:
13042             chanpos = pri_find_principle(pri, e->ringing.channel);
13043             if (chanpos < 0) {
13044                ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
13045                   PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13046             } else {
13047                chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
13048                if (chanpos < 0) {
13049                   ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
13050                      PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
13051                } else {
13052                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13053                   if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13054                      dahdi_enable_ec(pri->pvts[chanpos]);
13055                      pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
13056                      pri->pvts[chanpos]->alerting = 1;
13057                   } else
13058                      ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
13059 
13060                   if (
13061 #ifdef PRI_PROGRESS_MASK
13062                      e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
13063 #else
13064                      e->ringing.progress == 8
13065 #endif
13066                      ) {
13067                      /* Now we can do call progress detection */
13068                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13069                         /* RINGING detection isn't required because we got ALERTING signal */
13070                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
13071                         pri->pvts[chanpos]->dsp_features = 0;
13072                      }
13073                   }
13074 
13075 #ifdef SUPPORT_USERUSER
13076                   if (!ast_strlen_zero(e->ringing.useruserinfo)) {
13077                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13078                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13079                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
13080                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13081                   }
13082 #endif
13083 
13084                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13085                }
13086             }
13087             break;
13088          case PRI_EVENT_PROGRESS:
13089             /* Get chan value if e->e is not PRI_EVNT_RINGING */
13090             chanpos = pri_find_principle(pri, e->proceeding.channel);
13091             if (chanpos > -1) {
13092                if ((!pri->pvts[chanpos]->progress)
13093 #ifdef PRI_PROGRESS_MASK
13094                   || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
13095 #else
13096                   || (e->proceeding.progress == 8)
13097 #endif
13098                   ) {
13099                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
13100 
13101                   if (e->proceeding.cause > -1) {
13102                      ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
13103 
13104                      /* Work around broken, out of spec USER_BUSY cause in a progress message */
13105                      if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
13106                         if (pri->pvts[chanpos]->owner) {
13107                            ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
13108 
13109                            pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
13110                            f.subclass = AST_CONTROL_BUSY;
13111                         }
13112                      }
13113                   }
13114 
13115                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13116                   ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
13117                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13118                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13119                   if (
13120 #ifdef PRI_PROGRESS_MASK
13121                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13122 #else
13123                      e->proceeding.progress == 8
13124 #endif
13125                      ) {
13126                      /* Now we can do call progress detection */
13127                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13128                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13129                         pri->pvts[chanpos]->dsp_features = 0;
13130                      }
13131                      /* Bring voice path up */
13132                      f.subclass = AST_CONTROL_PROGRESS;
13133                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13134                   }
13135                   pri->pvts[chanpos]->progress = 1;
13136                   pri->pvts[chanpos]->dialing = 0;
13137                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13138                }
13139             }
13140             break;
13141          case PRI_EVENT_PROCEEDING:
13142             chanpos = pri_find_principle(pri, e->proceeding.channel);
13143             if (chanpos > -1) {
13144                if (!pri->pvts[chanpos]->proceeding) {
13145                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
13146 
13147                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13148                   ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
13149                      pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
13150                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13151                   if (
13152 #ifdef PRI_PROGRESS_MASK
13153                      e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
13154 #else
13155                      e->proceeding.progress == 8
13156 #endif
13157                      ) {
13158                      /* Now we can do call progress detection */
13159                      if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13160                         ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13161                         pri->pvts[chanpos]->dsp_features = 0;
13162                      }
13163                      /* Bring voice path up */
13164                      f.subclass = AST_CONTROL_PROGRESS;
13165                      dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13166                   }
13167                   pri->pvts[chanpos]->proceeding = 1;
13168                   pri->pvts[chanpos]->dialing = 0;
13169                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13170                }
13171             }
13172             break;
13173          case PRI_EVENT_FACNAME:
13174             chanpos = pri_find_principle(pri, e->facname.channel);
13175             if (chanpos < 0) {
13176                ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
13177                   PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13178             } else {
13179                chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
13180                if (chanpos < 0) {
13181                   ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
13182                      PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
13183                } else {
13184                   /* Re-use *69 field for PRI */
13185                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13186                   ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
13187                   ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
13188                   pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
13189                   dahdi_enable_ec(pri->pvts[chanpos]);
13190                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13191                }
13192             }
13193             break;
13194          case PRI_EVENT_ANSWER:
13195             chanpos = pri_find_principle(pri, e->answer.channel);
13196             if (chanpos < 0) {
13197                ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
13198                   PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13199             } else {
13200                chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
13201                if (chanpos < 0) {
13202                   ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
13203                      PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
13204                } else {
13205                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13206                   /* Now we can do call progress detection */
13207 
13208                   /* We changed this so it turns on the DSP no matter what... progress or no progress.
13209                    * By this time, we need DTMF detection and other features that were previously disabled
13210                    * -- Matt F */
13211                   if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
13212                      ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
13213                      pri->pvts[chanpos]->dsp_features = 0;
13214                   }
13215                   if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
13216                      ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
13217                      x = DAHDI_START;
13218                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
13219                      if (res < 0) {
13220                         if (errno != EINPROGRESS) {
13221                            ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
13222                         }
13223                      }
13224                   } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
13225                      pri->pvts[chanpos]->dialing = 1;
13226                      /* Send any "w" waited stuff */
13227                      res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
13228                      if (res < 0) {
13229                         ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
13230                         pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13231                      } else
13232                         ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
13233 
13234                      pri->pvts[chanpos]->dop.dialstr[0] = '\0';
13235                   } else if (pri->pvts[chanpos]->confirmanswer) {
13236                      ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
13237                   } else {
13238                      pri->pvts[chanpos]->dialing = 0;
13239                      pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
13240                      /* Enable echo cancellation if it's not on already */
13241                      dahdi_enable_ec(pri->pvts[chanpos]);
13242                   }
13243 
13244 #ifdef SUPPORT_USERUSER
13245                   if (!ast_strlen_zero(e->answer.useruserinfo)) {
13246                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13247                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13248                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
13249                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13250                   }
13251 #endif
13252 
13253                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13254                }
13255             }
13256             break;
13257          case PRI_EVENT_HANGUP:
13258             chanpos = pri_find_principle(pri, e->hangup.channel);
13259             if (chanpos < 0) {
13260                ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
13261                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13262             } else {
13263                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13264                if (chanpos > -1) {
13265                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13266                   if (!pri->pvts[chanpos]->alreadyhungup) {
13267                      /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
13268                      pri->pvts[chanpos]->alreadyhungup = 1;
13269                      if (pri->pvts[chanpos]->realcall)
13270                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13271                      else if (pri->pvts[chanpos]->owner) {
13272                         /* Queue a BUSY instead of a hangup if our cause is appropriate */
13273                         pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13274                         switch (pri->pvts[chanpos]->owner->_state) {
13275                         case AST_STATE_BUSY:
13276                         case AST_STATE_UP:
13277                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13278                            break;
13279                         default:
13280                            switch (e->hangup.cause) {
13281                            case PRI_CAUSE_USER_BUSY:
13282                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13283                               break;
13284                            case PRI_CAUSE_CALL_REJECTED:
13285                            case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13286                            case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13287                            case PRI_CAUSE_SWITCH_CONGESTION:
13288                            case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13289                            case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13290                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13291                               break;
13292                            default:
13293                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13294                            }
13295                            break;
13296                         }
13297                      }
13298                      ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
13299                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
13300                   } else {
13301                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13302                      pri->pvts[chanpos]->call = NULL;
13303                   }
13304                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13305                      ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
13306                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13307                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13308                      pri->pvts[chanpos]->resetting = 1;
13309                   }
13310                   if (e->hangup.aoc_units > -1)
13311                      ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13312                            pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13313 
13314 #ifdef SUPPORT_USERUSER
13315                   if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
13316                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13317                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13318                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13319                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13320                   }
13321 #endif
13322 
13323                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13324                } else {
13325                   ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
13326                      PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13327                }
13328             }
13329             break;
13330 #ifndef PRI_EVENT_HANGUP_REQ
13331 #error please update libpri
13332 #endif
13333          case PRI_EVENT_HANGUP_REQ:
13334             chanpos = pri_find_principle(pri, e->hangup.channel);
13335             if (chanpos < 0) {
13336                ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
13337                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13338             } else {
13339                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13340                if (chanpos > -1) {
13341                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13342                   if (pri->pvts[chanpos]->realcall)
13343                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13344                   else if (pri->pvts[chanpos]->owner) {
13345                      pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
13346                      switch (pri->pvts[chanpos]->owner->_state) {
13347                      case AST_STATE_BUSY:
13348                      case AST_STATE_UP:
13349                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13350                         break;
13351                      default:
13352                         switch (e->hangup.cause) {
13353                         case PRI_CAUSE_USER_BUSY:
13354                            pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
13355                            break;
13356                         case PRI_CAUSE_CALL_REJECTED:
13357                         case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
13358                         case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
13359                         case PRI_CAUSE_SWITCH_CONGESTION:
13360                         case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
13361                         case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
13362                            pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
13363                            break;
13364                         default:
13365                            pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13366                            break;
13367                         }
13368                         break;
13369                      }
13370                      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);
13371                      if (e->hangup.aoc_units > -1)
13372                         ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
13373                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
13374                   } else {
13375                      pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
13376                      pri->pvts[chanpos]->call = NULL;
13377                   }
13378                   if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
13379                      ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
13380                            PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13381                      pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
13382                      pri->pvts[chanpos]->resetting = 1;
13383                   }
13384 
13385 #ifdef SUPPORT_USERUSER
13386                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13387                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13388                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13389                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13390                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13391                   }
13392 #endif
13393 
13394                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13395                } else {
13396                   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);
13397                }
13398             }
13399             break;
13400          case PRI_EVENT_HANGUP_ACK:
13401             chanpos = pri_find_principle(pri, e->hangup.channel);
13402             if (chanpos < 0) {
13403                ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
13404                   PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13405             } else {
13406                chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
13407                if (chanpos > -1) {
13408                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13409                   pri->pvts[chanpos]->call = NULL;
13410                   pri->pvts[chanpos]->resetting = 0;
13411                   if (pri->pvts[chanpos]->owner) {
13412                      ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
13413                   }
13414 
13415 #ifdef SUPPORT_USERUSER
13416                   if (!ast_strlen_zero(e->hangup.useruserinfo)) {
13417                      struct ast_channel *owner = pri->pvts[chanpos]->owner;
13418                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13419                      pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
13420                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13421                   }
13422 #endif
13423 
13424                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13425                }
13426             }
13427             break;
13428          case PRI_EVENT_CONFIG_ERR:
13429             ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
13430             break;
13431          case PRI_EVENT_RESTART_ACK:
13432             chanpos = pri_find_principle(pri, e->restartack.channel);
13433             if (chanpos < 0) {
13434                /* Sometime switches (e.g. I421 / British Telecom) don't give us the
13435                   channel number, so we have to figure it out...  This must be why
13436                   everybody resets exactly a channel at a time. */
13437                for (x = 0; x < pri->numchans; x++) {
13438                   if (pri->pvts[x] && pri->pvts[x]->resetting) {
13439                      chanpos = x;
13440                      ast_mutex_lock(&pri->pvts[chanpos]->lock);
13441                      ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
13442                         pri->pvts[chanpos]->prioffset, pri->span);
13443                      if (pri->pvts[chanpos]->realcall)
13444                         pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13445                      else if (pri->pvts[chanpos]->owner) {
13446                         ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
13447                            pri->pvts[chanpos]->prioffset, pri->span);
13448                         pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13449                      }
13450                      pri->pvts[chanpos]->resetting = 0;
13451                      ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13452                            pri->pvts[chanpos]->prioffset, pri->span);
13453                      ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13454                      if (pri->resetting)
13455                         pri_check_restart(pri);
13456                      break;
13457                   }
13458                }
13459                if (chanpos < 0) {
13460                   ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
13461                      PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13462                }
13463             } else {
13464                if (pri->pvts[chanpos]) {
13465                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13466                   if (pri->pvts[chanpos]->realcall)
13467                      pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
13468                   else if (pri->pvts[chanpos]->owner) {
13469                      ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
13470                         PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
13471                      pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
13472                   }
13473                   pri->pvts[chanpos]->resetting = 0;
13474                   pri->pvts[chanpos]->inservice = 1;
13475                   ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
13476                            pri->pvts[chanpos]->prioffset, pri->span);
13477                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13478                   if (pri->resetting)
13479                      pri_check_restart(pri);
13480                }
13481             }
13482             break;
13483          case PRI_EVENT_SETUP_ACK:
13484             chanpos = pri_find_principle(pri, e->setup_ack.channel);
13485             if (chanpos < 0) {
13486                ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
13487                   PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
13488             } else {
13489                chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
13490                if (chanpos > -1) {
13491                   ast_mutex_lock(&pri->pvts[chanpos]->lock);
13492                   pri->pvts[chanpos]->setup_ack = 1;
13493                   /* Send any queued digits */
13494                   for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
13495                      ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
13496                      pri_information(pri->pri, pri->pvts[chanpos]->call,
13497                         pri->pvts[chanpos]->dialdest[x]);
13498                   }
13499                   ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13500                } else
13501                   ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
13502             }
13503             break;
13504          case PRI_EVENT_NOTIFY:
13505             chanpos = pri_find_principle(pri, e->notify.channel);
13506             if (chanpos < 0) {
13507                ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
13508                   PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
13509             } else if (!pri->discardremoteholdretrieval) {
13510                struct ast_frame f = { AST_FRAME_CONTROL, };
13511                ast_mutex_lock(&pri->pvts[chanpos]->lock);
13512                switch (e->notify.info) {
13513                case PRI_NOTIFY_REMOTE_HOLD:
13514                   f.subclass = AST_CONTROL_HOLD;
13515                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13516                   break;
13517                case PRI_NOTIFY_REMOTE_RETRIEVAL:
13518                   f.subclass = AST_CONTROL_UNHOLD;
13519                   dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
13520                   break;
13521                }
13522                ast_mutex_unlock(&pri->pvts[chanpos]->lock);
13523             }
13524             break;
13525          default:
13526             ast_debug(1, "Event: %d\n", e->e);
13527          }
13528       }
13529       ast_mutex_unlock(&pri->lock);
13530    }
13531    /* Never reached */
13532    return NULL;
13533 }

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

Definition at line 12033 of file chan_dahdi.c.

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

Referenced by pri_dchannel().

12034 {
12035    struct dahdi_pvt *p;
12036    p = pri->crvs;
12037    while (p) {
12038       if (p->channel == crv)
12039          return p;
12040       p = p->next;
12041    }
12042    return NULL;
12043 }

static int pri_find_dchan ( struct dahdi_pri pri  )  [static]

Definition at line 4140 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, dahdi_pri::pri, dahdi_pri::sig, and SIG_BRI_PTMP.

Referenced by pri_dchannel().

04141 {
04142    int oldslot = -1;
04143    struct pri *old;
04144    int newslot = -1;
04145    int x;
04146    old = pri->pri;
04147    for (x = 0; x < NUM_DCHANS; x++) {
04148       if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
04149          newslot = x;
04150       if (pri->dchans[x] == old) {
04151          oldslot = x;
04152       }
04153    }
04154    if (newslot < 0) {
04155       newslot = 0;
04156       /* This is annoying to see on non persistent layer 2 connections.  Let's not complain in that case */
04157       if (pri->sig != SIG_BRI_PTMP) {
04158          ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
04159             pri->dchannels[newslot]);
04160       }
04161    }
04162    if (old && (oldslot != newslot))
04163       ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
04164          pri->dchannels[oldslot], pri->dchannels[newslot]);
04165    pri->pri = pri->dchans[newslot];
04166    return 0;
04167 }

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

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

10809 {
10810    int x;
10811    if (backwards)
10812       x = pri->numchans;
10813    else
10814       x = 0;
10815    for (;;) {
10816       if (backwards && (x < 0))
10817          break;
10818       if (!backwards && (x >= pri->numchans))
10819          break;
10820       if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
10821          ast_debug(1, "Found empty available channel %d/%d\n",
10822             pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
10823          return x;
10824       }
10825       if (backwards)
10826          x--;
10827       else
10828          x++;
10829    }
10830    return -1;
10831 }

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

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

12048 {
12049    int x;
12050    int span = PRI_SPAN(channel);
12051    int spanfd;
12052    struct dahdi_params param;
12053    int principle = -1;
12054    int explicit = PRI_EXPLICIT(channel);
12055    channel = PRI_CHANNEL(channel);
12056 
12057    if (!explicit) {
12058       spanfd = pri_active_dchan_fd(pri);
12059       memset(&param, 0, sizeof(param));
12060       if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
12061          return -1;
12062       span = pris[param.spanno - 1].prilogicalspan;
12063    }
12064 
12065    for (x = 0; x < pri->numchans; x++) {
12066       if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
12067          principle = x;
12068          break;
12069       }
12070    }
12071 
12072    return principle;
12073 }

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

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

12078 {
12079    int x;
12080    struct dahdi_pvt *crv;
12081    if (!c) {
12082       if (principle < 0)
12083          return -1;
12084       return principle;
12085    }
12086    if ((principle > -1) &&
12087       (principle < pri->numchans) &&
12088       (pri->pvts[principle]) &&
12089       (pri->pvts[principle]->call == c))
12090       return principle;
12091    /* First, check for other bearers */
12092    for (x = 0; x < pri->numchans; x++) {
12093       if (!pri->pvts[x])
12094          continue;
12095       if (pri->pvts[x]->call == c) {
12096          /* Found our call */
12097          if (principle != x) {
12098             struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
12099 
12100             ast_verb(3, "Moving call from channel %d to channel %d\n",
12101                 old->channel, new->channel);
12102             if (new->owner) {
12103                ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
12104                   old->channel, new->channel, new->channel);
12105                return -1;
12106             }
12107             /* Fix it all up now */
12108             new->owner = old->owner;
12109             old->owner = NULL;
12110             if (new->owner) {
12111                ast_string_field_build(new->owner, name,
12112                   "DAHDI/%d:%d-%d", pri->trunkgroup,
12113                   new->channel, 1);
12114                new->owner->tech_pvt = new;
12115                ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
12116                new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
12117                old->subs[SUB_REAL].owner = NULL;
12118             } else
12119                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);
12120             new->call = old->call;
12121             old->call = NULL;
12122 
12123             /* Copy any DSP that may be present */
12124             new->dsp = old->dsp;
12125             new->dsp_features = old->dsp_features;
12126             old->dsp = NULL;
12127             old->dsp_features = 0;
12128          }
12129          return principle;
12130       }
12131    }
12132    /* Now check for a CRV with no bearer */
12133    crv = pri->crvs;
12134    while (crv) {
12135       if (crv->call == c) {
12136          /* This is our match...  Perform some basic checks */
12137          if (crv->bearer)
12138             ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
12139          else if (pri->pvts[principle]->owner)
12140             ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
12141          else {
12142             /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
12143                wakeup the potential sleeper */
12144             dahdi_close_sub(crv, SUB_REAL);
12145             pri->pvts[principle]->call = crv->call;
12146             pri_assign_bearer(crv, pri, pri->pvts[principle]);
12147             ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
12148                pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
12149                pri->trunkgroup, crv->channel);
12150             wakeup_sub(crv, SUB_REAL, pri);
12151          }
12152          return principle;
12153       }
12154       crv = crv->next;
12155    }
12156    ast_log(LOG_WARNING, "Call specified, but not found?\n");
12157    return -1;
12158 }

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

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

01432 {
01433    int res;
01434    /* Grab the lock first */
01435    do {
01436       res = ast_mutex_trylock(&pri->lock);
01437       if (res) {
01438          DEADLOCK_AVOIDANCE(&pvt->lock);
01439       }
01440    } while (res);
01441    /* Then break the poll */
01442    if (pri->master != AST_PTHREADT_NULL)
01443       pthread_kill(pri->master, SIGURG);
01444    return 0;
01445 }

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

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

12319 {
12320    int x;
12321    int redo;
12322    ast_mutex_unlock(&pri->lock);
12323    ast_mutex_lock(&p->lock);
12324    do {
12325       redo = 0;
12326       for (x = 0; x < 3; x++) {
12327          while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
12328             redo++;
12329             DEADLOCK_AVOIDANCE(&p->lock);
12330          }
12331          if (p->subs[x].owner) {
12332             ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
12333             ast_channel_unlock(p->subs[x].owner);
12334          }
12335       }
12336    } while (redo);
12337    ast_mutex_unlock(&p->lock);
12338    ast_mutex_lock(&pri->lock);
12339    return 0;
12340 }

static int pri_is_up ( struct dahdi_pri pri  )  [static]

Definition at line 4080 of file chan_dahdi.c.

References DCHAN_AVAILABLE, dahdi_pri::dchanavail, and NUM_DCHANS.

Referenced by mkintf(), and pri_dchannel().

04081 {
04082    int x;
04083    for (x = 0; x < NUM_DCHANS; x++) {
04084       if (pri->dchanavail[x] == DCHAN_AVAILABLE)
04085          return 1;
04086    }
04087    return 0;
04088 }

static char* pri_order ( int  level  )  [static]

Definition at line 4107 of file chan_dahdi.c.

Referenced by handle_pri_show_span(), and pri_dchannel().

04108 {
04109    switch (level) {
04110    case 0:
04111       return "Primary";
04112    case 1:
04113       return "Secondary";
04114    case 2:
04115       return "Tertiary";
04116    case 3:
04117       return "Quaternary";
04118    default:
04119       return "<Unknown>";
04120    }
04121 }

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

09733 {
09734    int x;
09735    int trunkgroup;
09736    /* Get appropriate trunk group if there is one */
09737    trunkgroup = pris[*span].mastertrunkgroup;
09738    if (trunkgroup) {
09739       /* Select a specific trunk group */
09740       for (x = 0; x < NUM_SPANS; x++) {
09741          if (pris[x].trunkgroup == trunkgroup) {
09742             *span = x;
09743             return 0;
09744          }
09745       }
09746       ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
09747       *span = -1;
09748    } else {
09749       if (pris[*span].trunkgroup) {
09750          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
09751          *span = -1;
09752       } else if (pris[*span].mastertrunkgroup) {
09753          ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
09754          *span = -1;
09755       } else {
09756          if (si->totalchans == 31) {
09757             /* E1 */
09758             pris[*span].dchannels[0] = 16 + offset;
09759          } else if (si->totalchans == 24) {
09760             /* T1 or J1 */
09761             pris[*span].dchannels[0] = 24 + offset;
09762          } else if (si->totalchans == 3) {
09763             /* BRI */
09764             pris[*span].dchannels[0] = 3 + offset;
09765          } else {
09766             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);
09767             *span = -1;
09768             return 0;
09769          }
09770          pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
09771          pris[*span].offset = offset;
09772          pris[*span].span = *span + 1;
09773       }
09774    }
09775    return 0;
09776 }

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

Definition at line 16096 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_MAX_EXTENSION, 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_CHAN_MAPPING_LOGICAL, DAHDI_CHAN_MAPPING_PHYSICAL, DAHDI_OVERLAPDIAL_BOTH, DAHDI_OVERLAPDIAL_INCOMING, DAHDI_OVERLAPDIAL_NONE, DAHDI_OVERLAPDIAL_OUTGOING, dahdi_pvt::dahditrcallerid, dahdi_pri::dialplan, dahdi_pri::discardremoteholdretrieval, dahdi_pvt::drings, DSP_DIGITMODE_RELAXDTMF, dahdi_pvt::dtmfrelax, dahdi_pvt::echocanbridged, dahdi_pvt::echotraining, errno, dahdi_pri::facilityenable, dahdi_pvt::faxbuf_no, dahdi_pvt::faxbuf_policy, 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_pri::qsigchannelmapping, 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_MFCR2, 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(), dahdi_pvt::stripmsd, 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, dahdi_pvt::usefaxbuffers, ast_variable::value, dahdi_pvt::vars, and dahdi_pvt::waitfordialtone.

Referenced by setup_dahdi().

16097 {
16098    struct dahdi_pvt *tmp;
16099    int y;
16100    int found_pseudo = 0;
16101    char dahdichan[MAX_CHANLIST_LEN] = {};
16102 
16103    for (; v; v = v->next) {
16104       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
16105          continue;
16106 
16107       /* must have parkinglot in confp before build_channels is called */
16108       if (!strcasecmp(v->name, "parkinglot")) {
16109          ast_copy_string(confp->chan.parkinglot, v->value, sizeof(confp->chan.parkinglot));
16110       }
16111 
16112       /* Create the interface list */
16113       if (!strcasecmp(v->name, "channel")
16114 #ifdef HAVE_PRI
16115          || !strcasecmp(v->name, "crv")
16116 #endif
16117          ) {
16118          int iscrv;
16119          if (options & PROC_DAHDI_OPT_NOCHAN) {
16120             ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
16121             continue;
16122          }
16123          iscrv = !strcasecmp(v->name, "crv");
16124          if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
16125                return -1;
16126          ast_log(LOG_DEBUG, "Channel '%s' configured.\n", v->value);
16127       } else if (!strcasecmp(v->name, "buffers")) {
16128          int res;
16129          char policy[21] = "";
16130 
16131          res = sscanf(v->value, "%30d,%20s", &confp->chan.buf_no, policy);
16132          if (res != 2) {
16133             ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
16134             confp->chan.buf_no = numbufs;
16135             continue;
16136          }
16137          if (confp->chan.buf_no < 0)
16138             confp->chan.buf_no = numbufs;
16139          if (!strcasecmp(policy, "full")) {
16140             confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
16141          } else if (!strcasecmp(policy, "immediate")) {
16142             confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
16143 #ifdef HAVE_DAHDI_HALF_FULL
16144          } else if (!strcasecmp(policy, "half_full")) {
16145             confp->chan.buf_policy = DAHDI_POLICY_HALF_FULL;
16146 #endif
16147          } else {
16148             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16149          }
16150       } else if (!strcasecmp(v->name, "faxbuffers")) {
16151          int res;
16152          char policy[21] = "";
16153 
16154          res = sscanf(v->value, "%30d,%20s", &confp->chan.faxbuf_no, policy);
16155          if (res != 2) {
16156             ast_log(LOG_WARNING, "Parsing faxbuffers option data failed, using defaults.\n");
16157             confp->chan.faxbuf_no = numbufs;
16158             continue;
16159          }
16160          confp->chan.usefaxbuffers = 1;
16161          if (confp->chan.faxbuf_no < 0)
16162             confp->chan.faxbuf_no = numbufs;
16163          if (!strcasecmp(policy, "full")) {
16164             confp->chan.faxbuf_policy = DAHDI_POLICY_WHEN_FULL;
16165          } else if (!strcasecmp(policy, "immediate")) {
16166             confp->chan.faxbuf_policy = DAHDI_POLICY_IMMEDIATE;
16167          } else {
16168             ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
16169             confp->chan.usefaxbuffers = 0;
16170          }
16171       } else if (!strcasecmp(v->name, "dahdichan")) {
16172          ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
16173       } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
16174          usedistinctiveringdetection = ast_true(v->value);
16175       } else if (!strcasecmp(v->name, "distinctiveringaftercid")) {
16176          distinctiveringaftercid = ast_true(v->value);
16177       } else if (!strcasecmp(v->name, "dring1context")) {
16178          ast_copy_string(confp->chan.drings.ringContext[0].contextData,v->value,sizeof(confp->chan.drings.ringContext[0].contextData));
16179       } else if (!strcasecmp(v->name, "dring2context")) {
16180          ast_copy_string(confp->chan.drings.ringContext[1].contextData,v->value,sizeof(confp->chan.drings.ringContext[1].contextData));
16181       } else if (!strcasecmp(v->name, "dring3context")) {
16182          ast_copy_string(confp->chan.drings.ringContext[2].contextData,v->value,sizeof(confp->chan.drings.ringContext[2].contextData));
16183       } else if (!strcasecmp(v->name, "dring1range")) {
16184          confp->chan.drings.ringnum[0].range = atoi(v->value);
16185       } else if (!strcasecmp(v->name, "dring2range")) {
16186          confp->chan.drings.ringnum[1].range = atoi(v->value);
16187       } else if (!strcasecmp(v->name, "dring3range")) {
16188          confp->chan.drings.ringnum[2].range = atoi(v->value);
16189       } else if (!strcasecmp(v->name, "dring1")) {
16190          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]);
16191       } else if (!strcasecmp(v->name, "dring2")) {
16192          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]);
16193       } else if (!strcasecmp(v->name, "dring3")) {
16194          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]);
16195       } else if (!strcasecmp(v->name, "usecallerid")) {
16196          confp->chan.use_callerid = ast_true(v->value);
16197       } else if (!strcasecmp(v->name, "cidsignalling")) {
16198          if (!strcasecmp(v->value, "bell"))
16199             confp->chan.cid_signalling = CID_SIG_BELL;
16200          else if (!strcasecmp(v->value, "v23"))
16201             confp->chan.cid_signalling = CID_SIG_V23;
16202          else if (!strcasecmp(v->value, "dtmf"))
16203             confp->chan.cid_signalling = CID_SIG_DTMF;
16204          else if (!strcasecmp(v->value, "smdi"))
16205             confp->chan.cid_signalling = CID_SIG_SMDI;
16206          else if (!strcasecmp(v->value, "v23_jp"))
16207             confp->chan.cid_signalling = CID_SIG_V23_JP;
16208          else if (ast_true(v->value))
16209             confp->chan.cid_signalling = CID_SIG_BELL;
16210       } else if (!strcasecmp(v->name, "cidstart")) {
16211          if (!strcasecmp(v->value, "ring"))
16212             confp->chan.cid_start = CID_START_RING;
16213          else if (!strcasecmp(v->value, "polarity_in"))
16214             confp->chan.cid_start = CID_START_POLARITY_IN;
16215          else if (!strcasecmp(v->value, "polarity"))
16216             confp->chan.cid_start = CID_START_POLARITY;
16217          else if (ast_true(v->value))
16218             confp->chan.cid_start = CID_START_RING;
16219       } else if (!strcasecmp(v->name, "threewaycalling")) {
16220          confp->chan.threewaycalling = ast_true(v->value);
16221       } else if (!strcasecmp(v->name, "cancallforward")) {
16222          confp->chan.cancallforward = ast_true(v->value);
16223       } else if (!strcasecmp(v->name, "relaxdtmf")) {
16224          if (ast_true(v->value))
16225             confp->chan.dtmfrelax = DSP_DIGITMODE_RELAXDTMF;
16226          else
16227             confp->chan.dtmfrelax = 0;
16228       } else if (!strcasecmp(v->name, "mailbox")) {
16229          ast_copy_string(confp->chan.mailbox, v->value, sizeof(confp->chan.mailbox));
16230       } else if (!strcasecmp(v->name, "hasvoicemail")) {
16231          if (ast_true(v->value) && ast_strlen_zero(confp->chan.mailbox)) {
16232             ast_copy_string(confp->chan.mailbox, cat, sizeof(confp->chan.mailbox));
16233          }
16234       } else if (!strcasecmp(v->name, "adsi")) {
16235          confp->chan.adsi = ast_true(v->value);
16236       } else if (!strcasecmp(v->name, "usesmdi")) {
16237          confp->chan.use_smdi = ast_true(v->value);
16238       } else if (!strcasecmp(v->name, "smdiport")) {
16239          ast_copy_string(confp->smdi_port, v->value, sizeof(confp->smdi_port));
16240       } else if (!strcasecmp(v->name, "transfer")) {
16241          confp->chan.transfer = ast_true(v->value);
16242       } else if (!strcasecmp(v->name, "canpark")) {
16243          confp->chan.canpark = ast_true(v->value);
16244       } else if (!strcasecmp(v->name, "echocancelwhenbridged")) {
16245          confp->chan.echocanbridged = ast_true(v->value);
16246       } else if (!strcasecmp(v->name, "busydetect")) {
16247          confp->chan.busydetect = ast_true(v->value);
16248       } else if (!strcasecmp(v->name, "busycount")) {
16249          confp->chan.busycount = atoi(v->value);
16250       } else if (!strcasecmp(v->name, "busypattern")) {
16251          if (sscanf(v->value, "%30d,%30d", &confp->chan.busy_tonelength, &confp->chan.busy_quietlength) != 2) {
16252             ast_log(LOG_ERROR, "busypattern= expects busypattern=tonelength,quietlength at line %d.\n", v->lineno);
16253          }
16254       } else if (!strcasecmp(v->name, "callprogress")) {
16255          confp->chan.callprogress &= ~CALLPROGRESS_PROGRESS;
16256          if (ast_true(v->value))
16257             confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
16258       } else if (!strcasecmp(v->name, "waitfordialtone")) {
16259          confp->chan.waitfordialtone = atoi(v->value);
16260       } else if (!strcasecmp(v->name, "faxdetect")) {
16261          confp->chan.callprogress &= ~CALLPROGRESS_FAX;
16262          if (!strcasecmp(v->value, "incoming")) {
16263             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING;
16264          } else if (!strcasecmp(v->value, "outgoing")) {
16265             confp->chan.callprogress |= CALLPROGRESS_FAX_OUTGOING;
16266          } else if (!strcasecmp(v->value, "both") || ast_true(v->value))
16267             confp->chan.callprogress |= CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING;
16268       } else if (!strcasecmp(v->name, "echocancel")) {
16269          process_echocancel(confp, v->value, v->lineno);
16270       } else if (!strcasecmp(v->name, "echotraining")) {
16271          if (sscanf(v->value, "%30d", &y) == 1) {
16272             if ((y < 10) || (y > 4000)) {
16273                ast_log(LOG_WARNING, "Echo training time must be within the range of 10 to 4000 ms at line %d.\n", v->lineno);
16274             } else {
16275                confp->chan.echotraining = y;
16276             }
16277          } else if (ast_true(v->value)) {
16278             confp->chan.echotraining = 400;
16279          } else
16280             confp->chan.echotraining = 0;
16281       } else if (!strcasecmp(v->name, "hidecallerid")) {
16282          confp->chan.hidecallerid = ast_true(v->value);
16283       } else if (!strcasecmp(v->name, "hidecalleridname")) {
16284          confp->chan.hidecalleridname = ast_true(v->value);
16285       } else if (!strcasecmp(v->name, "pulsedial")) {
16286          confp->chan.pulse = ast_true(v->value);
16287       } else if (!strcasecmp(v->name, "callreturn")) {
16288          confp->chan.callreturn = ast_true(v->value);
16289       } else if (!strcasecmp(v->name, "callwaiting")) {
16290          confp->chan.callwaiting = ast_true(v->value);
16291       } else if (!strcasecmp(v->name, "callwaitingcallerid")) {
16292          confp->chan.callwaitingcallerid = ast_true(v->value);
16293       } else if (!strcasecmp(v->name, "context")) {
16294          ast_copy_string(confp->chan.context, v->value, sizeof(confp->chan.context));
16295       } else if (!strcasecmp(v->name, "language")) {
16296          ast_copy_string(confp->chan.language, v->value, sizeof(confp->chan.language));
16297       } else if (!strcasecmp(v->name, "progzone")) {
16298          ast_copy_string(progzone, v->value, sizeof(progzone));
16299       } else if (!strcasecmp(v->name, "mohinterpret")
16300          ||!strcasecmp(v->name, "musiconhold") || !strcasecmp(v->name, "musicclass")) {
16301          ast_copy_string(confp->chan.mohinterpret, v->value, sizeof(confp->chan.mohinterpret));
16302       } else if (!strcasecmp(v->name, "mohsuggest")) {
16303          ast_copy_string(confp->chan.mohsuggest, v->value, sizeof(confp->chan.mohsuggest));
16304       } else if (!strcasecmp(v->name, "parkinglot")) {
16305          ast_copy_string(parkinglot, v->value, sizeof(parkinglot));
16306       } else if (!strcasecmp(v->name, "stripmsd")) {
16307          ast_log(LOG_NOTICE, "Configuration option \"%s\" has been deprecated. Please use dialplan instead\n", v->name);
16308          confp->chan.stripmsd = atoi(v->value);
16309       } else if (!strcasecmp(v->name, "jitterbuffers")) {
16310          numbufs = atoi(v->value);
16311       } else if (!strcasecmp(v->name, "group")) {
16312          confp->chan.group = ast_get_group(v->value);
16313       } else if (!strcasecmp(v->name, "callgroup")) {
16314          if (!strcasecmp(v->value, "none"))
16315             confp->chan.callgroup = 0;
16316          else
16317             confp->chan.callgroup = ast_get_group(v->value);
16318       } else if (!strcasecmp(v->name, "pickupgroup")) {
16319          if (!strcasecmp(v->value, "none"))
16320             confp->chan.pickupgroup = 0;
16321          else
16322             confp->chan.pickupgroup = ast_get_group(v->value);
16323       } else if (!strcasecmp(v->name, "setvar")) {
16324          char *varname = ast_strdupa(v->value), *varval = NULL;
16325          struct ast_variable *tmpvar;
16326          if (varname && (varval = strchr(varname, '='))) {
16327             *varval++ = '\0';
16328             if ((tmpvar = ast_variable_new(varname, varval, ""))) {
16329                tmpvar->next = confp->chan.vars;
16330                confp->chan.vars = tmpvar;
16331             }
16332          }
16333       } else if (!strcasecmp(v->name, "immediate")) {
16334          confp->chan.immediate = ast_true(v->value);
16335       } else if (!strcasecmp(v->name, "transfertobusy")) {
16336          confp->chan.transfertobusy = ast_true(v->value);
16337       } else if (!strcasecmp(v->name, "mwimonitor")) {
16338          confp->chan.mwimonitor_neon = 0;
16339          confp->chan.mwimonitor_fsk = 0;
16340          confp->chan.mwimonitor_rpas = 0;
16341          if (strcasestr(v->value, "fsk")) {
16342             confp->chan.mwimonitor_fsk = 1;
16343          }
16344          if (strcasestr(v->value, "rpas")) {
16345             confp->chan.mwimonitor_rpas = 1;
16346          }
16347          if (strcasestr(v->value, "neon")) {
16348             confp->chan.mwimonitor_neon = 1;
16349          }
16350          /* If set to true or yes, assume that simple fsk is desired */
16351          if (ast_true(v->value)) {
16352             confp->chan.mwimonitor_fsk = 1;
16353          }
16354       } else if (!strcasecmp(v->name, "cid_rxgain")) {
16355          if (sscanf(v->value, "%30f", &confp->chan.cid_rxgain) != 1) {
16356             ast_log(LOG_WARNING, "Invalid cid_rxgain: %s at line %d.\n", v->value, v->lineno);
16357          }
16358       } else if (!strcasecmp(v->name, "rxgain")) {
16359          if (sscanf(v->value, "%30f", &confp->chan.rxgain) != 1) {
16360             ast_log(LOG_WARNING, "Invalid rxgain: %s at line %d.\n", v->value, v->lineno);
16361          }
16362       } else if (!strcasecmp(v->name, "txgain")) {
16363          if (sscanf(v->value, "%30f", &confp->chan.txgain) != 1) {
16364             ast_log(LOG_WARNING, "Invalid txgain: %s at line %d.\n", v->value, v->lineno);
16365          }
16366       } else if (!strcasecmp(v->name, "tonezone")) {
16367          if (sscanf(v->value, "%30d", &confp->chan.tonezone) != 1) {
16368             ast_log(LOG_WARNING, "Invalid tonezone: %s at line %d.\n", v->value, v->lineno);
16369          }
16370       } else if (!strcasecmp(v->name, "callerid")) {
16371          if (!strcasecmp(v->value, "asreceived")) {
16372             confp->chan.cid_num[0] = '\0';
16373             confp->chan.cid_name[0] = '\0';
16374          } else {
16375             ast_callerid_split(v->value, confp->chan.cid_name, sizeof(confp->chan.cid_name), confp->chan.cid_num, sizeof(confp->chan.cid_num));
16376          }
16377       } else if (!strcasecmp(v->name, "fullname")) {
16378          ast_copy_string(confp->chan.cid_name, v->value, sizeof(confp->chan.cid_name));
16379       } else if (!strcasecmp(v->name, "cid_number")) {
16380          ast_copy_string(confp->chan.cid_num, v->value, sizeof(confp->chan.cid_num));
16381       } else if (!strcasecmp(v->name, "useincomingcalleridondahditransfer")) {
16382          confp->chan.dahditrcallerid = ast_true(v->value);
16383       } else if (!strcasecmp(v->name, "restrictcid")) {
16384          confp->chan.restrictcid = ast_true(v->value);
16385       } else if (!strcasecmp(v->name, "usecallingpres")) {
16386          confp->chan.use_callingpres = ast_true(v->value);
16387       } else if (!strcasecmp(v->name, "accountcode")) {
16388          ast_copy_string(confp->chan.accountcode, v->value, sizeof(confp->chan.accountcode));
16389       } else if (!strcasecmp(v->name, "amaflags")) {
16390          y = ast_cdr_amaflags2int(v->value);
16391          if (y < 0)
16392             ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d.\n", v->value, v->lineno);
16393          else
16394             confp->chan.amaflags = y;
16395       } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
16396          confp->chan.polarityonanswerdelay = atoi(v->value);
16397       } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
16398          confp->chan.answeronpolarityswitch = ast_true(v->value);
16399       } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
16400          confp->chan.hanguponpolarityswitch = ast_true(v->value);
16401       } else if (!strcasecmp(v->name, "sendcalleridafter")) {
16402          confp->chan.sendcalleridafter = atoi(v->value);
16403       } else if (!strcasecmp(v->name, "mwimonitornotify")) {
16404          ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
16405       } else if (!strcasecmp(v->name, "mwisendtype")) {
16406 #ifndef HAVE_DAHDI_LINEREVERSE_VMWI  /* backward compatibility for older dahdi VMWI implementation */
16407          if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
16408             mwisend_rpas = 1;
16409          } else {
16410             mwisend_rpas = 0;
16411          }
16412 #else
16413          /* Default is fsk, to turn it off you must specify nofsk */
16414          memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
16415          if (strcasestr(v->value, "nofsk")) {      /* NoFSK */
16416             confp->chan.mwisend_fsk = 0;
16417          } else {             /* Default FSK */
16418             confp->chan.mwisend_fsk = 1;
16419          }
16420          if (strcasestr(v->value, "rpas")) {       /* Ring Pulse Alert Signal, normally followed by FSK */
16421             confp->chan.mwisend_rpas = 1;
16422          } else {
16423             confp->chan.mwisend_rpas = 0;
16424          }
16425          if (strcasestr(v->value, "lrev")) {       /* Line Reversal */
16426             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
16427          }
16428          if (strcasestr(v->value, "hvdc")) {       /* HV 90VDC */
16429             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
16430          }
16431          if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){   /* 90V DC pulses */
16432             confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
16433          }
16434 #endif
16435       } else if (reload != 1) {
16436           if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
16437             int orig_radio = confp->chan.radio;
16438             int orig_outsigmod = confp->chan.outsigmod;
16439             int orig_auto = confp->is_sig_auto;
16440 
16441             confp->chan.radio = 0;
16442             confp->chan.outsigmod = -1;
16443             confp->is_sig_auto = 0;
16444             if (!strcasecmp(v->value, "em")) {
16445                confp->chan.sig = SIG_EM;
16446             } else if (!strcasecmp(v->value, "em_e1")) {
16447                confp->chan.sig = SIG_EM_E1;
16448             } else if (!strcasecmp(v->value, "em_w")) {
16449                confp->chan.sig = SIG_EMWINK;
16450             } else if (!strcasecmp(v->value, "fxs_ls")) {
16451                confp->chan.sig = SIG_FXSLS;
16452             } else if (!strcasecmp(v->value, "fxs_gs")) {
16453                confp->chan.sig = SIG_FXSGS;
16454             } else if (!strcasecmp(v->value, "fxs_ks")) {
16455                confp->chan.sig = SIG_FXSKS;
16456             } else if (!strcasecmp(v->value, "fxo_ls")) {
16457                confp->chan.sig = SIG_FXOLS;
16458             } else if (!strcasecmp(v->value, "fxo_gs")) {
16459                confp->chan.sig = SIG_FXOGS;
16460             } else if (!strcasecmp(v->value, "fxo_ks")) {
16461                confp->chan.sig = SIG_FXOKS;
16462             } else if (!strcasecmp(v->value, "fxs_rx")) {
16463                confp->chan.sig = SIG_FXSKS;
16464                confp->chan.radio = 1;
16465             } else if (!strcasecmp(v->value, "fxo_rx")) {
16466                confp->chan.sig = SIG_FXOLS;
16467                confp->chan.radio = 1;
16468             } else if (!strcasecmp(v->value, "fxs_tx")) {
16469                confp->chan.sig = SIG_FXSLS;
16470                confp->chan.radio = 1;
16471             } else if (!strcasecmp(v->value, "fxo_tx")) {
16472                confp->chan.sig = SIG_FXOGS;
16473                confp->chan.radio = 1;
16474             } else if (!strcasecmp(v->value, "em_rx")) {
16475                confp->chan.sig = SIG_EM;
16476                confp->chan.radio = 1;
16477             } else if (!strcasecmp(v->value, "em_tx")) {
16478                confp->chan.sig = SIG_EM;
16479                confp->chan.radio = 1;
16480             } else if (!strcasecmp(v->value, "em_rxtx")) {
16481                confp->chan.sig = SIG_EM;
16482                confp->chan.radio = 2;
16483             } else if (!strcasecmp(v->value, "em_txrx")) {
16484                confp->chan.sig = SIG_EM;
16485                confp->chan.radio = 2;
16486             } else if (!strcasecmp(v->value, "sf")) {
16487                confp->chan.sig = SIG_SF;
16488             } else if (!strcasecmp(v->value, "sf_w")) {
16489                confp->chan.sig = SIG_SFWINK;
16490             } else if (!strcasecmp(v->value, "sf_featd")) {
16491                confp->chan.sig = SIG_FEATD;
16492             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16493                confp->chan.sig = SIG_FEATDMF;
16494             } else if (!strcasecmp(v->value, "sf_featb")) {
16495                confp->chan.sig = SIG_SF_FEATB;
16496             } else if (!strcasecmp(v->value, "sf")) {
16497                confp->chan.sig = SIG_SF;
16498             } else if (!strcasecmp(v->value, "sf_rx")) {
16499                confp->chan.sig = SIG_SF;
16500                confp->chan.radio = 1;
16501             } else if (!strcasecmp(v->value, "sf_tx")) {
16502                confp->chan.sig = SIG_SF;
16503                confp->chan.radio = 1;
16504             } else if (!strcasecmp(v->value, "sf_rxtx")) {
16505                confp->chan.sig = SIG_SF;
16506                confp->chan.radio = 2;
16507             } else if (!strcasecmp(v->value, "sf_txrx")) {
16508                confp->chan.sig = SIG_SF;
16509                confp->chan.radio = 2;
16510             } else if (!strcasecmp(v->value, "featd")) {
16511                confp->chan.sig = SIG_FEATD;
16512             } else if (!strcasecmp(v->value, "featdmf")) {
16513                confp->chan.sig = SIG_FEATDMF;
16514             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16515                confp->chan.sig = SIG_FEATDMF_TA;
16516             } else if (!strcasecmp(v->value, "e911")) {
16517                confp->chan.sig = SIG_E911;
16518             } else if (!strcasecmp(v->value, "fgccama")) {
16519                confp->chan.sig = SIG_FGC_CAMA;
16520             } else if (!strcasecmp(v->value, "fgccamamf")) {
16521                confp->chan.sig = SIG_FGC_CAMAMF;
16522             } else if (!strcasecmp(v->value, "featb")) {
16523                confp->chan.sig = SIG_FEATB;
16524 #ifdef HAVE_PRI
16525             } else if (!strcasecmp(v->value, "pri_net")) {
16526                confp->chan.sig = SIG_PRI;
16527                confp->pri.nodetype = PRI_NETWORK;
16528             } else if (!strcasecmp(v->value, "pri_cpe")) {
16529                confp->chan.sig = SIG_PRI;
16530                confp->pri.nodetype = PRI_CPE;
16531             } else if (!strcasecmp(v->value, "bri_cpe")) {
16532                confp->chan.sig = SIG_BRI;
16533                confp->pri.nodetype = PRI_CPE;
16534             } else if (!strcasecmp(v->value, "bri_net")) {
16535                confp->chan.sig = SIG_BRI;
16536                confp->pri.nodetype = PRI_NETWORK;
16537             } else if (!strcasecmp(v->value, "bri_cpe_ptmp")) {
16538                confp->chan.sig = SIG_BRI_PTMP;
16539                confp->pri.nodetype = PRI_CPE;
16540             } else if (!strcasecmp(v->value, "bri_net_ptmp")) {
16541                ast_log(LOG_WARNING, "How cool would it be if someone implemented this mode!  For now, sucks for you. (line %d)\n", v->lineno);
16542             } else if (!strcasecmp(v->value, "gr303fxoks_net")) {
16543                confp->chan.sig = SIG_GR303FXOKS;
16544                confp->pri.nodetype = PRI_NETWORK;
16545             } else if (!strcasecmp(v->value, "gr303fxsks_cpe")) {
16546                confp->chan.sig = SIG_GR303FXSKS;
16547                confp->pri.nodetype = PRI_CPE;
16548 #endif
16549 #ifdef HAVE_SS7
16550             } else if (!strcasecmp(v->value, "ss7")) {
16551                confp->chan.sig = SIG_SS7;
16552 #endif
16553 #ifdef HAVE_OPENR2
16554             } else if (!strcasecmp(v->value, "mfcr2")) {
16555                confp->chan.sig = SIG_MFCR2;
16556 #endif
16557             } else if (!strcasecmp(v->value, "auto")) {
16558                confp->is_sig_auto = 1;
16559             } else {
16560                confp->chan.outsigmod = orig_outsigmod;
16561                confp->chan.radio = orig_radio;
16562                confp->is_sig_auto = orig_auto;
16563                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16564             }
16565           } else if (!strcasecmp(v->name, "outsignalling") || !strcasecmp(v->name, "outsignaling")) {
16566             if (!strcasecmp(v->value, "em")) {
16567                confp->chan.outsigmod = SIG_EM;
16568             } else if (!strcasecmp(v->value, "em_e1")) {
16569                confp->chan.outsigmod = SIG_EM_E1;
16570             } else if (!strcasecmp(v->value, "em_w")) {
16571                confp->chan.outsigmod = SIG_EMWINK;
16572             } else if (!strcasecmp(v->value, "sf")) {
16573                confp->chan.outsigmod = SIG_SF;
16574             } else if (!strcasecmp(v->value, "sf_w")) {
16575                confp->chan.outsigmod = SIG_SFWINK;
16576             } else if (!strcasecmp(v->value, "sf_featd")) {
16577                confp->chan.outsigmod = SIG_FEATD;
16578             } else if (!strcasecmp(v->value, "sf_featdmf")) {
16579                confp->chan.outsigmod = SIG_FEATDMF;
16580             } else if (!strcasecmp(v->value, "sf_featb")) {
16581                confp->chan.outsigmod = SIG_SF_FEATB;
16582             } else if (!strcasecmp(v->value, "sf")) {
16583                confp->chan.outsigmod = SIG_SF;
16584             } else if (!strcasecmp(v->value, "featd")) {
16585                confp->chan.outsigmod = SIG_FEATD;
16586             } else if (!strcasecmp(v->value, "featdmf")) {
16587                confp->chan.outsigmod = SIG_FEATDMF;
16588             } else if (!strcasecmp(v->value, "featdmf_ta")) {
16589                confp->chan.outsigmod = SIG_FEATDMF_TA;
16590             } else if (!strcasecmp(v->value, "e911")) {
16591                confp->chan.outsigmod = SIG_E911;
16592             } else if (!strcasecmp(v->value, "fgccama")) {
16593                confp->chan.outsigmod = SIG_FGC_CAMA;
16594             } else if (!strcasecmp(v->value, "fgccamamf")) {
16595                confp->chan.outsigmod = SIG_FGC_CAMAMF;
16596             } else if (!strcasecmp(v->value, "featb")) {
16597                confp->chan.outsigmod = SIG_FEATB;
16598             } else {
16599                ast_log(LOG_ERROR, "Unknown signalling method '%s' at line %d.\n", v->value, v->lineno);
16600             }
16601 #ifdef HAVE_PRI
16602          } else if (!strcasecmp(v->name, "pridialplan")) {
16603             if (!strcasecmp(v->value, "national")) {
16604                confp->pri.dialplan = PRI_NATIONAL_ISDN + 1;
16605             } else if (!strcasecmp(v->value, "unknown")) {
16606                confp->pri.dialplan = PRI_UNKNOWN + 1;
16607             } else if (!strcasecmp(v->value, "private")) {
16608                confp->pri.dialplan = PRI_PRIVATE + 1;
16609             } else if (!strcasecmp(v->value, "international")) {
16610                confp->pri.dialplan = PRI_INTERNATIONAL_ISDN + 1;
16611             } else if (!strcasecmp(v->value, "local")) {
16612                confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
16613             } else if (!strcasecmp(v->value, "dynamic")) {
16614                confp->pri.dialplan = -1;
16615             } else if (!strcasecmp(v->value, "redundant")) {
16616                confp->pri.dialplan = -2;
16617             } else {
16618                ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
16619             }
16620          } else if (!strcasecmp(v->name, "prilocaldialplan")) {
16621             if (!strcasecmp(v->value, "national")) {
16622                confp->pri.localdialplan = PRI_NATIONAL_ISDN + 1;
16623             } else if (!strcasecmp(v->value, "unknown")) {
16624                confp->pri.localdialplan = PRI_UNKNOWN + 1;
16625             } else if (!strcasecmp(v->value, "private")) {
16626                confp->pri.localdialplan = PRI_PRIVATE + 1;
16627             } else if (!strcasecmp(v->value, "international")) {
16628                confp->pri.localdialplan = PRI_INTERNATIONAL_ISDN + 1;
16629             } else if (!strcasecmp(v->value, "local")) {
16630                confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
16631             } else if (!strcasecmp(v->value, "dynamic")) {
16632                confp->pri.localdialplan = -1;
16633             } else if (!strcasecmp(v->value, "redundant")) {
16634                confp->pri.localdialplan = -2;
16635             } else {
16636                ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
16637             }
16638          } else if (!strcasecmp(v->name, "switchtype")) {
16639             if (!strcasecmp(v->value, "national"))
16640                confp->pri.switchtype = PRI_SWITCH_NI2;
16641             else if (!strcasecmp(v->value, "ni1"))
16642                confp->pri.switchtype = PRI_SWITCH_NI1;
16643             else if (!strcasecmp(v->value, "dms100"))
16644                confp->pri.switchtype = PRI_SWITCH_DMS100;
16645             else if (!strcasecmp(v->value, "4ess"))
16646                confp->pri.switchtype = PRI_SWITCH_ATT4ESS;
16647             else if (!strcasecmp(v->value, "5ess"))
16648                confp->pri.switchtype = PRI_SWITCH_LUCENT5E;
16649             else if (!strcasecmp(v->value, "euroisdn"))
16650                confp->pri.switchtype = PRI_SWITCH_EUROISDN_E1;
16651             else if (!strcasecmp(v->value, "qsig"))
16652                confp->pri.switchtype = PRI_SWITCH_QSIG;
16653             else {
16654                ast_log(LOG_ERROR, "Unknown switchtype '%s' at line %d.\n", v->value, v->lineno);
16655                return -1;
16656             }
16657          } else if (!strcasecmp(v->name, "nsf")) {
16658             if (!strcasecmp(v->value, "sdn"))
16659                confp->pri.nsf = PRI_NSF_SDN;
16660             else if (!strcasecmp(v->value, "megacom"))
16661                confp->pri.nsf = PRI_NSF_MEGACOM;
16662             else if (!strcasecmp(v->value, "tollfreemegacom"))
16663                confp->pri.nsf = PRI_NSF_TOLL_FREE_MEGACOM;
16664             else if (!strcasecmp(v->value, "accunet"))
16665                confp->pri.nsf = PRI_NSF_ACCUNET;
16666             else if (!strcasecmp(v->value, "none"))
16667                confp->pri.nsf = PRI_NSF_NONE;
16668             else {
16669                ast_log(LOG_WARNING, "Unknown network-specific facility '%s' at line %d.\n", v->value, v->lineno);
16670                confp->pri.nsf = PRI_NSF_NONE;
16671             }
16672          } else if (!strcasecmp(v->name, "priindication")) {
16673             if (!strcasecmp(v->value, "outofband"))
16674                confp->chan.priindication_oob = 1;
16675             else if (!strcasecmp(v->value, "inband"))
16676                confp->chan.priindication_oob = 0;
16677             else
16678                ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d.\n",
16679                   v->value, v->lineno);
16680          } else if (!strcasecmp(v->name, "priexclusive")) {
16681             confp->chan.priexclusive = ast_true(v->value);
16682          } else if (!strcasecmp(v->name, "internationalprefix")) {
16683             ast_copy_string(confp->pri.internationalprefix, v->value, sizeof(confp->pri.internationalprefix));
16684          } else if (!strcasecmp(v->name, "nationalprefix")) {
16685             ast_copy_string(confp->pri.nationalprefix, v->value, sizeof(confp->pri.nationalprefix));
16686          } else if (!strcasecmp(v->name, "localprefix")) {
16687             ast_copy_string(confp->pri.localprefix, v->value, sizeof(confp->pri.localprefix));
16688          } else if (!strcasecmp(v->name, "privateprefix")) {
16689             ast_copy_string(confp->pri.privateprefix, v->value, sizeof(confp->pri.privateprefix));
16690          } else if (!strcasecmp(v->name, "unknownprefix")) {
16691             ast_copy_string(confp->pri.unknownprefix, v->value, sizeof(confp->pri.unknownprefix));
16692          } else if (!strcasecmp(v->name, "resetinterval")) {
16693             if (!strcasecmp(v->value, "never"))
16694                confp->pri.resetinterval = -1;
16695             else if (atoi(v->value) >= 60)
16696                confp->pri.resetinterval = atoi(v->value);
16697             else
16698                ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n",
16699                   v->value, v->lineno);
16700          } else if (!strcasecmp(v->name, "minunused")) {
16701             confp->pri.minunused = atoi(v->value);
16702          } else if (!strcasecmp(v->name, "minidle")) {
16703             confp->pri.minidle = atoi(v->value);
16704          } else if (!strcasecmp(v->name, "idleext")) {
16705             ast_copy_string(confp->pri.idleext, v->value, sizeof(confp->pri.idleext));
16706          } else if (!strcasecmp(v->name, "idledial")) {
16707             ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
16708          } else if (!strcasecmp(v->name, "overlapdial")) {
16709             if (ast_true(v->value)) {
16710                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16711             } else if (!strcasecmp(v->value, "incoming")) {
16712                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_INCOMING;
16713             } else if (!strcasecmp(v->value, "outgoing")) {
16714                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_OUTGOING;
16715             } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
16716                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_BOTH;
16717             } else {
16718                confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
16719             }
16720 #ifdef HAVE_PRI_PROG_W_CAUSE
16721          } else if (!strcasecmp(v->name, "qsigchannelmapping")) {
16722             if (!strcasecmp(v->value, "logical")) {
16723                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_LOGICAL;
16724             } else if (!strcasecmp(v->value, "physical")) {
16725                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16726             } else {
16727                confp->pri.qsigchannelmapping = DAHDI_CHAN_MAPPING_PHYSICAL;
16728             }
16729 #endif
16730          } else if (!strcasecmp(v->name, "discardremoteholdretrieval")) {
16731             confp->pri.discardremoteholdretrieval = ast_true(v->value);
16732 #ifdef HAVE_PRI_INBANDDISCONNECT
16733          } else if (!strcasecmp(v->name, "inbanddisconnect")) {
16734             confp->pri.inbanddisconnect = ast_true(v->value);
16735 #endif
16736          } else if (!strcasecmp(v->name, "pritimer")) {
16737 #ifdef PRI_GETSET_TIMERS
16738             char tmp[20];
16739             char *timerc;
16740             char *c;
16741             int timer;
16742             int timeridx;
16743 
16744             ast_copy_string(tmp, v->value, sizeof(tmp));
16745             c = tmp;
16746             timerc = strsep(&c, ",");
16747             if (!ast_strlen_zero(timerc) && !ast_strlen_zero(c)) {
16748                timeridx = pri_timer2idx(timerc);
16749                timer = atoi(c);
16750                if (timeridx < 0 || PRI_MAX_TIMERS <= timeridx) {
16751                   ast_log(LOG_WARNING,
16752                      "'%s' is not a valid ISDN timer at line %d.\n", timerc,
16753                      v->lineno);
16754                } else if (!timer) {
16755                   ast_log(LOG_WARNING,
16756                      "'%s' is not a valid value for ISDN timer '%s' at line %d.\n",
16757                      c, timerc, v->lineno);
16758                } else {
16759                   pritimers[timeridx] = timer;
16760                }
16761             } else {
16762                ast_log(LOG_WARNING,
16763                   "'%s' is not a valid ISDN timer configuration string at line %d.\n",
16764                   v->value, v->lineno);
16765             }
16766 
16767          } else if (!strcasecmp(v->name, "facilityenable")) {
16768             confp->pri.facilityenable = ast_true(v->value);
16769 #endif /* PRI_GETSET_TIMERS */
16770 #endif /* HAVE_PRI */
16771 #ifdef HAVE_SS7
16772          } else if (!strcasecmp(v->name, "ss7type")) {
16773             if (!strcasecmp(v->value, "itu")) {
16774                cur_ss7type = SS7_ITU;
16775             } else if (!strcasecmp(v->value, "ansi")) {
16776                cur_ss7type = SS7_ANSI;
16777             } else
16778                ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
16779          } else if (!strcasecmp(v->name, "linkset")) {
16780             cur_linkset = atoi(v->value);
16781          } else if (!strcasecmp(v->name, "pointcode")) {
16782             cur_pointcode = parse_pointcode(v->value);
16783          } else if (!strcasecmp(v->name, "adjpointcode")) {
16784             cur_adjpointcode = parse_pointcode(v->value);
16785          } else if (!strcasecmp(v->name, "defaultdpc")) {
16786             cur_defaultdpc = parse_pointcode(v->value);
16787          } else if (!strcasecmp(v->name, "cicbeginswith")) {
16788             cur_cicbeginswith = atoi(v->value);
16789          } else if (!strcasecmp(v->name, "networkindicator")) {
16790             if (!strcasecmp(v->value, "national"))
16791                cur_networkindicator = SS7_NI_NAT;
16792             else if (!strcasecmp(v->value, "national_spare"))
16793                cur_networkindicator = SS7_NI_NAT_SPARE;
16794             else if (!strcasecmp(v->value, "international"))
16795                cur_networkindicator = SS7_NI_INT;
16796             else if (!strcasecmp(v->value, "international_spare"))
16797                cur_networkindicator = SS7_NI_INT_SPARE;
16798             else
16799                cur_networkindicator = -1;
16800          } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
16801             ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
16802          } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
16803             ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
16804          } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
16805             ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
16806          } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
16807             ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
16808          } else if (!strcasecmp(v->name, "ss7_called_nai")) {
16809             if (!strcasecmp(v->value, "national")) {
16810                confp->ss7.called_nai = SS7_NAI_NATIONAL;
16811             } else if (!strcasecmp(v->value, "international")) {
16812                confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
16813             } else if (!strcasecmp(v->value, "subscriber")) {
16814                confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
16815             } else if (!strcasecmp(v->value, "dynamic")) {
16816                confp->ss7.called_nai = SS7_NAI_DYNAMIC;
16817             } else {
16818                ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
16819             }
16820          } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
16821             if (!strcasecmp(v->value, "national")) {
16822                confp->ss7.calling_nai = SS7_NAI_NATIONAL;
16823             } else if (!strcasecmp(v->value, "international")) {
16824                confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
16825             } else if (!strcasecmp(v->value, "subscriber")) {
16826                confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
16827             } else if (!strcasecmp(v->value, "dynamic")) {
16828                confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
16829             } else {
16830                ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
16831             }
16832          } else if (!strcasecmp(v->name, "sigchan")) {
16833             int sigchan, res;
16834             sigchan = atoi(v->value);
16835             res = linkset_addsigchan(sigchan);
16836             if (res < 0)
16837                return -1;
16838 
16839          } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
16840             struct dahdi_ss7 *link;
16841             link = ss7_resolve_linkset(cur_linkset);
16842             if (!link) {
16843                ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
16844                return -1;
16845             }
16846             if (ast_true(v->value))
16847                link->flags |= LINKSET_FLAG_EXPLICITACM;
16848 #endif /* HAVE_SS7 */
16849 #ifdef HAVE_OPENR2
16850          } else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
16851             ast_copy_string(confp->mfcr2.r2proto_file, v->value, sizeof(confp->mfcr2.r2proto_file));
16852             ast_log(LOG_WARNING, "MFC/R2 Protocol file '%s' will be used, you only should use this if you *REALLY KNOW WHAT YOU ARE DOING*.\n", confp->mfcr2.r2proto_file);
16853          } else if (!strcasecmp(v->name, "mfcr2_logdir")) {
16854             ast_copy_string(confp->mfcr2.logdir, v->value, sizeof(confp->mfcr2.logdir));
16855          } else if (!strcasecmp(v->name, "mfcr2_variant")) {
16856             confp->mfcr2.variant = openr2_proto_get_variant(v->value);
16857             if (OR2_VAR_UNKNOWN == confp->mfcr2.variant) {
16858                ast_log(LOG_WARNING, "Unknown MFC/R2 variant '%s' at line %d, defaulting to ITU.\n", v->value, v->lineno);
16859                confp->mfcr2.variant = OR2_VAR_ITU;
16860             }
16861          } else if (!strcasecmp(v->name, "mfcr2_mfback_timeout")) {
16862             confp->mfcr2.mfback_timeout = atoi(v->value);
16863             if (!confp->mfcr2.mfback_timeout) {
16864                ast_log(LOG_WARNING, "MF timeout of 0? hum, I will protect you from your ignorance. Setting default.\n");
16865                confp->mfcr2.mfback_timeout = -1;
16866             } else if (confp->mfcr2.mfback_timeout > 0 && confp->mfcr2.mfback_timeout < 500) {
16867                ast_log(LOG_WARNING, "MF timeout less than 500ms is not recommended, you have been warned!\n");
16868             }
16869          } else if (!strcasecmp(v->name, "mfcr2_metering_pulse_timeout")) {
16870             confp->mfcr2.metering_pulse_timeout = atoi(v->value);
16871             if (confp->mfcr2.metering_pulse_timeout > 500) {
16872                ast_log(LOG_WARNING, "Metering pulse timeout greater than 500ms is not recommended, you have been warned!\n");
16873             }
16874          } else if (!strcasecmp(v->name, "mfcr2_get_ani_first")) {
16875             confp->mfcr2.get_ani_first = ast_true(v->value) ? 1 : 0;
16876          } else if (!strcasecmp(v->name, "mfcr2_double_answer")) {
16877             confp->mfcr2.double_answer = ast_true(v->value) ? 1 : 0;
16878          } else if (!strcasecmp(v->name, "mfcr2_charge_calls")) {
16879             confp->mfcr2.charge_calls = ast_true(v->value) ? 1 : 0;
16880          } else if (!strcasecmp(v->name, "mfcr2_accept_on_offer")) {
16881             confp->mfcr2.accept_on_offer = ast_true(v->value) ? 1 : 0;
16882          } else if (!strcasecmp(v->name, "mfcr2_allow_collect_calls")) {
16883             confp->mfcr2.allow_collect_calls = ast_true(v->value) ? 1 : 0;
16884          } else if (!strcasecmp(v->name, "mfcr2_forced_release")) {
16885             confp->mfcr2.forced_release = ast_true(v->value) ? 1 : 0;
16886          } else if (!strcasecmp(v->name, "mfcr2_immediate_accept")) {
16887             confp->mfcr2.immediate_accept = ast_true(v->value) ? 1 : 0;
16888          } else if (!strcasecmp(v->name, "mfcr2_call_files")) {
16889             confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
16890          } else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
16891             confp->mfcr2.max_ani = atoi(v->value);
16892             if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
16893                confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
16894             }
16895          } else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
16896             confp->mfcr2.max_dnis = atoi(v->value);
16897             if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
16898                confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
16899             }
16900          } else if (!strcasecmp(v->name, "mfcr2_category")) {
16901             confp->mfcr2.category = openr2_proto_get_category(v->value);
16902             if (OR2_CALLING_PARTY_CATEGORY_UNKNOWN == confp->mfcr2.category) {
16903                confp->mfcr2.category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
16904                ast_log(LOG_WARNING, "Invalid MFC/R2 caller category '%s' at line %d. Using national subscriber as default.\n",
16905                      v->value, v->lineno);
16906             }
16907          } else if (!strcasecmp(v->name, "mfcr2_logging")) {
16908             openr2_log_level_t tmplevel;
16909             char *clevel;
16910             char *logval = ast_strdupa(v->value);
16911             while (logval) {
16912                clevel = strsep(&logval,",");
16913                if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
16914                   ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
16915                   continue;
16916                }
16917                confp->mfcr2.loglevel |= tmplevel;
16918             }
16919 #endif /* HAVE_OPENR2 */
16920          } else if (!strcasecmp(v->name, "cadence")) {
16921             /* setup to scan our argument */
16922             int element_count, c[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
16923             int i;
16924             struct dahdi_ring_cadence new_cadence;
16925             int cid_location = -1;
16926             int firstcadencepos = 0;
16927             char original_args[80];
16928             int cadence_is_ok = 1;
16929 
16930             ast_copy_string(original_args, v->value, sizeof(original_args));
16931             /* 16 cadences allowed (8 pairs) */
16932             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]);
16933 
16934             /* Cadence must be even (on/off) */
16935             if (element_count % 2 == 1) {
16936                ast_log(LOG_ERROR, "Must be a silence duration for each ring duration: %s at line %d.\n", original_args, v->lineno);
16937                cadence_is_ok = 0;
16938             }
16939 
16940             /* Ring cadences cannot be negative */
16941             for (i = 0; i < element_count; i++) {
16942                if (c[i] == 0) {
16943                   ast_log(LOG_ERROR, "Ring or silence duration cannot be zero: %s at line %d.\n", original_args, v->lineno);
16944                   cadence_is_ok = 0;
16945                   break;
16946                } else if (c[i] < 0) {
16947                   if (i % 2 == 1) {
16948                      /* Silence duration, negative possibly okay */
16949                      if (cid_location == -1) {
16950                         cid_location = i;
16951                         c[i] *= -1;
16952                      } else {
16953                         ast_log(LOG_ERROR, "CID location specified twice: %s at line %d.\n", original_args, v->lineno);
16954                         cadence_is_ok = 0;
16955                         break;
16956                      }
16957                   } else {
16958                      if (firstcadencepos == 0) {
16959                         firstcadencepos = i; /* only recorded to avoid duplicate specification */
16960                                  /* duration will be passed negative to the DAHDI driver */
16961                      } else {
16962                          ast_log(LOG_ERROR, "First cadence position specified twice: %s at line %d.\n", original_args, v->lineno);
16963                         cadence_is_ok = 0;
16964                         break;
16965                      }
16966                   }
16967                }
16968             }
16969 
16970             /* Substitute our scanned cadence */
16971             for (i = 0; i < 16; i++) {
16972                new_cadence.ringcadence[i] = c[i];
16973             }
16974 
16975             if (cadence_is_ok) {
16976                /* ---we scanned it without getting annoyed; now some sanity checks--- */
16977                if (element_count < 2) {
16978                   ast_log(LOG_ERROR, "Minimum cadence is ring,pause: %s at line %d.\n", original_args, v->lineno);
16979                } else {
16980                   if (cid_location == -1) {
16981                      /* user didn't say; default to first pause */
16982                      cid_location = 1;
16983                   } else {
16984                      /* convert element_index to cidrings value */
16985                      cid_location = (cid_location + 1) / 2;
16986                   }
16987                   /* ---we like their cadence; try to install it--- */
16988                   if (!user_has_defined_cadences++)
16989                      /* this is the first user-defined cadence; clear the default user cadences */
16990                      num_cadence = 0;
16991                   if ((num_cadence+1) >= NUM_CADENCE_MAX)
16992                      ast_log(LOG_ERROR, "Already %d cadences; can't add another: %s at line %d.\n", NUM_CADENCE_MAX, original_args, v->lineno);
16993                   else {
16994                      cadences[num_cadence] = new_cadence;
16995                      cidrings[num_cadence++] = cid_location;
16996                      ast_verb(3, "cadence 'r%d' added: %s\n",num_cadence,original_args);
16997                   }
16998                }
16999             }
17000          } else if (!strcasecmp(v->name, "ringtimeout")) {
17001             ringt_base = (atoi(v->value) * 8) / READ_SIZE;
17002          } else if (!strcasecmp(v->name, "prewink")) {
17003             confp->timing.prewinktime = atoi(v->value);
17004          } else if (!strcasecmp(v->name, "preflash")) {
17005             confp->timing.preflashtime = atoi(v->value);
17006          } else if (!strcasecmp(v->name, "wink")) {
17007             confp->timing.winktime = atoi(v->value);
17008          } else if (!strcasecmp(v->name, "flash")) {
17009             confp->timing.flashtime = atoi(v->value);
17010          } else if (!strcasecmp(v->name, "start")) {
17011             confp->timing.starttime = atoi(v->value);
17012          } else if (!strcasecmp(v->name, "rxwink")) {
17013             confp->timing.rxwinktime = atoi(v->value);
17014          } else if (!strcasecmp(v->name, "rxflash")) {
17015             confp->timing.rxflashtime = atoi(v->value);
17016          } else if (!strcasecmp(v->name, "debounce")) {
17017             confp->timing.debouncetime = atoi(v->value);
17018          } else if (!strcasecmp(v->name, "toneduration")) {
17019             int toneduration;
17020             int ctlfd;
17021             int res;
17022             struct dahdi_dialparams dps;
17023 
17024             ctlfd = open("/dev/dahdi/ctl", O_RDWR);
17025             if (ctlfd == -1) {
17026                ast_log(LOG_ERROR, "Unable to open /dev/dahdi/ctl to set toneduration at line %d.\n", v->lineno);
17027                return -1;
17028             }
17029 
17030             toneduration = atoi(v->value);
17031             if (toneduration > -1) {
17032                memset(&dps, 0, sizeof(dps));
17033 
17034                dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
17035                res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
17036                if (res < 0) {
17037                   ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
17038                   return -1;
17039                }
17040             }
17041             close(ctlfd);
17042          } else if (!strcasecmp(v->name, "defaultcic")) {
17043             ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
17044          } else if (!strcasecmp(v->name, "defaultozz")) {
17045             ast_copy_string(defaultozz, v->value, sizeof(defaultozz));
17046          } else if (!strcasecmp(v->name, "mwilevel")) {
17047             mwilevel = atoi(v->value);
17048          }
17049       } else if (!(options & PROC_DAHDI_OPT_NOWARN) )
17050          ast_log(LOG_WARNING, "Ignoring any changes to '%s' (on reload) at line %d.\n", v->name, v->lineno);
17051    }
17052    if (dahdichan[0]) {
17053       /* The user has set 'dahdichan' */
17054       /*< \todo pass proper line number instead of 0 */
17055       if (build_channels(confp, 0, dahdichan, reload, 0, &found_pseudo)) {
17056          return -1;
17057       }
17058    }
17059    /*< \todo why check for the pseudo in the per-channel section.
17060     * Any actual use for manual setup of the pseudo channel? */
17061    if (!found_pseudo && reload != 1) {
17062       /* use the default configuration for a channel, so
17063          that any settings from real configured channels
17064          don't "leak" into the pseudo channel config
17065       */
17066       struct dahdi_chan_conf conf = dahdi_chan_conf_default();
17067 
17068       tmp = mkintf(CHAN_PSEUDO, &conf, NULL, reload);
17069 
17070       if (tmp) {
17071          ast_verb(3, "Automatically generated pseudo channel\n");
17072       } else {
17073          ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
17074       }
17075    }
17076    return 0;
17077 }

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

Definition at line 16040 of file chan_dahdi.c.

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

Referenced by process_dahdi().

16041 {
16042    char *parse = ast_strdupa(data);
16043    char *params[DAHDI_MAX_ECHOCANPARAMS + 1];
16044    unsigned int param_count;
16045    unsigned int x;
16046 
16047    if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
16048       return;
16049 
16050    memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
16051 
16052    /* first parameter is tap length, process it here */
16053 
16054    x = ast_strlen_zero(params[0]) ? 0 : atoi(params[0]);
16055 
16056    if ((x == 32) || (x == 64) || (x == 128) || (x == 256) || (x == 512) || (x == 1024))
16057       confp->chan.echocancel.head.tap_length = x;
16058    else if ((confp->chan.echocancel.head.tap_length = ast_true(params[0])))
16059       confp->chan.echocancel.head.tap_length = 128;
16060 
16061    /* now process any remaining parameters */
16062 
16063    for (x = 1; x < param_count; x++) {
16064       struct {
16065          char *name;
16066          char *value;
16067       } param;
16068 
16069       if (ast_app_separate_args(params[x], '=', (char **) &param, 2) < 1) {
16070          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, params[x]);
16071          continue;
16072       }
16073 
16074       if (ast_strlen_zero(param.name) || (strlen(param.name) > sizeof(confp->chan.echocancel.params[0].name)-1)) {
16075          ast_log(LOG_WARNING, "Invalid echocancel parameter supplied at line %d: '%s'\n", line, param.name);
16076          continue;
16077       }
16078 
16079       strcpy(confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].name, param.name);
16080 
16081       if (param.value) {
16082          if (sscanf(param.value, "%30d", &confp->chan.echocancel.params[confp->chan.echocancel.head.param_count].value) != 1) {
16083             ast_log(LOG_WARNING, "Invalid echocancel parameter value supplied at line %d: '%s'\n", line, param.value);
16084             continue;
16085          }
16086       }
16087       confp->chan.echocancel.head.param_count++;
16088    }
16089 }

static char* redirectingreason2str ( int  redirectingreason  )  [static]

Definition at line 12344 of file chan_dahdi.c.

Referenced by pri_dchannel().

12345 {
12346    switch (redirectingreason) {
12347    case 0:
12348       return "UNKNOWN";
12349    case 1:
12350       return "BUSY";
12351    case 2:
12352       return "NO_REPLY";
12353    case 0xF:
12354       return "UNCONDITIONAL";
12355    default:
12356       return "NOREDIRECT";
12357    }
12358 }

static int reload ( void   )  [static]

Definition at line 17480 of file chan_dahdi.c.

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

17481 {
17482    int res = 0;
17483 
17484    res = setup_dahdi(1);
17485    if (res) {
17486       ast_log(LOG_WARNING, "Reload of chan_dahdi.so is unsuccessful!\n");
17487       return -1;
17488    }
17489    return 0;
17490 }

static int reset_conf ( struct dahdi_pvt p  )  [static]

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

02591 {
02592    p->confno = -1;
02593    memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
02594    if (p->subs[SUB_REAL].dfd > -1) {
02595       struct dahdi_confinfo zi;
02596 
02597       memset(&zi, 0, sizeof(zi));
02598       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &zi))
02599          ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
02600    }
02601    return 0;
02602 }

static int restart_monitor ( void   )  [static]

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

09706 {
09707    /* If we're supposed to be stopped -- stay stopped */
09708    if (monitor_thread == AST_PTHREADT_STOP)
09709       return 0;
09710    ast_mutex_lock(&monlock);
09711    if (monitor_thread == pthread_self()) {
09712       ast_mutex_unlock(&monlock);
09713       ast_log(LOG_WARNING, "Cannot kill myself\n");
09714       return -1;
09715    }
09716    if (monitor_thread != AST_PTHREADT_NULL) {
09717       /* Wake up the thread */
09718       pthread_kill(monitor_thread, SIGURG);
09719    } else {
09720       /* Start a new monitor */
09721       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
09722          ast_mutex_unlock(&monlock);
09723          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
09724          return -1;
09725       }
09726    }
09727    ast_mutex_unlock(&monlock);
09728    return 0;
09729 }

static int restore_conference ( struct dahdi_pvt p  )  [static]

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

02970 {
02971    int res;
02972    if (p->saveconf.confmode) {
02973       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &p->saveconf);
02974       p->saveconf.confmode = 0;
02975       if (res) {
02976          ast_log(LOG_WARNING, "Unable to restore conference info: %s\n", strerror(errno));
02977          return -1;
02978       }
02979    }
02980    ast_debug(1, "Restored conferencing\n");
02981    return 0;
02982 }

static int restore_gains ( struct dahdi_pvt p  )  [static]

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

02851 {
02852    int res;
02853 
02854    res = set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
02855    if (res) {
02856       ast_log(LOG_WARNING, "Unable to restore gains: %s\n", strerror(errno));
02857       return -1;
02858    }
02859 
02860    return 0;
02861 }

static int save_conference ( struct dahdi_pvt p  )  [static]

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

02897 {
02898    struct dahdi_confinfo c;
02899    int res;
02900    if (p->saveconf.confmode) {
02901       ast_log(LOG_WARNING, "Can't save conference -- already in use\n");
02902       return -1;
02903    }
02904    p->saveconf.chan = 0;
02905    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GETCONF, &p->saveconf);
02906    if (res) {
02907       ast_log(LOG_WARNING, "Unable to get conference info: %s\n", strerror(errno));
02908       p->saveconf.confmode = 0;
02909       return -1;
02910    }
02911    memset(&c, 0, sizeof(c));
02912    c.confmode = DAHDI_CONF_NORMAL;
02913    res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETCONF, &c);
02914    if (res) {
02915       ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
02916       return -1;
02917    }
02918    ast_debug(1, "Disabled conferencing\n");
02919    return 0;
02920 }

static int send_callerid ( struct dahdi_pvt p  )  [static]

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

03027 {
03028    /* Assumes spill in p->cidspill, p->cidlen in length and we're p->cidpos into it */
03029    int res;
03030    /* Take out of linear mode if necessary */
03031    if (p->subs[SUB_REAL].linear) {
03032       p->subs[SUB_REAL].linear = 0;
03033       dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
03034    }
03035    while (p->cidpos < p->cidlen) {
03036       res = write(p->subs[SUB_REAL].dfd, p->cidspill + p->cidpos, p->cidlen - p->cidpos);
03037       if (res < 0) {
03038          if (errno == EAGAIN)
03039             return 0;
03040          else {
03041             ast_log(LOG_WARNING, "write failed: %s\n", strerror(errno));
03042             return -1;
03043          }
03044       }
03045       if (!res)
03046          return 0;
03047       p->cidpos += res;
03048    }
03049    ast_free(p->cidspill);
03050    p->cidspill = NULL;
03051    if (p->callwaitcas) {
03052       /* Wait for CID/CW to expire */
03053       p->cidcwexpire = CIDCW_EXPIRE_SAMPLES;
03054    } else
03055       restore_conference(p);
03056    return 0;
03057 }

static int send_cwcidspill ( struct dahdi_pvt p  )  [static]

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

02987 {
02988    p->callwaitcas = 0;
02989    p->cidcwexpire = 0;
02990    if (!(p->cidspill = ast_malloc(MAX_CALLERID_SIZE)))
02991       return -1;
02992    p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, p->callwait_name, p->callwait_num, AST_LAW(p));
02993    /* Make sure we account for the end */
02994    p->cidlen += READ_SIZE * 4;
02995    p->cidpos = 0;
02996    send_callerid(p);
02997    ast_verb(3, "CPE supports Call Waiting Caller*ID.  Sending '%s/%s'\n", p->callwait_name, p->callwait_num);
02998    return 0;
02999 }

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

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

02832 {
02833    return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
02834 }

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

Definition at line 2813 of file chan_dahdi.c.

References ast_debug, errno, and fill_rxgain().

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

02814 {
02815    struct dahdi_gains g;
02816    int res;
02817 
02818    memset(&g, 0, sizeof(g));
02819    g.chan = chan;
02820    res = ioctl(fd, DAHDI_GETGAINS, &g);
02821    if (res) {
02822       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02823       return res;
02824    }
02825 
02826    fill_rxgain(&g, gain, law);
02827 
02828    return ioctl(fd, DAHDI_SETGAINS, &g);
02829 }

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

Definition at line 2795 of file chan_dahdi.c.

References ast_debug, errno, and fill_txgain().

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

02796 {
02797    struct dahdi_gains g;
02798    int res;
02799 
02800    memset(&g, 0, sizeof(g));
02801    g.chan = chan;
02802    res = ioctl(fd, DAHDI_GETGAINS, &g);
02803    if (res) {
02804       ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
02805       return res;
02806    }
02807 
02808    fill_txgain(&g, gain, law);
02809 
02810    return ioctl(fd, DAHDI_SETGAINS, &g);
02811 }

static int setup_dahdi ( int  reload  )  [static]

Definition at line 17079 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_FILEINVALID, 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_DCHANS, 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().

17080 {
17081    struct ast_config *cfg, *ucfg;
17082    struct ast_variable *v;
17083    struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
17084    struct dahdi_chan_conf conf;
17085    struct ast_flags config_flags = { reload == 1 ? CONFIG_FLAG_FILEUNCHANGED : 0 };
17086    const char *cat;
17087    int res;
17088 
17089 #ifdef HAVE_PRI
17090    char *c;
17091    int spanno;
17092    int i;
17093    int logicalspan;
17094    int trunkgroup;
17095    int dchannels[NUM_DCHANS];
17096 #endif
17097 
17098    cfg = ast_config_load(config, config_flags);
17099 
17100    /* Error if we have no config file */
17101    if (!cfg) {
17102       ast_log(LOG_ERROR, "Unable to load config %s\n", config);
17103       return 0;
17104    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
17105       ucfg = ast_config_load("users.conf", config_flags);
17106       if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
17107          return 0;
17108       } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
17109          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17110          return 0;
17111       }
17112       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17113       if ((cfg = ast_config_load(config, config_flags)) == CONFIG_STATUS_FILEINVALID) {
17114          ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17115          ast_config_destroy(ucfg);
17116          return 0;
17117       }
17118    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
17119       ast_log(LOG_ERROR, "File %s cannot be parsed.  Aborting.\n", config);
17120       return 0;
17121    } else {
17122       ast_clear_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
17123       if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
17124          ast_log(LOG_ERROR, "File users.conf cannot be parsed.  Aborting.\n");
17125          ast_config_destroy(cfg);
17126          return 0;
17127       }
17128    }
17129 
17130    /* It's a little silly to lock it, but we mind as well just to be sure */
17131    ast_mutex_lock(&iflock);
17132 #ifdef HAVE_PRI
17133    if (reload != 1) {
17134       /* Process trunkgroups first */
17135       v = ast_variable_browse(cfg, "trunkgroups");
17136       while (v) {
17137          if (!strcasecmp(v->name, "trunkgroup")) {
17138             trunkgroup = atoi(v->value);
17139             if (trunkgroup > 0) {
17140                if ((c = strchr(v->value, ','))) {
17141                   i = 0;
17142                   memset(dchannels, 0, sizeof(dchannels));
17143                   while (c && (i < NUM_DCHANS)) {
17144                      dchannels[i] = atoi(c + 1);
17145                      if (dchannels[i] < 0) {
17146                         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);
17147                      } else
17148                         i++;
17149                      c = strchr(c + 1, ',');
17150                   }
17151                   if (i) {
17152                      if (pri_create_trunkgroup(trunkgroup, dchannels)) {
17153                         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);
17154                   } else
17155                         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");
17156                   } else
17157                      ast_log(LOG_WARNING, "Trunk group %d lacks any valid D-channels at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17158                } else
17159                   ast_log(LOG_WARNING, "Trunk group %d lacks a primary D-channel at line %d of chan_dahdi.conf\n", trunkgroup, v->lineno);
17160             } else
17161                ast_log(LOG_WARNING, "Trunk group identifier must be a positive integer at line %d of chan_dahdi.conf\n", v->lineno);
17162          } else if (!strcasecmp(v->name, "spanmap")) {
17163             spanno = atoi(v->value);
17164             if (spanno > 0) {
17165                if ((c = strchr(v->value, ','))) {
17166                   trunkgroup = atoi(c + 1);
17167                   if (trunkgroup > 0) {
17168                      if ((c = strchr(c + 1, ',')))
17169                         logicalspan = atoi(c + 1);
17170                      else
17171                         logicalspan = 0;
17172                      if (logicalspan >= 0) {
17173                         if (pri_create_spanmap(spanno - 1, trunkgroup, logicalspan)) {
17174                            ast_log(LOG_WARNING, "Failed to map span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17175                      } else
17176                            ast_verb(2, "Mapped span %d to trunk group %d (logical span %d)\n", spanno, trunkgroup, logicalspan);
17177                      } else
17178                         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);
17179                   } else
17180                      ast_log(LOG_WARNING, "Trunk group must be a postive number at line %d of chan_dahdi.conf\n", v->lineno);
17181                } else
17182                   ast_log(LOG_WARNING, "Missing trunk group for span map at line %d of chan_dahdi.conf\n", v->lineno);
17183             } else
17184                ast_log(LOG_WARNING, "Span number must be a postive integer at line %d of chan_dahdi.conf\n", v->lineno);
17185          } else {
17186             ast_log(LOG_NOTICE, "Ignoring unknown keyword '%s' in trunkgroups\n", v->name);
17187          }
17188          v = v->next;
17189       }
17190    }
17191 #endif
17192 
17193    /* Copy the default jb config over global_jbconf */
17194    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
17195 
17196    mwimonitornotify[0] = '\0';
17197 
17198    v = ast_variable_browse(cfg, "channels");
17199    if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
17200       ast_mutex_unlock(&iflock);
17201       ast_config_destroy(cfg);
17202       if (ucfg) {
17203          ast_config_destroy(ucfg);
17204       }
17205       return res;
17206    }
17207 
17208    /* Now get configuration from all normal sections in chan_dahdi.conf: */
17209    for (cat = ast_category_browse(cfg, NULL); cat ; cat = ast_category_browse(cfg, cat)) {
17210       /* [channels] and [trunkgroups] are used. Let's also reserve
17211        * [globals] and [general] for future use
17212        */
17213       if (!strcasecmp(cat, "general") ||
17214          !strcasecmp(cat, "trunkgroups") ||
17215          !strcasecmp(cat, "globals") ||
17216          !strcasecmp(cat, "channels")) {
17217          continue;
17218       }
17219 
17220       memcpy(&conf, &base_conf, sizeof(conf));
17221 
17222       if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
17223          ast_mutex_unlock(&iflock);
17224          ast_config_destroy(cfg);
17225          if (ucfg) {
17226             ast_config_destroy(cfg);
17227          }
17228          return res;
17229       }
17230    }
17231 
17232    ast_config_destroy(cfg);
17233 
17234    if (ucfg) {
17235       const char *chans;
17236 
17237       process_dahdi(&base_conf, "", ast_variable_browse(ucfg, "general"), 1, 0);
17238 
17239       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
17240          if (!strcasecmp(cat, "general")) {
17241             continue;
17242          }
17243 
17244          chans = ast_variable_retrieve(ucfg, cat, "dahdichan");
17245 
17246          if (ast_strlen_zero(chans)) {
17247             continue;
17248          }
17249 
17250          memcpy(&conf, &base_conf, sizeof(conf));
17251 
17252          if ((res = process_dahdi(&conf, cat, ast_variable_browse(ucfg, cat), reload, PROC_DAHDI_OPT_NOCHAN | PROC_DAHDI_OPT_NOWARN))) {
17253             ast_config_destroy(ucfg);
17254             ast_mutex_unlock(&iflock);
17255             return res;
17256          }
17257       }
17258       ast_config_destroy(ucfg);
17259    }
17260    ast_mutex_unlock(&iflock);
17261 
17262 #ifdef HAVE_PRI
17263    if (reload != 1) {
17264       int x;
17265       for (x = 0; x < NUM_SPANS; x++) {
17266          if (pris[x].pvts[0]) {
17267             if (start_pri(pris + x)) {
17268                ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
17269                return -1;
17270             } else
17271                ast_verb(2, "Starting D-Channel on span %d\n", x + 1);
17272          }
17273       }
17274    }
17275 #endif
17276 #ifdef HAVE_SS7
17277    if (reload != 1) {
17278       int x;
17279       for (x = 0; x < NUM_SPANS; x++) {
17280          if (linksets[x].ss7) {
17281             if (ast_pthread_create(&linksets[x].master, NULL, ss7_linkset, &linksets[x])) {
17282                ast_log(LOG_ERROR, "Unable to start SS7 linkset on span %d\n", x + 1);
17283                return -1;
17284             } else
17285                ast_verb(2, "Starting SS7 linkset on span %d\n", x + 1);
17286          }
17287       }
17288    }
17289 #endif
17290 #ifdef HAVE_OPENR2
17291    if (reload != 1) {
17292       int x;
17293       for (x = 0; x < r2links_count; x++) {
17294          if (ast_pthread_create(&r2links[x]->r2master, NULL, mfcr2_monitor, r2links[x])) {
17295             ast_log(LOG_ERROR, "Unable to start R2 monitor on channel group %d\n", x + 1);
17296             return -1;
17297          } else {
17298             ast_verb(2, "Starting R2 monitor on channel group %d\n", x + 1);
17299          }
17300       }
17301    }
17302 #endif
17303    /* And start the monitor for the first time */
17304    restart_monitor();
17305    return 0;
17306 }

static int sigtype_to_signalling ( int  sigtype  )  [static]

Definition at line 9985 of file chan_dahdi.c.

Referenced by mkintf().

09986 {
09987    return sigtype;
09988 }

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

11354 {
11355    if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
11356       if (size) {
11357          *buf = '\0';
11358       }
11359       return;
11360    }
11361    switch (nai) {
11362    case SS7_NAI_INTERNATIONAL:
11363       snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
11364       break;
11365    case SS7_NAI_NATIONAL:
11366       snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
11367       break;
11368    case SS7_NAI_SUBSCRIBER:
11369       snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
11370       break;
11371    case SS7_NAI_UNKNOWN:
11372       snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
11373       break;
11374    default:
11375       snprintf(buf, size, "%s", number);
11376       break;
11377    }
11378 }

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

11163 {
11164    int i;
11165 
11166    for (i = 0; i < linkset->numchans; i++) {
11167       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11168          if (state) {
11169             if (state[i])
11170                linkset->pvts[i]->remotelyblocked = block;
11171          } else
11172             linkset->pvts[i]->remotelyblocked = block;
11173       }
11174    }
11175 }

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

Definition at line 11097 of file chan_dahdi.c.

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

Referenced by ss7_linkset().

11098 {
11099    int i;
11100    int winner = -1;
11101    for (i = 0; i < linkset->numchans; i++) {
11102       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
11103          winner = i;
11104          break;
11105       }
11106    }
11107    return winner;
11108 }

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

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

01457 {
01458    int res;
01459    /* Grab the lock first */
01460    do {
01461       res = ast_mutex_trylock(&pri->lock);
01462       if (res) {
01463          DEADLOCK_AVOIDANCE(&pvt->lock);
01464       }
01465    } while (res);
01466    /* Then break the poll */
01467    if (pri->master != AST_PTHREADT_NULL)
01468       pthread_kill(pri->master, SIGURG);
01469    return 0;
01470 }

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

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

11113 {
11114    unsigned char status[32];
11115    struct dahdi_pvt *p = NULL;
11116    int i, offset;
11117 
11118    for (i = 0; i < linkset->numchans; i++) {
11119       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11120          p = linkset->pvts[i];
11121          offset = p->cic - startcic;
11122          status[offset] = 0;
11123          if (p->locallyblocked)
11124             status[offset] |= (1 << 0) | (1 << 4);
11125          if (p->remotelyblocked)
11126             status[offset] |= (1 << 1) | (1 << 5);
11127          if (p->ss7call) {
11128             if (p->outgoing)
11129                status[offset] |= (1 << 3);
11130             else
11131                status[offset] |= (1 << 2);
11132          } else
11133             status[offset] |= 0x3 << 2;
11134       }
11135    }
11136 
11137    if (p)
11138       isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
11139    else
11140       ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
11141 
11142 }

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

Definition at line 11146 of file chan_dahdi.c.

References ast_channel::_softhangup, ast_mutex_lock(), ast_mutex_unlock(), AST_SOFTHANGUP_DEV, dahdi_pvt::cic, dahdi_pvt::dpc, dahdi_pvt::lock, dahdi_ss7::numchans, dahdi_pvt::owner, and dahdi_ss7::pvts.

Referenced by ss7_linkset().

11147 {
11148    int i;
11149 
11150    for (i = 0; i < linkset->numchans; i++) {
11151       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
11152          ast_mutex_lock(&linkset->pvts[i]->lock);
11153          if (linkset->pvts[i]->owner)
11154             linkset->pvts[i]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11155          ast_mutex_unlock(&linkset->pvts[i]->lock);
11156       }
11157    }
11158 }

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

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

11180 {
11181    int i;
11182 
11183    for (i = 0; i < linkset->numchans; i++) {
11184       if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
11185          linkset->pvts[i]->inservice = 1;
11186    }
11187 }

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

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

11390 {
11391    int res, i;
11392    struct timeval *next = NULL, tv;
11393    struct dahdi_ss7 *linkset = (struct dahdi_ss7 *) data;
11394    struct ss7 *ss7 = linkset->ss7;
11395    ss7_event *e = NULL;
11396    struct dahdi_pvt *p;
11397    int chanpos;
11398    struct pollfd pollers[NUM_DCHANS];
11399    int cic;
11400    unsigned int dpc;
11401    int nextms = 0;
11402 
11403    ss7_start(ss7);
11404 
11405    while(1) {
11406       ast_mutex_lock(&linkset->lock);
11407       if ((next = ss7_schedule_next(ss7))) {
11408          tv = ast_tvnow();
11409          tv.tv_sec = next->tv_sec - tv.tv_sec;
11410          tv.tv_usec = next->tv_usec - tv.tv_usec;
11411          if (tv.tv_usec < 0) {
11412             tv.tv_usec += 1000000;
11413             tv.tv_sec -= 1;
11414          }
11415          if (tv.tv_sec < 0) {
11416             tv.tv_sec = 0;
11417             tv.tv_usec = 0;
11418          }
11419          nextms = tv.tv_sec * 1000;
11420          nextms += tv.tv_usec / 1000;
11421       }
11422       ast_mutex_unlock(&linkset->lock);
11423 
11424       for (i = 0; i < linkset->numsigchans; i++) {
11425          pollers[i].fd = linkset->fds[i];
11426          pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
11427          pollers[i].revents = 0;
11428       }
11429 
11430       res = poll(pollers, linkset->numsigchans, nextms);
11431       if ((res < 0) && (errno != EINTR)) {
11432          ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
11433       } else if (!res) {
11434          ast_mutex_lock(&linkset->lock);
11435          ss7_schedule_run(ss7);
11436          ast_mutex_unlock(&linkset->lock);
11437          continue;
11438       }
11439 
11440       ast_mutex_lock(&linkset->lock);
11441       for (i = 0; i < linkset->numsigchans; i++) {
11442          if (pollers[i].revents & POLLPRI) {
11443             int x;
11444             if (ioctl(pollers[i].fd, DAHDI_GETEVENT, &x)) {
11445                ast_log(LOG_ERROR, "Error in exception retrieval!\n");
11446             }
11447             switch (x) {
11448             case DAHDI_EVENT_OVERRUN:
11449                ast_debug(1, "Overrun detected!\n");
11450                break;
11451             case DAHDI_EVENT_BADFCS:
11452                ast_debug(1, "Bad FCS\n");
11453                break;
11454             case DAHDI_EVENT_ABORT:
11455                ast_debug(1, "HDLC Abort\n");
11456                break;
11457             case DAHDI_EVENT_ALARM:
11458                ast_log(LOG_ERROR, "Alarm on link!\n");
11459                linkset->linkstate[i] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
11460                linkset->linkstate[i] &= ~LINKSTATE_UP;
11461                ss7_link_alarm(ss7, pollers[i].fd);
11462                break;
11463             case DAHDI_EVENT_NOALARM:
11464                ast_log(LOG_ERROR, "Alarm cleared on link\n");
11465                linkset->linkstate[i] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
11466                linkset->linkstate[i] |= LINKSTATE_STARTING;
11467                ss7_link_noalarm(ss7, pollers[i].fd);
11468                break;
11469             default:
11470                ast_log(LOG_ERROR, "Got exception %d!\n", x);
11471                break;
11472             }
11473          }
11474 
11475          if (pollers[i].revents & POLLIN) {
11476             res = ss7_read(ss7, pollers[i].fd);
11477          }
11478 
11479          if (pollers[i].revents & POLLOUT) {
11480             res = ss7_write(ss7, pollers[i].fd);
11481             if (res < 0) {
11482                ast_debug(1, "Error in write %s\n", strerror(errno));
11483             }
11484          }
11485       }
11486 
11487       while ((e = ss7_check_event(ss7))) {
11488          switch (e->e) {
11489          case SS7_EVENT_UP:
11490             if (linkset->state != LINKSET_STATE_UP) {
11491                ast_verbose("--- SS7 Up ---\n");
11492                ss7_reset_linkset(linkset);
11493             }
11494             linkset->state = LINKSET_STATE_UP;
11495             break;
11496          case SS7_EVENT_DOWN:
11497             ast_verbose("--- SS7 Down ---\n");
11498             linkset->state = LINKSET_STATE_DOWN;
11499             for (i = 0; i < linkset->numchans; i++) {
11500                struct dahdi_pvt *p = linkset->pvts[i];
11501                if (p)
11502                   p->inalarm = 1;
11503             }
11504             break;
11505          case MTP2_LINK_UP:
11506             ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
11507             break;
11508          case MTP2_LINK_DOWN:
11509             ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
11510             break;
11511          case ISUP_EVENT_CPG:
11512             chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
11513             if (chanpos < 0) {
11514                ast_log(LOG_WARNING, "CPG on unconfigured CIC %d\n", e->cpg.cic);
11515                break;
11516             }
11517             p = linkset->pvts[chanpos];
11518             ast_mutex_lock(&p->lock);
11519             switch (e->cpg.event) {
11520             case CPG_EVENT_ALERTING:
11521                p->alerting = 1;
11522                p->subs[SUB_REAL].needringing = 1;
11523                break;
11524             case CPG_EVENT_PROGRESS:
11525             case CPG_EVENT_INBANDINFO:
11526                {
11527                   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
11528                   ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
11529                   dahdi_queue_frame(p, &f, linkset);
11530                   p->progress = 1;
11531                   p->dialing = 0;
11532                   if (p->dsp && p->dsp_features) {
11533                      ast_dsp_set_features(p->dsp, p->dsp_features);
11534                      p->dsp_features = 0;
11535                   }
11536                }
11537                break;
11538             default:
11539                ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
11540             }
11541 
11542             ast_mutex_unlock(&p->lock);
11543             break;
11544          case ISUP_EVENT_RSC:
11545             ast_verbose("Resetting CIC %d\n", e->rsc.cic);
11546             chanpos = ss7_find_cic(linkset, e->rsc.cic, e->rsc.opc);
11547             if (chanpos < 0) {
11548                ast_log(LOG_WARNING, "RSC on unconfigured CIC %d\n", e->rsc.cic);
11549                break;
11550             }
11551             p = linkset->pvts[chanpos];
11552             ast_mutex_lock(&p->lock);
11553             p->inservice = 1;
11554             p->remotelyblocked = 0;
11555             dpc = p->dpc;
11556             isup_set_call_dpc(e->rsc.call, dpc);
11557             if (p->ss7call)
11558                p->ss7call = NULL;
11559             if (p->owner)
11560                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11561             ast_mutex_unlock(&p->lock);
11562             isup_rlc(ss7, e->rsc.call);
11563             break;
11564          case ISUP_EVENT_GRS:
11565             ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
11566             chanpos = ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
11567             if (chanpos < 0) {
11568                ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
11569                break;
11570             }
11571             p = linkset->pvts[chanpos];
11572             isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
11573             ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
11574             ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
11575             break;
11576          case ISUP_EVENT_CQM:
11577             ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
11578             ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
11579             break;
11580          case ISUP_EVENT_GRA:
11581             ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
11582             ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
11583             ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
11584             break;
11585          case ISUP_EVENT_IAM:
11586             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);
11587             chanpos = ss7_find_cic(linkset, e->iam.cic, e->iam.opc);
11588             if (chanpos < 0) {
11589                ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
11590                isup_rel(ss7, e->iam.call, -1);
11591                break;
11592             }
11593             p = linkset->pvts[chanpos];
11594             ast_mutex_lock(&p->lock);
11595             if (p->owner) {
11596                if (p->ss7call == e->iam.call) {
11597                   ast_mutex_unlock(&p->lock);
11598                   ast_log(LOG_WARNING, "Duplicate IAM requested on CIC %d\n", e->iam.cic);
11599                   break;
11600                } else {
11601                   ast_mutex_unlock(&p->lock);
11602                   ast_log(LOG_WARNING, "Ring requested on CIC %d already in use!\n", e->iam.cic);
11603                   break;
11604                }
11605             }
11606 
11607             dpc = p->dpc;
11608             p->ss7call = e->iam.call;
11609             isup_set_call_dpc(p->ss7call, dpc);
11610 
11611             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
11612                ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
11613                p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
11614             } else
11615                p->cid_num[0] = 0;
11616 
11617             if (p->immediate) {
11618                p->exten[0] = 's';
11619                p->exten[1] = '\0';
11620             } else if (!ast_strlen_zero(e->iam.called_party_num)) {
11621                char *st;
11622                ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
11623                st = strchr(p->exten, '#');
11624                if (st)
11625                   *st = '\0';
11626                } else
11627                   p->exten[0] = '\0';
11628 
11629             p->cid_ani[0] = '\0';
11630             if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
11631                ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
11632             else
11633                p->cid_name[0] = '\0';
11634 
11635             p->cid_ani2 = e->iam.oli_ani2;
11636             p->cid_ton = 0;
11637             ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
11638             ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
11639             p->gen_add_type = e->iam.gen_add_type;
11640             p->gen_add_nai = e->iam.gen_add_nai;
11641             p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
11642             p->gen_add_num_plan = e->iam.gen_add_num_plan;
11643             ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
11644             p->gen_dig_type = e->iam.gen_dig_type;
11645             p->gen_dig_scheme = e->iam.gen_dig_scheme;
11646             ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
11647             ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
11648             ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
11649             ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
11650             p->calling_party_cat = e->iam.calling_party_cat;
11651 
11652             /* Set DNID */
11653             if (!ast_strlen_zero(e->iam.called_party_num))
11654                ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
11655 
11656             if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
11657 
11658                if (e->iam.cot_check_required) {
11659                   dahdi_loopback(p, 1);
11660                } else
11661                   ss7_start_call(p, linkset);
11662             } else {
11663                ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
11664                p->alreadyhungup = 1;
11665                isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
11666             }
11667             ast_mutex_unlock(&p->lock);
11668             break;
11669          case ISUP_EVENT_COT:
11670             chanpos = ss7_find_cic(linkset, e->cot.cic, e->cot.opc);
11671             if (chanpos < 0) {
11672                ast_log(LOG_WARNING, "COT on unconfigured CIC %d\n", e->cot.cic);
11673                isup_rel(ss7, e->cot.call, -1);
11674                break;
11675             }
11676             p = linkset->pvts[chanpos];
11677 
11678             ast_mutex_lock(&p->lock);
11679 
11680             if (p->loopedback) {
11681                dahdi_loopback(p, 0);
11682                ss7_start_call(p, linkset);
11683             }
11684 
11685             ast_mutex_unlock(&p->lock);
11686 
11687             break;
11688          case ISUP_EVENT_CCR:
11689             ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
11690             chanpos = ss7_find_cic(linkset, e->ccr.cic, e->ccr.opc);
11691             if (chanpos < 0) {
11692                ast_log(LOG_WARNING, "CCR on unconfigured CIC %d\n", e->ccr.cic);
11693                break;
11694             }
11695 
11696             p = linkset->pvts[chanpos];
11697 
11698             ast_mutex_lock(&p->lock);
11699             dahdi_loopback(p, 1);
11700             ast_mutex_unlock(&p->lock);
11701 
11702             isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
11703             break;
11704          case ISUP_EVENT_CVT:
11705             ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
11706             chanpos = ss7_find_cic(linkset, e->cvt.cic, e->cvt.opc);
11707             if (chanpos < 0) {
11708                ast_log(LOG_WARNING, "CVT on unconfigured CIC %d\n", e->cvt.cic);
11709                break;
11710             }
11711 
11712             p = linkset->pvts[chanpos];
11713 
11714             ast_mutex_lock(&p->lock);
11715             dahdi_loopback(p, 1);
11716             ast_mutex_unlock(&p->lock);
11717 
11718             isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
11719             break;
11720          case ISUP_EVENT_REL:
11721             chanpos = ss7_find_cic(linkset, e->rel.cic, e->rel.opc);
11722             if (chanpos < 0) {
11723                ast_log(LOG_WARNING, "REL on unconfigured CIC %d\n", e->rel.cic);
11724                break;
11725             }
11726             p = linkset->pvts[chanpos];
11727             ast_mutex_lock(&p->lock);
11728             if (p->owner) {
11729                p->owner->hangupcause = e->rel.cause;
11730                p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
11731             } else if (!p->restartpending)
11732                ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
11733 
11734             /* End the loopback if we have one */
11735             dahdi_loopback(p, 0);
11736 
11737             isup_rlc(ss7, e->rel.call);
11738             p->ss7call = NULL;
11739 
11740             ast_mutex_unlock(&p->lock);
11741             break;
11742          case ISUP_EVENT_ACM:
11743             chanpos = ss7_find_cic(linkset, e->acm.cic, e->acm.opc);
11744             if (chanpos < 0) {
11745                ast_log(LOG_WARNING, "ACM on unconfigured CIC %d\n", e->acm.cic);
11746                isup_rel(ss7, e->acm.call, -1);
11747                break;
11748             } else {
11749                struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
11750 
11751                p = linkset->pvts[chanpos];
11752 
11753                ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
11754 
11755                if (e->acm.call_ref_ident > 0) {
11756                   p->rlt = 1; /* Setting it but not using it here*/
11757                }
11758 
11759                ast_mutex_lock(&p->lock);
11760                dahdi_queue_frame(p, &f, linkset);
11761                p->proceeding = 1;
11762                p->dialing = 0;
11763                /* Send alerting if subscriber is free */
11764                if (e->acm.called_party_status_ind == 1) {
11765                   p->alerting = 1;
11766                   p->subs[SUB_REAL].needringing = 1;
11767                }
11768                ast_mutex_unlock(&p->lock);
11769             }
11770             break;
11771          case ISUP_EVENT_CGB:
11772             chanpos = ss7_find_cic(linkset, e->cgb.startcic, e->cgb.opc);
11773             if (chanpos < 0) {
11774                ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
11775                break;
11776             }
11777             p = linkset->pvts[chanpos];
11778             ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
11779             isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
11780             break;
11781          case ISUP_EVENT_CGU:
11782             chanpos = ss7_find_cic(linkset, e->cgu.startcic, e->cgu.opc);
11783             if (chanpos < 0) {
11784                ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
11785                break;
11786             }
11787             p = linkset->pvts[chanpos];
11788             ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
11789             isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
11790             break;
11791          case ISUP_EVENT_UCIC:
11792             chanpos = ss7_find_cic(linkset, e->ucic.cic, e->ucic.opc);
11793             if (chanpos < 0) {
11794                ast_log(LOG_WARNING, "UCIC on unconfigured CIC %d\n", e->ucic.cic);
11795                break;
11796             }
11797             p = linkset->pvts[chanpos];
11798             ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
11799             ast_mutex_lock(&p->lock);
11800             p->remotelyblocked = 1;
11801             p->inservice = 0;
11802             ast_mutex_unlock(&p->lock);         //doesn't require a SS7 acknowledgement
11803             break;
11804          case ISUP_EVENT_BLO:
11805             chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
11806             if (chanpos < 0) {
11807                ast_log(LOG_WARNING, "BLO on unconfigured CIC %d\n", e->blo.cic);
11808                break;
11809             }
11810             p = linkset->pvts[chanpos];
11811             ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
11812             ast_mutex_lock(&p->lock);
11813             p->remotelyblocked = 1;
11814             ast_mutex_unlock(&p->lock);
11815             isup_bla(linkset->ss7, e->blo.cic, p->dpc);
11816             break;
11817          case ISUP_EVENT_BLA:
11818             chanpos = ss7_find_cic(linkset, e->bla.cic, e->bla.opc);
11819             if (chanpos < 0) {
11820                ast_log(LOG_WARNING, "BLA on unconfigured CIC %d\n", e->bla.cic);
11821                break;
11822             }
11823             ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
11824             p = linkset->pvts[chanpos];
11825             ast_mutex_lock(&p->lock);
11826             p->locallyblocked = 1;
11827             ast_mutex_unlock(&p->lock);
11828             break;
11829          case ISUP_EVENT_UBL:
11830             chanpos = ss7_find_cic(linkset, e->ubl.cic, e->ubl.opc);
11831             if (chanpos < 0) {
11832                ast_log(LOG_WARNING, "UBL on unconfigured CIC %d\n", e->ubl.cic);
11833                break;
11834             }
11835             p = linkset->pvts[chanpos];
11836             ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
11837             ast_mutex_lock(&p->lock);
11838             p->remotelyblocked = 0;
11839             ast_mutex_unlock(&p->lock);
11840             isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
11841             break;
11842          case ISUP_EVENT_UBA:
11843             chanpos = ss7_find_cic(linkset, e->uba.cic, e->uba.opc);
11844             if (chanpos < 0) {
11845                ast_log(LOG_WARNING, "UBA on unconfigured CIC %d\n", e->uba.cic);
11846                break;
11847             }
11848             p = linkset->pvts[chanpos];
11849             ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
11850             ast_mutex_lock(&p->lock);
11851             p->locallyblocked = 0;
11852             ast_mutex_unlock(&p->lock);
11853             break;
11854          case ISUP_EVENT_CON:
11855          case ISUP_EVENT_ANM:
11856             if (e->e == ISUP_EVENT_CON)
11857                cic = e->con.cic;
11858             else
11859                cic = e->anm.cic;
11860 
11861             chanpos = ss7_find_cic(linkset, cic, (e->e == ISUP_EVENT_ANM) ? e->anm.opc : e->con.opc);
11862             if (chanpos < 0) {
11863                ast_log(LOG_WARNING, "ANM/CON on unconfigured CIC %d\n", cic);
11864                isup_rel(ss7, (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call, -1);
11865                break;
11866             } else {
11867                p = linkset->pvts[chanpos];
11868                ast_mutex_lock(&p->lock);
11869                p->subs[SUB_REAL].needanswer = 1;
11870                if (p->dsp && p->dsp_features) {
11871                   ast_dsp_set_features(p->dsp, p->dsp_features);
11872                   p->dsp_features = 0;
11873                }
11874                dahdi_enable_ec(p);
11875                ast_mutex_unlock(&p->lock);
11876             }
11877             break;
11878          case ISUP_EVENT_RLC:
11879             chanpos = ss7_find_cic(linkset, e->rlc.cic, e->rlc.opc);
11880             if (chanpos < 0) {
11881                ast_log(LOG_WARNING, "RLC on unconfigured CIC %d\n", e->rlc.cic);
11882                break;
11883             } else {
11884                p = linkset->pvts[chanpos];
11885                ast_mutex_lock(&p->lock);
11886                if (p->alreadyhungup)
11887                   p->ss7call = NULL;
11888                else
11889                   ast_log(LOG_NOTICE, "Received RLC out and we haven't sent REL.  Ignoring.\n");
11890                ast_mutex_unlock(&p->lock);
11891                }
11892                break;
11893          case ISUP_EVENT_FAA:
11894             chanpos = ss7_find_cic(linkset, e->faa.cic, e->faa.opc);
11895             if (chanpos < 0) {
11896                ast_log(LOG_WARNING, "FAA on unconfigured CIC %d\n", e->faa.cic);
11897                break;
11898             } else {
11899                p = linkset->pvts[chanpos];
11900                ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
11901                ast_mutex_lock(&p->lock);
11902                if (p->alreadyhungup){
11903                   p->ss7call = NULL;
11904                   ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR.  Ignoring.\n");
11905                }
11906                ast_mutex_unlock(&p->lock);
11907             }
11908             break;
11909          default:
11910             ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
11911             break;
11912          }
11913       }
11914       ast_mutex_unlock(&linkset->lock);
11915    }
11916 
11917    return 0;
11918 }

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

Definition at line 11382 of file chan_dahdi.c.

Referenced by ss7_linkset().

11383 {
11384    return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
11385 }

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

Definition at line 1449 of file chan_dahdi.c.

References ast_mutex_unlock(), and dahdi_ss7::lock.

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

01450 {
01451    ast_mutex_unlock(&ss7->lock);
01452 }

static void ss7_reset_linkset ( struct dahdi_ss7 linkset  )  [static]

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

11192 {
11193    int i, startcic = -1, endcic, dpc;
11194 
11195    if (linkset->numchans <= 0)
11196       return;
11197 
11198    startcic = linkset->pvts[0]->cic;
11199    /* DB: CIC's DPC fix */
11200    dpc = linkset->pvts[0]->dpc;
11201 
11202    for (i = 0; i < linkset->numchans; i++) {
11203       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)) {
11204          continue;
11205       } else {
11206          endcic = linkset->pvts[i]->cic;
11207          ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
11208          isup_grs(linkset->ss7, startcic, endcic, dpc);
11209 
11210          /* DB: CIC's DPC fix */
11211          if (linkset->pvts[i+1]) {
11212             startcic = linkset->pvts[i+1]->cic;
11213             dpc = linkset->pvts[i+1]->dpc;
11214          }
11215       }
11216    }
11217 }

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

Definition at line 9874 of file chan_dahdi.c.

References linksets, and NUM_SPANS.

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

09875 {
09876    if ((linkset < 0) || (linkset >= NUM_SPANS))
09877       return NULL;
09878    else
09879       return &linksets[linkset - 1];
09880 }

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

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

11236 {
11237    struct ss7 *ss7 = linkset->ss7;
11238    int res;
11239    int law = 1;
11240    struct ast_channel *c;
11241    char tmp[256];
11242 
11243    if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
11244       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
11245 
11246    if (linkset->type == SS7_ITU)
11247       law = DAHDI_LAW_ALAW;
11248    else
11249       law = DAHDI_LAW_MULAW;
11250 
11251    res = dahdi_setlaw(p->subs[SUB_REAL].dfd, law);
11252    if (res < 0)
11253       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
11254 
11255    if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
11256       p->proceeding = 1;
11257       isup_acm(ss7, p->ss7call);
11258    }
11259 
11260    ast_mutex_unlock(&linkset->lock);
11261    c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
11262 
11263    if (!c) {
11264       ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
11265       /* Holding this lock is assumed entering the function */
11266       ast_mutex_lock(&linkset->lock);
11267       return;
11268    } else
11269       ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
11270 
11271    dahdi_enable_ec(p);
11272 
11273    /* We only reference these variables in the context of the ss7_linkset function
11274     * when receiving either and IAM or a COT message.  Since they are only accessed
11275     * from this context, we should be safe to unlock around them */
11276 
11277    ast_mutex_unlock(&p->lock);
11278 
11279    if (!ast_strlen_zero(p->charge_number)) {
11280       pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
11281       /* Clear this after we set it */
11282       p->charge_number[0] = 0;
11283    }
11284    if (!ast_strlen_zero(p->gen_add_number)) {
11285       pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
11286       /* Clear this after we set it */
11287       p->gen_add_number[0] = 0;
11288    }
11289    if (!ast_strlen_zero(p->jip_number)) {
11290       pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
11291       /* Clear this after we set it */
11292       p->jip_number[0] = 0;
11293    }
11294    if (!ast_strlen_zero(p->gen_dig_number)) {
11295       pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
11296       /* Clear this after we set it */
11297       p->gen_dig_number[0] = 0;
11298    }
11299    if (!ast_strlen_zero(p->orig_called_num)) {
11300       pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
11301       /* Clear this after we set it */
11302       p->orig_called_num[0] = 0;
11303    }
11304 
11305    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
11306    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
11307    /* Clear this after we set it */
11308    p->gen_dig_type = 0;
11309 
11310    snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
11311    pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
11312    /* Clear this after we set it */
11313    p->gen_dig_scheme = 0;
11314 
11315    if (!ast_strlen_zero(p->lspi_ident)) {
11316       pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
11317       /* Clear this after we set it */
11318       p->lspi_ident[0] = 0;
11319    }
11320 
11321    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
11322    pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
11323    /* Clear this after we set it */
11324    p->call_ref_ident = 0;
11325 
11326    snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
11327    pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
11328    /* Clear this after we set it */
11329    p->call_ref_pc = 0;
11330 
11331    snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
11332    pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
11333    /* Clear this after we set it */
11334    p->calling_party_cat = 0;
11335 
11336    if (!ast_strlen_zero(p->redirecting_num)) {
11337       pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
11338       /* Clear this after we set it */
11339       p->redirecting_num[0] = 0;
11340    }
11341    if (!ast_strlen_zero(p->generic_name)) {
11342       pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
11343       /* Clear this after we set it */
11344       p->generic_name[0] = 0;
11345    }
11346 
11347    ast_mutex_lock(&p->lock);
11348    ast_mutex_lock(&linkset->lock);
11349 }

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

Definition at line 7675 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, 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, 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, ast_channel::language, dahdi_pvt::lastcid_num, len(), dahdi_subchannel::linear, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, dahdi_pvt::mailbox, dahdi_pvt::mwimonitor_rpas, my_getsigstr(), ast_channel::name, 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, 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().

07676 {
07677    struct ast_channel *chan = data;
07678    struct dahdi_pvt *p = chan->tech_pvt;
07679    char exten[AST_MAX_EXTENSION] = "";
07680    char exten2[AST_MAX_EXTENSION] = "";
07681    unsigned char buf[256];
07682    char dtmfcid[300];
07683    char dtmfbuf[300];
07684    struct callerid_state *cs = NULL;
07685    char *name = NULL, *number = NULL;
07686    int distMatches;
07687    int curRingData[3];
07688    int receivedRingT;
07689    int counter1;
07690    int counter;
07691    int samples = 0;
07692    struct ast_smdi_md_message *smdi_msg = NULL;
07693    int flags = 0;
07694    int i;
07695    int timeout;
07696    int getforward = 0;
07697    char *s1, *s2;
07698    int len = 0;
07699    int res;
07700    int idx;
07701 
07702    ast_mutex_lock(&ss_thread_lock);
07703    ss_thread_count++;
07704    ast_mutex_unlock(&ss_thread_lock);
07705    /* in the bizarre case where the channel has become a zombie before we
07706       even get started here, abort safely
07707    */
07708    if (!p) {
07709       ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
07710       ast_hangup(chan);
07711       goto quit;
07712    }
07713    ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
07714    idx = dahdi_get_index(chan, p, 1);
07715    if (idx < 0) {
07716       ast_log(LOG_WARNING, "Huh?\n");
07717       ast_hangup(chan);
07718       goto quit;
07719    }
07720    if (p->dsp)
07721       ast_dsp_digitreset(p->dsp);
07722    switch (p->sig) {
07723 #ifdef HAVE_PRI
07724    case SIG_PRI:
07725    case SIG_BRI:
07726    case SIG_BRI_PTMP:
07727       /* Now loop looking for an extension */
07728       ast_copy_string(exten, p->exten, sizeof(exten));
07729       len = strlen(exten);
07730       res = 0;
07731       while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
07732          if (len && !ast_ignore_pattern(chan->context, exten))
07733             tone_zone_play_tone(p->subs[idx].dfd, -1);
07734          else
07735             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
07736          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
07737             timeout = matchdigittimeout;
07738          else
07739             timeout = gendigittimeout;
07740          res = ast_waitfordigit(chan, timeout);
07741          if (res < 0) {
07742             ast_debug(1, "waitfordigit returned < 0...\n");
07743             ast_hangup(chan);
07744             goto quit;
07745          } else if (res) {
07746             exten[len++] = res;
07747             exten[len] = '\0';
07748          } else
07749             break;
07750       }
07751       /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
07752       if (ast_strlen_zero(exten)) {
07753          ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
07754          exten[0] = 's';
07755          exten[1] = '\0';
07756       }
07757       tone_zone_play_tone(p->subs[idx].dfd, -1);
07758       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
07759          /* Start the real PBX */
07760          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
07761          if (p->dsp) {
07762             ast_dsp_digitreset(p->dsp);
07763          }
07764          if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
07765             if (p->pri->pri) {      
07766                if (!pri_grab(p, p->pri)) {
07767                   pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
07768                   p->proceeding = 1;
07769                   pri_rel(p->pri);
07770                } else {
07771                   ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
07772                }
07773             }
07774          }
07775          dahdi_enable_ec(p);
07776          ast_setstate(chan, AST_STATE_RING);
07777          res = ast_pbx_run(chan);
07778          if (res) {
07779             ast_log(LOG_WARNING, "PBX exited non-zero!\n");
07780          }
07781       } else {
07782          ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
07783          chan->hangupcause = AST_CAUSE_UNALLOCATED;
07784          ast_hangup(chan);
07785          p->exten[0] = '\0';
07786          /* Since we send release complete here, we won't get one */
07787          p->call = NULL;
07788       }
07789       goto quit;
07790       break;
07791 #endif
07792    case SIG_FEATD:
07793    case SIG_FEATDMF:
07794    case SIG_FEATDMF_TA:
07795    case SIG_E911:
07796    case SIG_FGC_CAMAMF:
07797    case SIG_FEATB:
07798    case SIG_EMWINK:
07799    case SIG_SF_FEATD:
07800    case SIG_SF_FEATDMF:
07801    case SIG_SF_FEATB:
07802    case SIG_SFWINK:
07803       if (dahdi_wink(p, idx))
07804          goto quit;
07805       /* Fall through */
07806    case SIG_EM:
07807    case SIG_EM_E1:
07808    case SIG_SF:
07809    case SIG_FGC_CAMA:
07810       res = tone_zone_play_tone(p->subs[idx].dfd, -1);
07811       if (p->dsp)
07812          ast_dsp_digitreset(p->dsp);
07813       /* set digit mode appropriately */
07814       if (p->dsp) {
07815          if (NEED_MFDETECT(p))
07816             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07817          else
07818             ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07819       }
07820       memset(dtmfbuf, 0, sizeof(dtmfbuf));
07821       /* Wait for the first digit only if immediate=no */
07822       if (!p->immediate)
07823          /* Wait for the first digit (up to 5 seconds). */
07824          res = ast_waitfordigit(chan, 5000);
07825       else
07826          res = 0;
07827       if (res > 0) {
07828          /* save first char */
07829          dtmfbuf[0] = res;
07830          switch (p->sig) {
07831          case SIG_FEATD:
07832          case SIG_SF_FEATD:
07833             res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07834             if (res > 0)
07835                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07836             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07837             break;
07838          case SIG_FEATDMF_TA:
07839             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07840             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07841             if (dahdi_wink(p, idx)) goto quit;
07842             dtmfbuf[0] = 0;
07843             /* Wait for the first digit (up to 5 seconds). */
07844             res = ast_waitfordigit(chan, 5000);
07845             if (res <= 0) break;
07846             dtmfbuf[0] = res;
07847             /* fall through intentionally */
07848          case SIG_FEATDMF:
07849          case SIG_E911:
07850          case SIG_FGC_CAMAMF:
07851          case SIG_SF_FEATDMF:
07852             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07853             /* if international caca, do it again to get real ANO */
07854             if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
07855             {
07856                if (dahdi_wink(p, idx)) goto quit;
07857                dtmfbuf[0] = 0;
07858                /* Wait for the first digit (up to 5 seconds). */
07859                res = ast_waitfordigit(chan, 5000);
07860                if (res <= 0) break;
07861                dtmfbuf[0] = res;
07862                res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07863             }
07864             if (res > 0) {
07865                /* if E911, take off hook */
07866                if (p->sig == SIG_E911)
07867                   dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07868                res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "#", 3000);
07869             }
07870             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07871             break;
07872          case SIG_FEATB:
07873          case SIG_SF_FEATB:
07874             res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
07875             if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07876             break;
07877          case SIG_EMWINK:
07878             /* if we received a '*', we are actually receiving Feature Group D
07879                dial syntax, so use that mode; otherwise, fall through to normal
07880                mode
07881             */
07882             if (res == '*') {
07883                res = my_getsigstr(chan, dtmfbuf + 1, "*", 3000);
07884                if (res > 0)
07885                   res = my_getsigstr(chan, dtmfbuf + strlen(dtmfbuf), "*", 3000);
07886                if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
07887                break;
07888             }
07889          default:
07890             /* If we got the first digit, get the rest */
07891             len = 1;
07892             dtmfbuf[len] = '\0';
07893             while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07894                if (ast_exists_extension(chan, chan->context, dtmfbuf, 1, p->cid_num)) {
07895                   timeout = matchdigittimeout;
07896                } else {
07897                   timeout = gendigittimeout;
07898                }
07899                res = ast_waitfordigit(chan, timeout);
07900                if (res < 0) {
07901                   ast_debug(1, "waitfordigit returned < 0...\n");
07902                   ast_hangup(chan);
07903                   goto quit;
07904                } else if (res) {
07905                   dtmfbuf[len++] = res;
07906                   dtmfbuf[len] = '\0';
07907                } else {
07908                   break;
07909                }
07910             }
07911             break;
07912          }
07913       }
07914       if (res == -1) {
07915          ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
07916          ast_hangup(chan);
07917          goto quit;
07918       } else if (res < 0) {
07919          ast_debug(1, "Got hung up before digits finished\n");
07920          ast_hangup(chan);
07921          goto quit;
07922       }
07923 
07924       if (p->sig == SIG_FGC_CAMA) {
07925          char anibuf[100];
07926 
07927          if (ast_safe_sleep(chan,1000) == -1) {
07928             ast_hangup(chan);
07929             goto quit;
07930          }
07931          dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
07932          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
07933          res = my_getsigstr(chan, anibuf, "#", 10000);
07934          if ((res > 0) && (strlen(anibuf) > 2)) {
07935             if (anibuf[strlen(anibuf) - 1] == '#')
07936                anibuf[strlen(anibuf) - 1] = 0;
07937             ast_set_callerid(chan, anibuf + 2, NULL, anibuf + 2);
07938          }
07939          ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
07940       }
07941 
07942       ast_copy_string(exten, dtmfbuf, sizeof(exten));
07943       if (ast_strlen_zero(exten))
07944          ast_copy_string(exten, "s", sizeof(exten));
07945       if (p->sig == SIG_FEATD || p->sig == SIG_EMWINK) {
07946          /* Look for Feature Group D on all E&M Wink and Feature Group D trunks */
07947          if (exten[0] == '*') {
07948             char *stringp=NULL;
07949             ast_copy_string(exten2, exten, sizeof(exten2));
07950             /* Parse out extension and callerid */
07951             stringp=exten2 +1;
07952             s1 = strsep(&stringp, "*");
07953             s2 = strsep(&stringp, "*");
07954             if (s2) {
07955                if (!ast_strlen_zero(p->cid_num))
07956                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07957                else
07958                   ast_set_callerid(chan, s1, NULL, s1);
07959                ast_copy_string(exten, s2, sizeof(exten));
07960             } else
07961                ast_copy_string(exten, s1, sizeof(exten));
07962          } else if (p->sig == SIG_FEATD)
07963             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07964       }
07965       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
07966          if (exten[0] == '*') {
07967             char *stringp=NULL;
07968             ast_copy_string(exten2, exten, sizeof(exten2));
07969             /* Parse out extension and callerid */
07970             stringp=exten2 +1;
07971             s1 = strsep(&stringp, "#");
07972             s2 = strsep(&stringp, "#");
07973             if (s2) {
07974                if (!ast_strlen_zero(p->cid_num))
07975                   ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
07976                else
07977                   if (*(s1 + 2))
07978                      ast_set_callerid(chan, s1 + 2, NULL, s1 + 2);
07979                ast_copy_string(exten, s2 + 1, sizeof(exten));
07980             } else
07981                ast_copy_string(exten, s1 + 2, sizeof(exten));
07982          } else
07983             ast_log(LOG_WARNING, "Got a non-Feature Group D input on channel %d.  Assuming E&M Wink instead\n", p->channel);
07984       }
07985       if ((p->sig == SIG_E911) || (p->sig == SIG_FGC_CAMAMF)) {
07986          if (exten[0] == '*') {
07987             char *stringp=NULL;
07988             ast_copy_string(exten2, exten, sizeof(exten2));
07989             /* Parse out extension and callerid */
07990             stringp=exten2 +1;
07991             s1 = strsep(&stringp, "#");
07992             s2 = strsep(&stringp, "#");
07993             if (s2 && (*(s2 + 1) == '0')) {
07994                if (*(s2 + 2))
07995                   ast_set_callerid(chan, s2 + 2, NULL, s2 + 2);
07996             }
07997             if (s1)  ast_copy_string(exten, s1, sizeof(exten));
07998             else ast_copy_string(exten, "911", sizeof(exten));
07999          } else
08000             ast_log(LOG_WARNING, "Got a non-E911/FGC CAMA input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08001       }
08002       if (p->sig == SIG_FEATB) {
08003          if (exten[0] == '*') {
08004             char *stringp=NULL;
08005             ast_copy_string(exten2, exten, sizeof(exten2));
08006             /* Parse out extension and callerid */
08007             stringp=exten2 +1;
08008             s1 = strsep(&stringp, "#");
08009             ast_copy_string(exten, exten2 + 1, sizeof(exten));
08010          } else
08011             ast_log(LOG_WARNING, "Got a non-Feature Group B input on channel %d.  Assuming E&M Wink instead\n", p->channel);
08012       }
08013       if ((p->sig == SIG_FEATDMF) || (p->sig == SIG_FEATDMF_TA)) {
08014          dahdi_wink(p, idx);
08015          /* some switches require a minimum guard time between
08016             the last FGD wink and something that answers
08017             immediately. This ensures it */
08018          if (ast_safe_sleep(chan,100)) goto quit;
08019       }
08020       dahdi_enable_ec(p);
08021       if (NEED_MFDETECT(p)) {
08022          if (p->dsp) {
08023             if (!p->hardwaredtmf)
08024                ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_DTMF | p->dtmfrelax);
08025             else {
08026                ast_dsp_free(p->dsp);
08027                p->dsp = NULL;
08028             }
08029          }
08030       }
08031 
08032       if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
08033          ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08034          if (p->dsp) ast_dsp_digitreset(p->dsp);
08035          res = ast_pbx_run(chan);
08036          if (res) {
08037             ast_log(LOG_WARNING, "PBX exited non-zero\n");
08038             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08039          }
08040          goto quit;
08041       } else {
08042          ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
08043          sleep(2);
08044          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_INFO);
08045          if (res < 0)
08046             ast_log(LOG_WARNING, "Unable to start special tone on %d\n", p->channel);
08047          else
08048             sleep(1);
08049          res = ast_streamfile(chan, "ss-noservice", chan->language);
08050          if (res >= 0)
08051             ast_waitstream(chan, "");
08052          res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08053          ast_hangup(chan);
08054          goto quit;
08055       }
08056       break;
08057    case SIG_FXOLS:
08058    case SIG_FXOGS:
08059    case SIG_FXOKS:
08060       /* Read the first digit */
08061       timeout = firstdigittimeout;
08062       /* If starting a threeway call, never timeout on the first digit so someone
08063          can use flash-hook as a "hold" feature */
08064       if (p->subs[SUB_THREEWAY].owner)
08065          timeout = 999999;
08066       while (len < AST_MAX_EXTENSION-1) {
08067          /* Read digit unless it's supposed to be immediate, in which case the
08068             only answer is 's' */
08069          if (p->immediate)
08070             res = 's';
08071          else
08072             res = ast_waitfordigit(chan, timeout);
08073          timeout = 0;
08074          if (res < 0) {
08075             ast_debug(1, "waitfordigit returned < 0...\n");
08076             res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08077             ast_hangup(chan);
08078             goto quit;
08079          } else if (res) {
08080             ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
08081             exten[len++]=res;
08082             exten[len] = '\0';
08083          }
08084          if (!ast_ignore_pattern(chan->context, exten))
08085             tone_zone_play_tone(p->subs[idx].dfd, -1);
08086          else
08087             tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08088          if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num) && strcmp(exten, ast_parking_ext())) {
08089             if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
08090                if (getforward) {
08091                   /* Record this as the forwarding extension */
08092                   ast_copy_string(p->call_forward, exten, sizeof(p->call_forward));
08093                   ast_verb(3, "Setting call forward to '%s' on channel %d\n", p->call_forward, p->channel);
08094                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08095                   if (res)
08096                      break;
08097                   usleep(500000);
08098                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08099                   sleep(1);
08100                   memset(exten, 0, sizeof(exten));
08101                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
08102                   len = 0;
08103                   getforward = 0;
08104                } else {
08105                   res = tone_zone_play_tone(p->subs[idx].dfd, -1);
08106                   ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08107                   if (!ast_strlen_zero(p->cid_num)) {
08108                      if (!p->hidecallerid)
08109                         ast_set_callerid(chan, p->cid_num, NULL, p->cid_num);
08110                      else
08111                         ast_set_callerid(chan, NULL, NULL, p->cid_num);
08112                   }
08113                   if (!ast_strlen_zero(p->cid_name)) {
08114                      if (!p->hidecallerid)
08115                         ast_set_callerid(chan, NULL, p->cid_name, NULL);
08116                   }
08117                   ast_setstate(chan, AST_STATE_RING);
08118                   dahdi_enable_ec(p);
08119                   res = ast_pbx_run(chan);
08120                   if (res) {
08121                      ast_log(LOG_WARNING, "PBX exited non-zero\n");
08122                      res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08123                   }
08124                   goto quit;
08125                }
08126             } else {
08127                /* It's a match, but they just typed a digit, and there is an ambiguous match,
08128                   so just set the timeout to matchdigittimeout and wait some more */
08129                timeout = matchdigittimeout;
08130             }
08131          } else if (res == 0) {
08132             ast_debug(1, "not enough digits (and no ambiguous match)...\n");
08133             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08134             dahdi_wait_event(p->subs[idx].dfd);
08135             ast_hangup(chan);
08136             goto quit;
08137          } else if (p->callwaiting && !strcmp(exten, "*70")) {
08138             ast_verb(3, "Disabling call waiting on %s\n", chan->name);
08139             /* Disable call waiting if enabled */
08140             p->callwaiting = 0;
08141             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08142             if (res) {
08143                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08144                   chan->name, strerror(errno));
08145             }
08146             len = 0;
08147             ioctl(p->subs[idx].dfd,DAHDI_CONFDIAG,&len);
08148             memset(exten, 0, sizeof(exten));
08149             timeout = firstdigittimeout;
08150 
08151          } else if (!strcmp(exten,ast_pickup_ext())) {
08152             /* Scan all channels and see if there are any
08153              * ringing channels that have call groups
08154              * that equal this channels pickup group
08155              */
08156             if (idx == SUB_REAL) {
08157                /* Switch us from Third call to Call Wait */
08158                if (p->subs[SUB_THREEWAY].owner) {
08159                   /* If you make a threeway call and the *8# a call, it should actually
08160                      look like a callwait */
08161                   alloc_sub(p, SUB_CALLWAIT);
08162                   swap_subs(p, SUB_CALLWAIT, SUB_THREEWAY);
08163                   unalloc_sub(p, SUB_THREEWAY);
08164                }
08165                dahdi_enable_ec(p);
08166                if (ast_pickup_call(chan)) {
08167                   ast_debug(1, "No call pickup possible...\n");
08168                   res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08169                   dahdi_wait_event(p->subs[idx].dfd);
08170                }
08171                ast_hangup(chan);
08172                goto quit;
08173             } else {
08174                ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
08175                ast_hangup(chan);
08176                goto quit;
08177             }
08178 
08179          } else if (!p->hidecallerid && !strcmp(exten, "*67")) {
08180             ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
08181             /* Disable Caller*ID if enabled */
08182             p->hidecallerid = 1;
08183             if (chan->cid.cid_num)
08184                ast_free(chan->cid.cid_num);
08185             chan->cid.cid_num = NULL;
08186             if (chan->cid.cid_name)
08187                ast_free(chan->cid.cid_name);
08188             chan->cid.cid_name = NULL;
08189             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08190             if (res) {
08191                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08192                   chan->name, strerror(errno));
08193             }
08194             len = 0;
08195             memset(exten, 0, sizeof(exten));
08196             timeout = firstdigittimeout;
08197          } else if (p->callreturn && !strcmp(exten, "*69")) {
08198             res = 0;
08199             if (!ast_strlen_zero(p->lastcid_num)) {
08200                res = ast_say_digit_str(chan, p->lastcid_num, "", chan->language);
08201             }
08202             if (!res)
08203                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08204             break;
08205          } else if (!strcmp(exten, "*78")) {
08206             dahdi_dnd(p, 1);
08207             /* Do not disturb */
08208             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08209             getforward = 0;
08210             memset(exten, 0, sizeof(exten));
08211             len = 0;
08212          } else if (!strcmp(exten, "*79")) {
08213             dahdi_dnd(p, 0);
08214             /* Do not disturb */
08215             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08216             getforward = 0;
08217             memset(exten, 0, sizeof(exten));
08218             len = 0;
08219          } else if (p->cancallforward && !strcmp(exten, "*72")) {
08220             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08221             getforward = 1;
08222             memset(exten, 0, sizeof(exten));
08223             len = 0;
08224          } else if (p->cancallforward && !strcmp(exten, "*73")) {
08225             ast_verb(3, "Cancelling call forwarding on channel %d\n", p->channel);
08226             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08227             memset(p->call_forward, 0, sizeof(p->call_forward));
08228             getforward = 0;
08229             memset(exten, 0, sizeof(exten));
08230             len = 0;
08231          } else if ((p->transfer || p->canpark) && !strcmp(exten, ast_parking_ext()) &&
08232                   p->subs[SUB_THREEWAY].owner &&
08233                   ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
08234             /* This is a three way call, the main call being a real channel,
08235                and we're parking the first call. */
08236             ast_masq_park_call(ast_bridged_channel(p->subs[SUB_THREEWAY].owner), chan, 0, NULL);
08237             ast_verb(3, "Parking call to '%s'\n", chan->name);
08238             break;
08239          } else if (!ast_strlen_zero(p->lastcid_num) && !strcmp(exten, "*60")) {
08240             ast_verb(3, "Blacklisting number %s\n", p->lastcid_num);
08241             res = ast_db_put("blacklist", p->lastcid_num, "1");
08242             if (!res) {
08243                res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08244                memset(exten, 0, sizeof(exten));
08245                len = 0;
08246             }
08247          } else if (p->hidecallerid && !strcmp(exten, "*82")) {
08248             ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
08249             /* Enable Caller*ID if enabled */
08250             p->hidecallerid = 0;
08251             if (chan->cid.cid_num)
08252                ast_free(chan->cid.cid_num);
08253             chan->cid.cid_num = NULL;
08254             if (chan->cid.cid_name)
08255                ast_free(chan->cid.cid_name);
08256             chan->cid.cid_name = NULL;
08257             ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
08258             res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
08259             if (res) {
08260                ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
08261                   chan->name, strerror(errno));
08262             }
08263             len = 0;
08264             memset(exten, 0, sizeof(exten));
08265             timeout = firstdigittimeout;
08266          } else if (!strcmp(exten, "*0")) {
08267             struct ast_channel *nbridge =
08268                p->subs[SUB_THREEWAY].owner;
08269             struct dahdi_pvt *pbridge = NULL;
08270             /* set up the private struct of the bridged one, if any */
08271             if (nbridge && ast_bridged_channel(nbridge))
08272                pbridge = ast_bridged_channel(nbridge)->tech_pvt;
08273             if (nbridge && pbridge &&
08274                (nbridge->tech == &dahdi_tech) &&
08275                (ast_bridged_channel(nbridge)->tech == &dahdi_tech) &&
08276                ISTRUNK(pbridge)) {
08277                int func = DAHDI_FLASH;
08278                /* Clear out the dial buffer */
08279                p->dop.dialstr[0] = '\0';
08280                /* flash hookswitch */
08281                if ((ioctl(pbridge->subs[SUB_REAL].dfd,DAHDI_HOOK,&func) == -1) && (errno != EINPROGRESS)) {
08282                   ast_log(LOG_WARNING, "Unable to flash external trunk on channel %s: %s\n",
08283                      nbridge->name, strerror(errno));
08284                }
08285                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08286                unalloc_sub(p, SUB_THREEWAY);
08287                p->owner = p->subs[SUB_REAL].owner;
08288                if (ast_bridged_channel(p->subs[SUB_REAL].owner))
08289                   ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
08290                ast_hangup(chan);
08291                goto quit;
08292             } else {
08293                tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08294                dahdi_wait_event(p->subs[idx].dfd);
08295                tone_zone_play_tone(p->subs[idx].dfd, -1);
08296                swap_subs(p, SUB_REAL, SUB_THREEWAY);
08297                unalloc_sub(p, SUB_THREEWAY);
08298                p->owner = p->subs[SUB_REAL].owner;
08299                ast_hangup(chan);
08300                goto quit;
08301             }
08302          } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
08303                      ((exten[0] != '*') || (strlen(exten) > 2))) {
08304             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);
08305             break;
08306          }
08307          if (!timeout)
08308             timeout = gendigittimeout;
08309          if (len && !ast_ignore_pattern(chan->context, exten))
08310             tone_zone_play_tone(p->subs[idx].dfd, -1);
08311       }
08312       break;
08313    case SIG_FXSLS:
08314    case SIG_FXSGS:
08315    case SIG_FXSKS:
08316 #ifdef HAVE_PRI
08317       if (p->pri) {
08318          /* This is a GR-303 trunk actually.  Wait for the first ring... */
08319          struct ast_frame *f;
08320          int res;
08321          time_t start;
08322 
08323          time(&start);
08324          ast_setstate(chan, AST_STATE_RING);
08325          while (time(NULL) < start + 3) {
08326             res = ast_waitfor(chan, 1000);
08327             if (res) {
08328                f = ast_read(chan);
08329                if (!f) {
08330                   ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
08331                   ast_hangup(chan);
08332                   goto quit;
08333                } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
08334                   res = 1;
08335                } else
08336                   res = 0;
08337                ast_frfree(f);
08338                if (res) {
08339                   ast_debug(1, "Got ring!\n");
08340                   res = 0;
08341                   break;
08342                }
08343             }
08344          }
08345       }
08346 #endif
08347       /* check for SMDI messages */
08348       if (p->use_smdi && p->smdi_iface) {
08349          smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
08350 
08351          if (smdi_msg != NULL) {
08352             ast_copy_string(chan->exten, smdi_msg->fwd_st, sizeof(chan->exten));
08353 
08354             if (smdi_msg->type == 'B')
08355                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "b");
08356             else if (smdi_msg->type == 'N')
08357                pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
08358 
08359             ast_debug(1, "Received SMDI message on %s\n", chan->name);
08360          } else {
08361             ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
08362          }
08363       }
08364 
08365       if (p->use_callerid && (p->cid_signalling == CID_SIG_SMDI && smdi_msg)) {
08366          number = smdi_msg->calling_st;
08367 
08368       /* If we want caller id, we're in a prering state due to a polarity reversal
08369        * and we're set to use a polarity reversal to trigger the start of caller id,
08370        * grab the caller id and wait for ringing to start... */
08371       } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
08372          /* If set to use DTMF CID signalling, listen for DTMF */
08373          if (p->cid_signalling == CID_SIG_DTMF) {
08374             int k = 0;
08375             cs = NULL;
08376             ast_debug(1, "Receiving DTMF cid on "
08377                "channel %s\n", chan->name);
08378             dahdi_setlinear(p->subs[idx].dfd, 0);
08379             res = 2000;
08380             for (;;) {
08381                struct ast_frame *f;
08382                res = ast_waitfor(chan, res);
08383                if (res <= 0) {
08384                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08385                      "Exiting simple switch\n");
08386                   ast_hangup(chan);
08387                   goto quit;
08388                }
08389                f = ast_read(chan);
08390                if (!f)
08391                   break;
08392                if (f->frametype == AST_FRAME_DTMF) {
08393                   dtmfbuf[k++] = f->subclass;
08394                   ast_debug(1, "CID got digit '%c'\n", f->subclass);
08395                   res = 2000;
08396                }
08397                ast_frfree(f);
08398                if (chan->_state == AST_STATE_RING ||
08399                   chan->_state == AST_STATE_RINGING)
08400                   break; /* Got ring */
08401             }
08402             dtmfbuf[k] = '\0';
08403             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08404             /* Got cid and ring. */
08405             ast_debug(1, "CID got string '%s'\n", dtmfbuf);
08406             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08407             ast_debug(1, "CID is '%s', flags %d\n",
08408                dtmfcid, flags);
08409             /* If first byte is NULL, we have no cid */
08410             if (!ast_strlen_zero(dtmfcid))
08411                number = dtmfcid;
08412             else
08413                number = NULL;
08414          /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08415          } else if ((p->cid_signalling == CID_SIG_V23) || (p->cid_signalling == CID_SIG_V23_JP)) {
08416             cs = callerid_new(p->cid_signalling);
08417             if (cs) {
08418                samples = 0;
08419 #if 1
08420                bump_gains(p);
08421 #endif
08422                /* Take out of linear mode for Caller*ID processing */
08423                dahdi_setlinear(p->subs[idx].dfd, 0);
08424 
08425                /* First we wait and listen for the Caller*ID */
08426                for (;;) {
08427                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08428                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08429                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08430                      callerid_free(cs);
08431                      ast_hangup(chan);
08432                      goto quit;
08433                   }
08434                   if (i & DAHDI_IOMUX_SIGEVENT) {
08435                      res = dahdi_get_event(p->subs[idx].dfd);
08436                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08437                      if (res == DAHDI_EVENT_NOALARM) {
08438                         p->inalarm = 0;
08439                      }
08440 
08441                      if (p->cid_signalling == CID_SIG_V23_JP) {
08442                         if (res == DAHDI_EVENT_RINGBEGIN) {
08443                            res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
08444                            usleep(1);
08445                         }
08446                      } else {
08447                         res = 0;
08448                         break;
08449                      }
08450                   } else if (i & DAHDI_IOMUX_READ) {
08451                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08452                      if (res < 0) {
08453                         if (errno != ELAST) {
08454                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08455                            callerid_free(cs);
08456                            ast_hangup(chan);
08457                            goto quit;
08458                         }
08459                         break;
08460                      }
08461                      samples += res;
08462 
08463                      if (p->cid_signalling == CID_SIG_V23_JP) {
08464                         res = callerid_feed_jp(cs, buf, res, AST_LAW(p));
08465                      } else {
08466                         res = callerid_feed(cs, buf, res, AST_LAW(p));
08467                      }
08468 
08469                      if (res < 0) {
08470                         ast_log(LOG_WARNING, "CallerID feed failed on channel '%s'\n", chan->name);
08471                         break;
08472                      } else if (res)
08473                         break;
08474                      else if (samples > (8000 * 10))
08475                         break;
08476                   }
08477                }
08478                if (res == 1) {
08479                   callerid_get(cs, &name, &number, &flags);
08480                   ast_log(LOG_NOTICE, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08481                }
08482 
08483                if (p->cid_signalling == CID_SIG_V23_JP) {
08484                   res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
08485                   usleep(1);
08486                   res = 4000;
08487                } else {
08488 
08489                   /* Finished with Caller*ID, now wait for a ring to make sure there really is a call coming */
08490                   res = 2000;
08491                }
08492 
08493                for (;;) {
08494                   struct ast_frame *f;
08495                   res = ast_waitfor(chan, res);
08496                   if (res <= 0) {
08497                      ast_log(LOG_WARNING, "CID timed out waiting for ring. "
08498                         "Exiting simple switch\n");
08499                      ast_hangup(chan);
08500                      goto quit;
08501                   }
08502                   if (!(f = ast_read(chan))) {
08503                      ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
08504                      ast_hangup(chan);
08505                      goto quit;
08506                   }
08507                   ast_frfree(f);
08508                   if (chan->_state == AST_STATE_RING ||
08509                      chan->_state == AST_STATE_RINGING)
08510                      break; /* Got ring */
08511                }
08512 
08513                /* We must have a ring by now, so, if configured, lets try to listen for
08514                 * distinctive ringing */
08515                if (p->usedistinctiveringdetection) {
08516                   len = 0;
08517                   distMatches = 0;
08518                   /* Clear the current ring data array so we dont have old data in it. */
08519                   for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08520                      curRingData[receivedRingT] = 0;
08521                   receivedRingT = 0;
08522                   counter = 0;
08523                   counter1 = 0;
08524                   /* Check to see if context is what it should be, if not set to be. */
08525                   if (strcmp(p->context,p->defcontext) != 0) {
08526                      ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08527                      ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08528                   }
08529 
08530                   for (;;) {
08531                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08532                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08533                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08534                         callerid_free(cs);
08535                         ast_hangup(chan);
08536                         goto quit;
08537                      }
08538                      if (i & DAHDI_IOMUX_SIGEVENT) {
08539                         res = dahdi_get_event(p->subs[idx].dfd);
08540                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08541                         if (res == DAHDI_EVENT_NOALARM) {
08542                            p->inalarm = 0;
08543                         }
08544                         res = 0;
08545                         /* Let us detect distinctive ring */
08546 
08547                         curRingData[receivedRingT] = p->ringt;
08548 
08549                         if (p->ringt < p->ringt_base/2)
08550                            break;
08551                         /* Increment the ringT counter so we can match it against
08552                            values in chan_dahdi.conf for distinctive ring */
08553                         if (++receivedRingT == ARRAY_LEN(curRingData))
08554                            break;
08555                      } else if (i & DAHDI_IOMUX_READ) {
08556                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
08557                         if (res < 0) {
08558                            if (errno != ELAST) {
08559                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08560                               callerid_free(cs);
08561                               ast_hangup(chan);
08562                               goto quit;
08563                            }
08564                            break;
08565                         }
08566                         if (p->ringt)
08567                            p->ringt--;
08568                         if (p->ringt == 1) {
08569                            res = -1;
08570                            break;
08571                         }
08572                      }
08573                   }
08574                      /* this only shows up if you have n of the dring patterns filled in */
08575                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08576                   for (counter = 0; counter < 3; counter++) {
08577                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08578                      channel */
08579                      distMatches = 0;
08580                      for (counter1 = 0; counter1 < 3; counter1++) {
08581                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08582                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
08583                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08584                            curRingData[counter1]);
08585                            distMatches++;
08586                         } else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08587                               curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08588                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08589                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08590                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08591                            distMatches++;
08592                         }
08593                      }
08594 
08595                      if (distMatches == 3) {
08596                         /* The ring matches, set the context to whatever is for distinctive ring.. */
08597                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08598                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08599                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08600                         break;
08601                      }
08602                   }
08603                }
08604                /* Restore linear mode (if appropriate) for Caller*ID processing */
08605                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08606 #if 1
08607                restore_gains(p);
08608 #endif
08609             } else
08610                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08611          } else {
08612             ast_log(LOG_WARNING, "Channel %s in prering "
08613                "state, but I have nothing to do. "
08614                "Terminating simple switch, should be "
08615                "restarted by the actual ring.\n",
08616                chan->name);
08617             ast_hangup(chan);
08618             goto quit;
08619          }
08620       } else if (p->use_callerid && p->cid_start == CID_START_RING) {
08621          if (p->cid_signalling == CID_SIG_DTMF) {
08622             int k = 0;
08623             cs = NULL;
08624             dahdi_setlinear(p->subs[idx].dfd, 0);
08625             res = 2000;
08626             for (;;) {
08627                struct ast_frame *f;
08628                res = ast_waitfor(chan, res);
08629                if (res <= 0) {
08630                   ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
08631                      "Exiting simple switch\n");
08632                   ast_hangup(chan);
08633                   return NULL;
08634                }
08635                f = ast_read(chan);
08636                if (f->frametype == AST_FRAME_DTMF) {
08637                   dtmfbuf[k++] = f->subclass;
08638                   ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
08639                   res = 2000;
08640                }
08641                ast_frfree(f);
08642 
08643                if (p->ringt_base == p->ringt)
08644                   break;
08645             }
08646             dtmfbuf[k] = '\0';
08647             dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08648             /* Got cid and ring. */
08649             callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
08650             ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
08651                dtmfcid, flags);
08652             /* If first byte is NULL, we have no cid */
08653             if (!ast_strlen_zero(dtmfcid))
08654                number = dtmfcid;
08655             else
08656                number = NULL;
08657             /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
08658          } else {
08659             /* FSK Bell202 callerID */
08660             cs = callerid_new(p->cid_signalling);
08661             if (cs) {
08662 #if 1
08663                bump_gains(p);
08664 #endif
08665                samples = 0;
08666                len = 0;
08667                distMatches = 0;
08668                /* Clear the current ring data array so we dont have old data in it. */
08669                for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
08670                   curRingData[receivedRingT] = 0;
08671                receivedRingT = 0;
08672                counter = 0;
08673                counter1 = 0;
08674                /* Check to see if context is what it should be, if not set to be. */
08675                if (strcmp(p->context,p->defcontext) != 0) {
08676                   ast_copy_string(p->context, p->defcontext, sizeof(p->context));
08677                   ast_copy_string(chan->context,p->defcontext,sizeof(chan->context));
08678                }
08679 
08680                /* Take out of linear mode for Caller*ID processing */
08681                dahdi_setlinear(p->subs[idx].dfd, 0);
08682                for (;;) {
08683                   i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08684                   if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08685                      ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08686                      callerid_free(cs);
08687                      ast_hangup(chan);
08688                      goto quit;
08689                   }
08690                   if (i & DAHDI_IOMUX_SIGEVENT) {
08691                      res = dahdi_get_event(p->subs[idx].dfd);
08692                      ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08693                      if (res == DAHDI_EVENT_NOALARM) {
08694                         p->inalarm = 0;
08695                      }
08696                      /* If we get a PR event, they hung up while processing calerid */
08697                      if ( res == DAHDI_EVENT_POLARITY && p->hanguponpolarityswitch && p->polarity == POLARITY_REV) {
08698                         ast_log(LOG_DEBUG, "Hanging up due to polarity reversal on channel %d while detecting callerid\n", p->channel);
08699                         p->polarity = POLARITY_IDLE;
08700                         callerid_free(cs);
08701                         ast_hangup(chan);
08702                         goto quit;
08703                      }
08704                      res = 0;
08705                      /* Let us detect callerid when the telco uses distinctive ring */
08706 
08707                      curRingData[receivedRingT] = p->ringt;
08708 
08709                      if (p->ringt < p->ringt_base/2)
08710                         break;
08711                      /* Increment the ringT counter so we can match it against
08712                         values in chan_dahdi.conf for distinctive ring */
08713                      if (++receivedRingT == ARRAY_LEN(curRingData))
08714                         break;
08715                   } else if (i & DAHDI_IOMUX_READ) {
08716                      res = read(p->subs[idx].dfd, buf, sizeof(buf));
08717                      if (res < 0) {
08718                         if (errno != ELAST) {
08719                            ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08720                            callerid_free(cs);
08721                            ast_hangup(chan);
08722                            goto quit;
08723                         }
08724                         break;
08725                      }
08726                      if (p->ringt)
08727                         p->ringt--;
08728                      if (p->ringt == 1) {
08729                         res = -1;
08730                         break;
08731                      }
08732                      samples += res;
08733                      res = callerid_feed(cs, buf, res, AST_LAW(p));
08734                      if (res < 0) {
08735                         ast_log(LOG_WARNING, "CallerID feed failed: %s\n", strerror(errno));
08736                         break;
08737                      } else if (res)
08738                         break;
08739                      else if (samples > (8000 * 10))
08740                         break;
08741                   }
08742                }
08743                if (res == 1) {
08744                   callerid_get(cs, &name, &number, &flags);
08745                   ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
08746                }
08747                if (distinctiveringaftercid == 1) {
08748                   /* Clear the current ring data array so we dont have old data in it. */
08749                   for (receivedRingT = 0; receivedRingT < 3; receivedRingT++) {
08750                      curRingData[receivedRingT] = 0;
08751                   }
08752                   receivedRingT = 0;
08753                   ast_verb(3, "Detecting post-CID distinctive ring\n");
08754                   for (;;) {
08755                      i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
08756                      if ((res = ioctl(p->subs[idx].dfd, DAHDI_IOMUX, &i))) {
08757                         ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
08758                         callerid_free(cs);
08759                         ast_hangup(chan);
08760                         goto quit;
08761                      }
08762                      if (i & DAHDI_IOMUX_SIGEVENT) {
08763                         res = dahdi_get_event(p->subs[idx].dfd);
08764                         ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
08765                         if (res == DAHDI_EVENT_NOALARM) {
08766                            p->inalarm = 0;
08767                         }
08768                         res = 0;
08769                         /* Let us detect callerid when the telco uses distinctive ring */
08770 
08771                         curRingData[receivedRingT] = p->ringt;
08772 
08773                         if (p->ringt < p->ringt_base/2)
08774                            break;
08775                         /* Increment the ringT counter so we can match it against
08776                            values in chan_dahdi.conf for distinctive ring */
08777                         if (++receivedRingT == ARRAY_LEN(curRingData))
08778                            break;
08779                      } else if (i & DAHDI_IOMUX_READ) {
08780                         res = read(p->subs[idx].dfd, buf, sizeof(buf));
08781                         if (res < 0) {
08782                            if (errno != ELAST) {
08783                               ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
08784                               callerid_free(cs);
08785                               ast_hangup(chan);
08786                               goto quit;
08787                            }
08788                            break;
08789                         }
08790                      if (p->ringt)
08791                         p->ringt--;
08792                         if (p->ringt == 1) {
08793                            res = -1;
08794                            break;
08795                         }
08796                      }
08797                   }
08798                }
08799                if (p->usedistinctiveringdetection) {
08800                   /* this only shows up if you have n of the dring patterns filled in */
08801                   ast_verb(3, "Detected ring pattern: %d,%d,%d\n",curRingData[0],curRingData[1],curRingData[2]);
08802 
08803                   for (counter = 0; counter < 3; counter++) {
08804                      /* Check to see if the rings we received match any of the ones in chan_dahdi.conf for this
08805                      channel */
08806                      /* this only shows up if you have n of the dring patterns filled in */
08807                      ast_verb(3, "Checking %d,%d,%d\n",
08808                            p->drings.ringnum[counter].ring[0],
08809                            p->drings.ringnum[counter].ring[1],
08810                            p->drings.ringnum[counter].ring[2]);
08811                      distMatches = 0;
08812                      for (counter1 = 0; counter1 < 3; counter1++) {
08813                         ast_verb(3, "Ring pattern check range: %d\n", p->drings.ringnum[counter].range);
08814                         if (p->drings.ringnum[counter].ring[counter1] == -1) {
08815                            ast_verb(3, "Pattern ignore (-1) detected, so matching pattern %d regardless.\n",
08816                            curRingData[counter1]);
08817                            distMatches++;
08818                         }
08819                         else if (curRingData[counter1] <= (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range) &&
08820                            curRingData[counter1] >= (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range)) {
08821                            ast_verb(3, "Ring pattern matched in range: %d to %d\n",
08822                            (p->drings.ringnum[counter].ring[counter1] - p->drings.ringnum[counter].range),
08823                            (p->drings.ringnum[counter].ring[counter1] + p->drings.ringnum[counter].range));
08824                            distMatches++;
08825                         }
08826                      }
08827                      if (distMatches == 3) {
08828                         /* The ring matches, set the context to whatever is for distinctive ring.. */
08829                         ast_copy_string(p->context, p->drings.ringContext[counter].contextData, sizeof(p->context));
08830                         ast_copy_string(chan->context, p->drings.ringContext[counter].contextData, sizeof(chan->context));
08831                         ast_verb(3, "Distinctive Ring matched context %s\n",p->context);
08832                         break;
08833                      }
08834                   }
08835                }
08836                /* Restore linear mode (if appropriate) for Caller*ID processing */
08837                dahdi_setlinear(p->subs[idx].dfd, p->subs[idx].linear);
08838 #if 1
08839                restore_gains(p);
08840 #endif
08841                if (res < 0) {
08842                   ast_log(LOG_WARNING, "CallerID returned with error on channel '%s'\n", chan->name);
08843                }
08844             } else
08845                ast_log(LOG_WARNING, "Unable to get caller ID space\n");
08846          }
08847       } else
08848          cs = NULL;
08849 
08850       if (number)
08851          ast_shrink_phone_number(number);
08852       ast_set_callerid(chan, number, name, number);
08853 
08854       if (smdi_msg)
08855          ASTOBJ_UNREF(smdi_msg, ast_smdi_md_message_destroy);
08856 
08857       if (cs)
08858          callerid_free(cs);
08859       /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
08860       if (flags & CID_MSGWAITING) {
08861          ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
08862          notify_message(p->mailbox, 1);
08863          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
08864          if (p->mwimonitor_rpas) {
08865             ast_hangup(chan);
08866             return NULL;
08867          }
08868       } else if (flags & CID_NOMSGWAITING) {
08869          ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
08870          notify_message(p->mailbox, 0);
08871          /* If generated using Ring Pulse Alert, then ring has been answered as a call and needs to be hungup */
08872          if (p->mwimonitor_rpas) {
08873             ast_hangup(chan);
08874             return NULL;
08875          }
08876       }
08877 
08878       ast_setstate(chan, AST_STATE_RING);
08879       chan->rings = 1;
08880       p->ringt = p->ringt_base;
08881       res = ast_pbx_run(chan);
08882       if (res) {
08883          ast_hangup(chan);
08884          ast_log(LOG_WARNING, "PBX exited non-zero\n");
08885       }
08886       goto quit;
08887    default:
08888       ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
08889       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08890       if (res < 0)
08891             ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08892    }
08893    res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
08894    if (res < 0)
08895          ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
08896    ast_hangup(chan);
08897 quit:
08898    ast_mutex_lock(&ss_thread_lock);
08899    ss_thread_count--;
08900    ast_cond_signal(&ss_thread_complete);
08901    ast_mutex_unlock(&ss_thread_lock);
08902    return NULL;
08903 }

static int start_pri ( struct dahdi_pri pri  )  [static]

Definition at line 13537 of file chan_dahdi.c.

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

Referenced by setup_dahdi().

13538 {
13539    int res, x;
13540    struct dahdi_params p;
13541    struct dahdi_bufferinfo bi;
13542    struct dahdi_spaninfo si;
13543    int i;
13544 
13545    for (i = 0; i < NUM_DCHANS; i++) {
13546       if (!pri->dchannels[i])
13547          break;
13548       pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
13549       x = pri->dchannels[i];
13550       if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
13551          ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
13552          return -1;
13553       }
13554       memset(&p, 0, sizeof(p));
13555       res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
13556       if (res) {
13557          dahdi_close_pri_fd(pri, i);
13558          ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
13559          return -1;
13560       }
13561       if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
13562          dahdi_close_pri_fd(pri, i);
13563          ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
13564          return -1;
13565       }
13566       memset(&si, 0, sizeof(si));
13567       res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
13568       if (res) {
13569          dahdi_close_pri_fd(pri, i);
13570          ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
13571       }
13572       if (!si.alarms)
13573          pri->dchanavail[i] |= DCHAN_NOTINALARM;
13574       else
13575          pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
13576       memset(&bi, 0, sizeof(bi));
13577       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
13578       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
13579       bi.numbufs = 32;
13580       bi.bufsize = 1024;
13581       if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
13582          ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
13583          dahdi_close_pri_fd(pri, i);
13584          return -1;
13585       }
13586       switch (pri->sig) {
13587       case SIG_BRI:
13588          pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
13589          break;
13590       case SIG_BRI_PTMP:
13591          pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
13592          break;
13593       default:
13594          pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
13595          break;
13596       }
13597       /* Force overlap dial if we're doing GR-303! */
13598       if (pri->switchtype == PRI_SWITCH_GR303_TMC)
13599          pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
13600       pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
13601 #ifdef HAVE_PRI_PROG_W_CAUSE
13602       pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
13603 #endif
13604 #ifdef HAVE_PRI_INBANDDISCONNECT
13605       pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
13606 #endif
13607       /* Enslave to master if appropriate */
13608       if (i)
13609          pri_enslave(pri->dchans[0], pri->dchans[i]);
13610       if (!pri->dchans[i]) {
13611          dahdi_close_pri_fd(pri, i);
13612          ast_log(LOG_ERROR, "Unable to create PRI structure\n");
13613          return -1;
13614       }
13615       pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
13616       pri_set_nsf(pri->dchans[i], pri->nsf);
13617 #ifdef PRI_GETSET_TIMERS
13618       for (x = 0; x < PRI_MAX_TIMERS; x++) {
13619          if (pritimers[x] != 0)
13620             pri_set_timer(pri->dchans[i], x, pritimers[x]);
13621       }
13622 #endif
13623    }
13624    /* Assume primary is the one we use */
13625    pri->pri = pri->dchans[0];
13626    pri->resetpos = -1;
13627    if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
13628       for (i = 0; i < NUM_DCHANS; i++) {
13629          if (!pri->dchannels[i])
13630             break;
13631          dahdi_close_pri_fd(pri, i);
13632       }
13633       ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
13634       return -1;
13635    }
13636    return 0;
13637 }

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

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

02063 {
02064    int tchan;
02065    int tinthreeway;
02066    struct ast_channel *towner;
02067 
02068    ast_debug(1, "Swapping %d and %d\n", a, b);
02069 
02070    tchan = p->subs[a].chan;
02071    towner = p->subs[a].owner;
02072    tinthreeway = p->subs[a].inthreeway;
02073 
02074    p->subs[a].chan = p->subs[b].chan;
02075    p->subs[a].owner = p->subs[b].owner;
02076    p->subs[a].inthreeway = p->subs[b].inthreeway;
02077 
02078    p->subs[b].chan = tchan;
02079    p->subs[b].owner = towner;
02080    p->subs[b].inthreeway = tinthreeway;
02081 
02082    if (p->subs[a].owner)
02083       ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
02084    if (p->subs[b].owner)
02085       ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
02086    wakeup_sub(p, a, NULL);
02087    wakeup_sub(p, b, NULL);
02088 }

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

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

02213 {
02214    if (!x) {
02215       ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
02216       return -1;
02217    }
02218    ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
02219    dahdi_close_sub(p, x);
02220    p->subs[x].linear = 0;
02221    p->subs[x].chan = 0;
02222    p->subs[x].owner = NULL;
02223    p->subs[x].inthreeway = 0;
02224    p->polarity = POLARITY_IDLE;
02225    memset(&p->subs[x].curconf, 0, sizeof(p->subs[x].curconf));
02226    return 0;
02227 }

static int unload_module ( void   )  [static]

Definition at line 15932 of file chan_dahdi.c.

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

15933 {
15934 #if defined(HAVE_PRI) || defined(HAVE_SS7)
15935    int y;
15936 #endif
15937 #ifdef HAVE_PRI
15938    for (y = 0; y < NUM_SPANS; y++)
15939       ast_mutex_destroy(&pris[y].lock);
15940 #endif
15941 #ifdef HAVE_SS7
15942    for (y = 0; y < NUM_SPANS; y++)
15943       ast_mutex_destroy(&linksets[y].lock);
15944 #endif /* HAVE_SS7 */
15945    return __unload_module();
15946 }

static int update_conf ( struct dahdi_pvt p  )  [static]

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

02605 {
02606    int needconf = 0;
02607    int x;
02608    int useslavenative;
02609    struct dahdi_pvt *slave = NULL;
02610 
02611    useslavenative = isslavenative(p, &slave);
02612    /* Start with the obvious, general stuff */
02613    for (x = 0; x < 3; x++) {
02614       /* Look for three way calls */
02615       if ((p->subs[x].dfd > -1) && p->subs[x].inthreeway) {
02616          conf_add(p, &p->subs[x], x, 0);
02617          needconf++;
02618       } else {
02619          conf_del(p, &p->subs[x], x);
02620       }
02621    }
02622    /* If we have a slave, add him to our conference now. or DAX
02623       if this is slave native */
02624    for (x = 0; x < MAX_SLAVES; x++) {
02625       if (p->slaves[x]) {
02626          if (useslavenative)
02627             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p));
02628          else {
02629             conf_add(p, &p->slaves[x]->subs[SUB_REAL], SUB_REAL, 0);
02630             needconf++;
02631          }
02632       }
02633    }
02634    /* If we're supposed to be in there, do so now */
02635    if (p->inconference && !p->subs[SUB_REAL].inthreeway) {
02636       if (useslavenative)
02637          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(slave));
02638       else {
02639          conf_add(p, &p->subs[SUB_REAL], SUB_REAL, 0);
02640          needconf++;
02641       }
02642    }
02643    /* If we have a master, add ourselves to his conference */
02644    if (p->master) {
02645       if (isslavenative(p->master, NULL)) {
02646          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, GET_CHANNEL(p->master));
02647       } else {
02648          conf_add(p->master, &p->subs[SUB_REAL], SUB_REAL, 0);
02649       }
02650    }
02651    if (!needconf) {
02652       /* Nobody is left (or should be left) in our conference.
02653          Kill it. */
02654       p->confno = -1;
02655    }
02656    ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
02657    return 0;
02658 }

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

Definition at line 1520 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_pri::lock, dahdi_subchannel::owner, and dahdi_pvt::subs.

Referenced by pri_fixup_principle(), and swap_subs().

01521 {
01522 #ifdef HAVE_PRI
01523    if (pri)
01524       ast_mutex_unlock(&pri->lock);
01525 #endif
01526    for (;;) {
01527       if (p->subs[a].owner) {
01528          if (ast_channel_trylock(p->subs[a].owner)) {
01529             DEADLOCK_AVOIDANCE(&p->lock);
01530          } else {
01531             ast_queue_frame(p->subs[a].owner, &ast_null_frame);
01532             ast_channel_unlock(p->subs[a].owner);
01533             break;
01534          }
01535       } else
01536          break;
01537    }
01538 #ifdef HAVE_PRI
01539    if (pri)
01540       ast_mutex_lock(&pri->lock);
01541 #endif
01542 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Comedian Mail (Voicemail System)" , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 17500 of file chan_dahdi.c.

int alarm

Definition at line 2367 of file chan_dahdi.c.

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

Referenced by alarm2str().

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

Definition at line 1495 of file chan_dahdi.c.

Definition at line 17500 of file chan_dahdi.c.

struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] [static]

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

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

Definition at line 238 of file chan_dahdi.c.

int cur_adjpointcode = -1 [static]

Definition at line 456 of file chan_dahdi.c.

int cur_cicbeginswith = -1 [static]

Definition at line 455 of file chan_dahdi.c.

int cur_defaultdpc = -1 [static]

Definition at line 458 of file chan_dahdi.c.

int cur_linkset = -1 [static]

Definition at line 453 of file chan_dahdi.c.

int cur_networkindicator = -1 [static]

Definition at line 457 of file chan_dahdi.c.

int cur_pointcode = -1 [static]

Definition at line 454 of file chan_dahdi.c.

int cur_ss7type = -1 [static]

Definition at line 452 of file chan_dahdi.c.

struct ast_cli_entry dahdi_cli[] [static]

Definition at line 15169 of file chan_dahdi.c.

struct ast_cli_entry dahdi_pri_cli[] [static]

Definition at line 13943 of file chan_dahdi.c.

char* dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility" [static]

Definition at line 3960 of file chan_dahdi.c.

struct ast_cli_entry dahdi_ss7_cli[] [static]

Definition at line 15838 of file chan_dahdi.c.

struct ast_channel_tech dahdi_tech [static]

Definition at line 1401 of file chan_dahdi.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 173 of file chan_dahdi.c.

char defaultcic[64] = "" [static]

Definition at line 296 of file chan_dahdi.c.

char defaultozz[64] = "" [static]

Definition at line 297 of file chan_dahdi.c.

int distinctiveringaftercid = 0 [static]

Definition at line 310 of file chan_dahdi.c.

char* events[] [static]

Definition at line 2344 of file chan_dahdi.c.

int firstdigittimeout = 16000 [static]

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

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

struct ast_jb_conf global_jbconf [static]

Definition at line 181 of file chan_dahdi.c.

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

int ifcount = 0 [static]

Definition at line 342 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 161 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 332 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 354 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 350 of file chan_dahdi.c.

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

int mwilevel = 512 [static]

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

int mwisend_rpas = 0 [static]

Definition at line 304 of file chan_dahdi.c.

char* name

Definition at line 2368 of file chan_dahdi.c.

int num_cadence = 4 [static]

Definition at line 1473 of file chan_dahdi.c.

int num_restart_pending = 0 [static]

Definition at line 359 of file chan_dahdi.c.

int numbufs = 4 [static]

Definition at line 312 of file chan_dahdi.c.

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

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

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

Definition at line 307 of file chan_dahdi.c.

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

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

struct dahdi_pvt* round_robin[32]

Definition at line 1428 of file chan_dahdi.c.

Definition at line 355 of file chan_dahdi.c.

int ss_thread_count = 0 [static]

Definition at line 358 of file chan_dahdi.c.

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

Definition at line 356 of file chan_dahdi.c.

Referenced by dahdi_restart(), and ss_thread().

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

Definition at line 600 of file chan_dahdi.c.

const char tdesc[] [static]

Definition at line 215 of file chan_dahdi.c.

int usedistinctiveringdetection = 0 [static]

Definition at line 309 of file chan_dahdi.c.

int user_has_defined_cadences = 0 [static]

Definition at line 1474 of file chan_dahdi.c.


Generated by  doxygen 1.6.2